# yapf: disable
# isort: skip_file
# ruff: noqa



# To not generate code where imported names might get shadowed when a user
# specifies some name in their proto file to be the same as one of our imported
# names, (for example: a request field named `uuid`) we bind all imports to
# names that are forbidden in 'proto' and therefore can never collide.

# Standard imports.
from __future__ import annotations as IMPORT_future_annotations

# The following MUST appear before the rest of the imports, since those imports
# may be invalid (broken) if the generated code is mismatched with the installed
# libraries.
import rebootdev.versioning as IMPORT_reboot_versioning
IMPORT_reboot_versioning.check_generated_code_compatible("0.37.1")

# ATTENTION: no types in this file should be imported with their unqualified
#            name (e.g. `from typing import Any`). That would cause clashes
#            with user-defined methods that have the same name. Use
#            fully-qualified names (e.g. `IMPORT_typing.Any`) instead.
import asyncio as IMPORT_asyncio
import builtins as IMPORT_builtins
import contextvars as IMPORT_contextvars
import dataclasses as IMPORT_dataclasses
import google.protobuf.descriptor as IMPORT_google_protobuf_descriptor
import google.protobuf.json_format as IMPORT_google_protobuf_json_format
import google.protobuf.message as IMPORT_google_protobuf_message
import grpc as IMPORT_grpc
import grpc_status._async as IMPORT_rpc_status_async
from grpc_status import rpc_status as IMPORT_rpc_status_sync
import json as IMPORT_json
import os as IMPORT_os
import traceback as IMPORT_traceback
import uuid as IMPORT_uuid
import pickle as IMPORT_pickle
import rebootdev as IMPORT_rebootdev
import log.log as IMPORT_log_log   # type: ignore[import]
import typing as IMPORT_typing
import rebootdev.aio.backoff as IMPORT_reboot_aio_backoff
import functools as IMPORT_functools
from abc import abstractmethod as IMPORT_abc_abstractmethod
from datetime import datetime as IMPORT_datetime_datetime
from datetime import timedelta as IMPORT_datetime_timedelta
from datetime import timezone as IMPORT_datetime_timezone
from google.protobuf import timestamp_pb2 as IMPORT_google_protobuf_timestamp_pb2
from google.protobuf import wrappers_pb2 as IMPORT_google_protobuf_wrappers_pb2
import rebootdev.aio.tracing as IMPORT_reboot_aio_tracing
from google.rpc import status_pb2 as IMPORT_google_rpc_status_pb2
from tzlocal import get_localzone as IMPORT_tzlocal_get_localzone
import rebootdev.aio.call as IMPORT_reboot_aio_call
import rebootdev.aio.contexts as IMPORT_reboot_aio_contexts
import rebootdev.aio.headers as IMPORT_reboot_aio_headers
import rebootdev.aio.idempotency as IMPORT_reboot_aio_idempotency
import rebootdev.aio.internals.channel_manager as IMPORT_reboot_aio_internals_channel_manager
import rebootdev.aio.internals.middleware as IMPORT_reboot_aio_internals_middleware
import rebootdev.aio.internals.tasks_cache as IMPORT_reboot_aio_internals_tasks_cache
import rebootdev.aio.internals.tasks_dispatcher as IMPORT_reboot_aio_internals_tasks_dispatcher
import rebootdev.aio.placement as IMPORT_reboot_aio_placement
import rebootdev.aio.servicers as IMPORT_reboot_aio_servicers
import rebootdev.aio.state_managers as IMPORT_reboot_aio_state_managers
import rebootdev.aio.stubs as IMPORT_reboot_aio_stubs
import rebootdev.aio.tasks as IMPORT_reboot_aio_tasks
import rebootdev.aio.types as IMPORT_reboot_aio_types
import rebootdev.aio.external as IMPORT_reboot_aio_external
import rebootdev.aio.workflows as IMPORT_reboot_aio_workflows
import rebootdev.settings as IMPORT_reboot_settings
import rebootdev.nodejs.python as IMPORT_reboot_nodejs_python
from rebootdev.time import DateTimeWithTimeZone as IMPORT_reboot_time_DateTimeWithTimeZone
import rbt.v1alpha1 as IMPORT_rbt_v1alpha1
import rbt.v1alpha1.nodejs_pb2 as IMPORT_rbt_v1alpha1_nodejs_pb2
import google.protobuf.any_pb2 as IMPORT_google_protobuf_any_pb2

# User defined or referenced imports.
import google.protobuf.descriptor_pb2
import google.protobuf.empty_pb2
import rbt.mcp.v1.stream_pb2
import rbt.mcp.v1.stream_pb2_grpc
import rbt.v1alpha1.options_pb2
# Additionally re-export all messages and enums from the pb2 module.
from rbt.mcp.v1.stream_pb2 import (
    Event,
    PutRequest,
    PutResponse,
    ReplayRequest,
    ReplayResponse,
)

logger = IMPORT_log_log.get_logger(__name__)

############################ Legacy gRPC Servicers ############################
# This section is relevant (only) for servicers that implement a legacy gRPC
# service in a Reboot context. It is irrelevant to clients.

def MakeLegacyGrpcServiceable(
    # A legacy gRPC servicer type can't be more specific than `type`,
    # because legacy gRPC servicers (as generated by the gRPC `protoc`
    # plugin) do not share any common base class other than `object`.
    servicer_type: type
) -> IMPORT_reboot_aio_servicers.Serviceable:
    raise ValueError(f"Unknown legacy gRPC servicer type '{servicer_type}'")



############################ Reboot Servicer Middlewares ############################
# This section is relevant (only) for servicers implementing a Reboot servicer. It
# is irrelevant to clients, except for the fact that some clients are _also_ such
# servicers.

# For internal calls, we can use a magic token to bypass token verification and
# authorization checks. The token provides no auth information (e.g.,
# `context.auth is None`).
__internal_magic_token__: str = f'internal-{str(IMPORT_uuid.uuid4())}'

class StreamServicerMiddleware(IMPORT_reboot_aio_internals_middleware.Middleware):

    def __init__(
        self,
        *,
        servicer: StreamBaseServicer,
        application_id: IMPORT_reboot_aio_types.ApplicationId,
        consensus_id: IMPORT_reboot_aio_types.ConsensusId,
        state_manager: IMPORT_reboot_aio_state_managers.StateManager,
        placement_client: IMPORT_reboot_aio_placement.PlacementClient,
        channel_manager: IMPORT_reboot_aio_internals_channel_manager._ChannelManager,
        tasks_cache: IMPORT_reboot_aio_internals_tasks_cache.TasksCache,
        token_verifier: IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.token_verifiers.TokenVerifier],
        effect_validation: IMPORT_reboot_aio_contexts.EffectValidation,
        app_internal_api_key_secret: str,
        ready: IMPORT_asyncio.Event,
    ):
        super().__init__(
            application_id=application_id,
            consensus_id=consensus_id,
            state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            service_names = [
                IMPORT_reboot_aio_types.ServiceName("rbt.mcp.v1.StreamMethods"),
            ],
            placement_client=placement_client,
            channel_manager=channel_manager,
            effect_validation=effect_validation,
            app_internal_api_key_secret=app_internal_api_key_secret,
        )

        self._servicer = servicer
        self._state_manager = state_manager
        self.tasks_dispatcher = IMPORT_reboot_aio_internals_tasks_dispatcher.TasksDispatcher(
            application_id=application_id,
            dispatch=self.dispatch,
            tasks_cache=tasks_cache,
            ready=ready,
            complete_task=self._state_manager.complete_task,
        )

        # Store the type of each method's request so that stored requests can be
        # deserialized into the correct type.
        self.request_type_by_method_name: dict[str, type[IMPORT_google_protobuf_message.Message]] = {
            'Create': google.protobuf.empty_pb2.Empty,
            'Put': rbt.mcp.v1.stream_pb2.PutRequest,
            'Replay': rbt.mcp.v1.stream_pb2.ReplayRequest,
        }

        # Get authorizer, if any, converting from a rule if necessary.
        def convert_authorizer_rule_if_necessary(
            authorizer_or_rule: IMPORT_typing.Optional[
                IMPORT_rebootdev.aio.auth.authorizers.Authorizer | IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule
            ]
        ) -> IMPORT_rebootdev.aio.auth.authorizers.Authorizer:

            # If no authorizer or rule is provided, return the default
            # authorizer which allows if app internal or allows if in
            # dev mode (and logs some warnings to help the user
            # realize where they are missing authorization).
            if authorizer_or_rule is None:
                return IMPORT_rebootdev.aio.auth.authorizers.DefaultAuthorizer(
                    'Stream'
                )

            if isinstance(authorizer_or_rule, IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule):
                return StreamAuthorizer(
                    _default=authorizer_or_rule
                )

            return authorizer_or_rule

        self._authorizer = convert_authorizer_rule_if_necessary(
            servicer.authorizer()
        )

        # Create token verifier.
        self._token_verifier: IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.token_verifiers.TokenVerifier] = (
            servicer.token_verifier() or token_verifier
        )

        # Since users specify errors as proto messages they can't raise them
        # directly - to do so they have to use the `Aborted` wrapper, which will
        # hold the original proto message. On errors we'll need to check whether
        # such wrappers hold a proto message for a specified error, so we can
        # avoid retrying tasks that complete with a specified error.
        self._specified_errors_by_service_method_name: dict[str, list[str]] = {
        }


    def add_to_server(self, server: IMPORT_grpc.aio.Server) -> None:
        rbt.mcp.v1.stream_pb2_grpc.add_StreamMethodsServicer_to_server(
            self, server
        )

    async def inspect(self, state_ref: IMPORT_reboot_aio_types.StateRef) -> IMPORT_typing.AsyncIterator[IMPORT_google_protobuf_message.Message]:
        """Implementation of `Middleware.inspect()`."""
        context = self.create_context(
            headers=IMPORT_reboot_aio_headers.Headers(
                application_id=self.application_id,
                state_ref=state_ref,
            ),
            state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            method="inspect",
            context_type=IMPORT_reboot_aio_contexts.ReaderContext,
        )

        async with self._state_manager.streaming_reader_idempotency_key(
            context,
            self._servicer.__state_type__,
            authorize=None,
        ) as states:
            async for (state, idempotency_key) in states:
                yield state

    async def react_query(
        self,
        headers: IMPORT_reboot_aio_headers.Headers,
        method: str,
        request_bytes: bytes,
    ) -> IMPORT_typing.AsyncIterator[tuple[IMPORT_typing.Optional[IMPORT_google_protobuf_message.Message], list[IMPORT_uuid.UUID]]]:
        """Returns the response of calling 'method' given a message
        deserialized from the provided 'request_bytes' for each state
        update that creates a different response.

        # The caller (react.py) should have already ensured that this consensus
        # is authoritative for this traffic.
        assert self.placement_client.consensus_for_actor(
            headers.application_id,
            headers.state_ref,
        ) == self._consensus_id

        NOTE: only unary reader methods are supported."""
        # Need to define these up here since we can only do that once.
        last_response: IMPORT_typing.Optional[IMPORT_google_protobuf_message.Message] = None
        aggregated_idempotency_keys: list[IMPORT_uuid.UUID] = []
        if method == 'Create':
            # Invariant here is that users should not have called this
            # directly but only through code generated React
            # components which should not have been generated except
            # for valid method candidates.
            logger.warning(
                "Got a React query request with an invalid method name: "
                f"Method '{method}' is invalid for servicer Stream."
                "\n"
                "Do you have a browser tab open for an older version "
                "of this application, or for a different application all together?"
            )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.InvalidMethod(),
                message=
                    f"Method '{method}' is invalid"
            )
            yield  # Necessary for type checking.
        elif method == 'Put':
            # Invariant here is that users should not have called this
            # directly but only through code generated React
            # components which should not have been generated except
            # for valid method candidates.
            logger.warning(
                "Got a React query request with an invalid method name: "
                f"Method '{method}' is invalid for servicer Stream."
                "\n"
                "Do you have a browser tab open for an older version "
                "of this application, or for a different application all together?"
            )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.InvalidMethod(),
                message=
                    f"Method '{method}' is invalid"
            )
            yield  # Necessary for type checking.
        elif method == 'Replay':

            context = self.create_context(
                headers=headers,
                state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                method='Replay',
                context_type=IMPORT_reboot_aio_contexts.ReaderContext,
            )

            with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="Replay() (reactively)",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
            ):
                context.auth = await self._maybe_verify_token(
                    headers=headers, method='Replay'
                )

                request = rbt.mcp.v1.stream_pb2.ReplayRequest()
                request.ParseFromString(request_bytes)

                async with self._state_manager.reactively(
                    context,
                    self._servicer.__state_type__,
                    authorize=self._maybe_authorize(
                        method_name='rbt.mcp.v1.StreamMethods.Replay',
                        headers=headers,
                        auth=context.auth,
                        request=request,
                    ),
                ) as states:
                    async for (state, idempotency_keys) in states:

                        aggregated_idempotency_keys.extend(idempotency_keys)

                        # Note: This does not do any defensive copying currently:
                        # see https://github.com/reboot-dev/respect/issues/2636.
                        @IMPORT_reboot_aio_internals_middleware.maybe_run_function_twice_to_validate_effects
                        async def run__Replay(validating_effects: bool) -> IMPORT_google_protobuf_message.Message:
                            return await self.__Replay(
                                context,
                                state,
                                request,
                                validating_effects=validating_effects,
                            )

                        response = await run__Replay()

                        if last_response != response:
                            yield (response, aggregated_idempotency_keys)
                            last_response = response
                        else:
                            yield (None, aggregated_idempotency_keys)

                        aggregated_idempotency_keys.clear()
        else:
            logger.warning(
                "Got a React query request with an invalid method name: "
                f"Method '{method}' is invalid for servicer Stream."
                "\n"
                "Do you have a browser tab open for an older version "
                "of this application, or for a different application all together?"
            )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.InvalidMethod(),
                message=
                    f"Method '{method}' not found"
            )
            yield  # Unreachable but necessary for mypy.

    async def react_mutate(
        self,
        headers: IMPORT_reboot_aio_headers.Headers,
        method: str,
        request_bytes: bytes,
    ) -> IMPORT_google_protobuf_message.Message:
        """Returns the response of calling 'method' given a message
        deserialized from the provided 'request_bytes'."""
        if method == 'Create':
            request = google.protobuf.empty_pb2.Empty()
            request.ParseFromString(request_bytes)

            # NOTE: we automatically retry mutations that come through
            # React when we get a `IMPORT_grpc.StatusCode.UNAVAILABLE` to
            # match the retry logic we do in the React code generated
            # to handle lack/loss of connectivity.
            #
            # TODO(benh): revisit this decision if we ever see reason
            # to call `react_mutate()` from any place other than where
            # we're executing React (e.g., browser, next.js server
            # component, etc).
            call_backoff = IMPORT_reboot_aio_backoff.Backoff()
            while True:
                # We make a full-fledged gRPC call, so that if this traffic
                # was misrouted (i.e. this consensus is not authoritative
                # for the state), it will now go to the right place. The
                # receiving middleware will handle things like effect
                # validation and so forth.
                assert headers.application_id is not None  # Guaranteed by `Headers`.
                stub = rbt.mcp.v1.stream_pb2_grpc.StreamMethodsStub(
                    self.channel_manager.get_channel_to(
                        self.placement_client.address_for_actor(
                            headers.application_id,
                            headers.state_ref,
                        )
                    )
                )
                call = stub.Create(
                    request=request,
                    metadata=headers.to_grpc_metadata(),
                )
                try:
                    return await call
                except IMPORT_grpc.aio.AioRpcError as error:
                    if error.code() == IMPORT_grpc.StatusCode.UNAVAILABLE:
                        await call_backoff()
                        continue

                    # Reconstitute the error that the server threw, if it was a declared error.
                    status = await IMPORT_rpc_status_async.from_call(call)
                    if status is not None:
                        raise Stream.CreateAborted.from_status(
                            status
                        ) from None
                    raise Stream.CreateAborted.from_grpc_aio_rpc_error(
                        error
                     ) from None

        elif method == 'Put':
            request = rbt.mcp.v1.stream_pb2.PutRequest()
            request.ParseFromString(request_bytes)

            # NOTE: we automatically retry mutations that come through
            # React when we get a `IMPORT_grpc.StatusCode.UNAVAILABLE` to
            # match the retry logic we do in the React code generated
            # to handle lack/loss of connectivity.
            #
            # TODO(benh): revisit this decision if we ever see reason
            # to call `react_mutate()` from any place other than where
            # we're executing React (e.g., browser, next.js server
            # component, etc).
            call_backoff = IMPORT_reboot_aio_backoff.Backoff()
            while True:
                # We make a full-fledged gRPC call, so that if this traffic
                # was misrouted (i.e. this consensus is not authoritative
                # for the state), it will now go to the right place. The
                # receiving middleware will handle things like effect
                # validation and so forth.
                assert headers.application_id is not None  # Guaranteed by `Headers`.
                stub = rbt.mcp.v1.stream_pb2_grpc.StreamMethodsStub(
                    self.channel_manager.get_channel_to(
                        self.placement_client.address_for_actor(
                            headers.application_id,
                            headers.state_ref,
                        )
                    )
                )
                call = stub.Put(
                    request=request,
                    metadata=headers.to_grpc_metadata(),
                )
                try:
                    return await call
                except IMPORT_grpc.aio.AioRpcError as error:
                    if error.code() == IMPORT_grpc.StatusCode.UNAVAILABLE:
                        await call_backoff()
                        continue

                    # Reconstitute the error that the server threw, if it was a declared error.
                    status = await IMPORT_rpc_status_async.from_call(call)
                    if status is not None:
                        raise Stream.PutAborted.from_status(
                            status
                        ) from None
                    raise Stream.PutAborted.from_grpc_aio_rpc_error(
                        error
                     ) from None

        elif method == 'Replay':
            # Invariant here is that users should not have called this
            # directly but only through code generated React
            # components which should not have been generated except
            # for valid method candidates.
            logger.warning(
                "Got a react mutate request with an invalid method name: "
                "Method 'Replay' is invalid for servicer Stream."
                "\n"
                "Do you have an old browser tab still open for an older version "
                "of this application, or a different application all together?"
            )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.InvalidMethod(),
                message=f"Method '{method}' is invalid"
            )
        else:
            logger.warning(
                "Got a react mutate request with an invalid method name: "
                f"Method '{method}' is invalid for servicer Stream."
                "\n"
                "Do you have an old browser tab still open for an older version "
                "of this application, or a different application all together?"
            )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.InvalidMethod(),
                message=
                    f"Method '{method}' not found"
            )

    async def dispatch(
        self,
        task: IMPORT_reboot_aio_tasks.TaskEffect,
        *,
        only_validate: bool = False,
        on_loop_iteration: IMPORT_reboot_aio_internals_tasks_dispatcher.OnLoopIterationCallable = (lambda iteration, next_iteration_schedule: None),
    ) -> IMPORT_reboot_aio_internals_tasks_dispatcher.TaskResponseOrError:
        """Dispatches the tasks to execute unless 'only_validate' is set to
        true, in which case just ensures that the task actually exists.
        Note that this function will be called *by* tasks_dispatcher; it will
        not itself call into tasks_dispatcher."""

        if 'Create' == task.method_name:
            if only_validate:
                # TODO(benh): validate 'task.request' is correct type.
                return google.protobuf.empty_pb2.Empty()

            # Use an inline method to create a new scope, so that we can use
            # variable names like `context` and `effects` in multiple branches
            # in this code (notably when there are multiple task types) without
            # hitting a mypy error that the variable's type is not consistent.
            async def run_Create(
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                *,
                validating_effects: bool = False,
            ):
                async with self._state_manager.task_workflow(
                    context,
                    task,
                    on_loop_iteration=on_loop_iteration,
                    validating_effects=validating_effects,
                ) as complete:
                    try:
                        response = await (StreamWorkflowStub(
                            context=context,
                            state_ref=context._state_ref,
                        ).Create(
                            IMPORT_typing.cast(google.protobuf.empty_pb2.Empty, task.request),
                            bearer_token=__internal_magic_token__,
                            idempotency=IMPORT_reboot_aio_idempotency.Idempotency(
                                alias=f'Task {task.task_id.task_uuid}',
                            ),
                        ))
                        await complete(task, (response, None))
                        return (response, None)
                    except IMPORT_asyncio.CancelledError:
                        # Check if the task was cancelled by a TasksServicer.
                        if self.tasks_dispatcher.is_task_cancelled(task.task_id.task_uuid):
                            # The running task was cancelled by a TasksServicer.
                            await complete(task, (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError()))
                            return (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError())
                        else:
                            raise
                    except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                        error_type = f'{aborted.error.__class__.__module__}.{aborted.error.__class__.__qualname__}'
                        # Do not retry a task if the error was specified in the
                        # proto file.
                        if error_type in self._specified_errors_by_service_method_name.get('rbt.mcp.v1.StreamMethods.Create', []):
                            await complete(task, (None, aborted.error))
                            return (None, aborted.error)
                        raise


            return await run_Create(
                self.create_context(
                    headers=IMPORT_reboot_aio_headers.Headers(
                        application_id=self.application_id,
                        state_ref=IMPORT_reboot_aio_types.StateRef(task.task_id.state_ref),
                    ),
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Create',
                    context_type=IMPORT_reboot_aio_contexts.WorkflowContext,
                    task=task,
                )
            )
        elif 'Put' == task.method_name:
            if only_validate:
                # TODO(benh): validate 'task.request' is correct type.
                return rbt.mcp.v1.stream_pb2.PutResponse()

            # Use an inline method to create a new scope, so that we can use
            # variable names like `context` and `effects` in multiple branches
            # in this code (notably when there are multiple task types) without
            # hitting a mypy error that the variable's type is not consistent.
            async def run_Put(
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                *,
                validating_effects: bool = False,
            ):
                async with self._state_manager.task_workflow(
                    context,
                    task,
                    on_loop_iteration=on_loop_iteration,
                    validating_effects=validating_effects,
                ) as complete:
                    try:
                        response = await (StreamWorkflowStub(
                            context=context,
                            state_ref=context._state_ref,
                        ).Put(
                            IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.PutRequest, task.request),
                            bearer_token=__internal_magic_token__,
                            idempotency=IMPORT_reboot_aio_idempotency.Idempotency(
                                alias=f'Task {task.task_id.task_uuid}',
                            ),
                        ))
                        await complete(task, (response, None))
                        return (response, None)
                    except IMPORT_asyncio.CancelledError:
                        # Check if the task was cancelled by a TasksServicer.
                        if self.tasks_dispatcher.is_task_cancelled(task.task_id.task_uuid):
                            # The running task was cancelled by a TasksServicer.
                            await complete(task, (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError()))
                            return (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError())
                        else:
                            raise
                    except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                        error_type = f'{aborted.error.__class__.__module__}.{aborted.error.__class__.__qualname__}'
                        # Do not retry a task if the error was specified in the
                        # proto file.
                        if error_type in self._specified_errors_by_service_method_name.get('rbt.mcp.v1.StreamMethods.Put', []):
                            await complete(task, (None, aborted.error))
                            return (None, aborted.error)
                        raise


            return await run_Put(
                self.create_context(
                    headers=IMPORT_reboot_aio_headers.Headers(
                        application_id=self.application_id,
                        state_ref=IMPORT_reboot_aio_types.StateRef(task.task_id.state_ref),
                    ),
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Put',
                    context_type=IMPORT_reboot_aio_contexts.WorkflowContext,
                    task=task,
                )
            )
        elif 'Replay' == task.method_name:
            if only_validate:
                # TODO(benh): validate 'task.request' is correct type.
                return rbt.mcp.v1.stream_pb2.ReplayResponse()

            # Use an inline method to create a new scope, so that we can use
            # variable names like `context` and `effects` in multiple branches
            # in this code (notably when there are multiple task types) without
            # hitting a mypy error that the variable's type is not consistent.
            async def run_Replay(
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                *,
                validating_effects: bool = False,
            ):
                async with self._state_manager.task_workflow(
                    context,
                    task,
                    on_loop_iteration=on_loop_iteration,
                    validating_effects=validating_effects,
                ) as complete:
                    try:
                        response = await (StreamWorkflowStub(
                            context=context,
                            state_ref=context._state_ref,
                        ).Replay(
                            IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.ReplayRequest, task.request),
                            bearer_token=__internal_magic_token__,
                        ))
                        await complete(task, (response, None))
                        return (response, None)
                    except IMPORT_asyncio.CancelledError:
                        # Check if the task was cancelled by a TasksServicer.
                        if self.tasks_dispatcher.is_task_cancelled(task.task_id.task_uuid):
                            # The running task was cancelled by a TasksServicer.
                            await complete(task, (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError()))
                            return (None, IMPORT_rbt_v1alpha1.tasks_pb2.TaskCancelledError())
                        else:
                            raise
                    except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                        error_type = f'{aborted.error.__class__.__module__}.{aborted.error.__class__.__qualname__}'
                        # Do not retry a task if the error was specified in the
                        # proto file.
                        if error_type in self._specified_errors_by_service_method_name.get('rbt.mcp.v1.StreamMethods.Replay', []):
                            await complete(task, (None, aborted.error))
                            return (None, aborted.error)
                        raise


            return await run_Replay(
                self.create_context(
                    headers=IMPORT_reboot_aio_headers.Headers(
                        application_id=self.application_id,
                        state_ref=IMPORT_reboot_aio_types.StateRef(task.task_id.state_ref),
                    ),
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Replay',
                    context_type=IMPORT_reboot_aio_contexts.WorkflowContext,
                    task=task,
                )
            )

        # There are no tasks for this service.
        start_or_validate = "start" if not only_validate else "validate"
        raise RuntimeError(
            f"Attempted to {start_or_validate} task '{task.method_name}' "
            f"on 'Stream' which does not exist"
        )

    # Stream specific methods:
    async def __Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
        *,
        validating_effects: bool,
    ) -> Stream.CreateEffects:
        try:
            response = (
                await self._servicer._Create(
                    context=context,
                    state=state,
                    request=request
                )
            )
            IMPORT_reboot_aio_types.assert_type(
                response,
                [google.protobuf.empty_pb2.Empty],
            )
            self.maybe_raise_effect_validation_retry(
                logger=logger,
                idempotency_manager=context,
                method_name='Stream.Create',
                validating_effects=validating_effects,
                context=context,
            )
            return Stream.CreateEffects(
                state=state,
                response=response,
                tasks=context._tasks,
                _colocated_upserts=context._colocated_upserts,
            )
        except IMPORT_reboot_aio_contexts.RetryReactively:
            # Retrying reactively, just let this propagate.
            raise
        except IMPORT_reboot_aio_contexts.EffectValidationRetry:
            # Doing effect validation, just let this propagate.
            raise
        except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
            # If the caller aborted due to a retryable error, just
            # propagate the aborted instead of propagating `Unknown`
            # so that a client can transparently retry.
            if IMPORT_rebootdev.aio.aborted.is_retryable(aborted):
                raise aborted
            # Log any _unhandled_ abort stack traces to make it
            # easier for debugging.
            #
            # NOTE: we don't log if we're a task as it will be logged
            # in `public/rebootdev/aio/internals/tasks_dispatcher.py` instead.
            aborted_type: IMPORT_typing.Optional[type] = None
            aborted_type = Stream.CreateAborted
            if isinstance(aborted, IMPORT_rebootdev.aio.aborted.SystemAborted):
                # Not logging when within `node` as we already log there.
                if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                    logger.warning(
                        f"Unhandled (in 'rbt.mcp.v1.Stream.Create') {aborted}; propagating as 'Unknown'\n" +
                        ''.join(IMPORT_traceback.format_exception(aborted))
                    )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                    # TODO(benh): consider whether or not we want to
                    # include the 'package.service.method' which may
                    # get concatenated together forming a kind of
                    # "stack trace"; while it's super helpful for
                    # debugging, it does expose implementation
                    # information.
                    message=f"unhandled (in 'rbt.mcp.v1.Stream.Create') {aborted}"
                )
            else:
                if (
                    aborted_type is not None and
                    not isinstance(aborted, aborted_type) and
                    aborted_type.is_declared_error(aborted.error)
                ):
                    # We propagate declared errors that might have
                    # come from another call, i.e., we might have an
                    # `Aborted` but not for this method but the
                    # `Aborted` that we have has an error that this
                    # method declared. This allows a developer to
                    # simply add the declared error to their `.proto`
                    # file rather than having to catch and re-raise
                    # the error with their own aborted type.
                    if context.task is None:
                        logger.warning(
                            f"Propagating unhandled but declared error (in 'rbt.mcp.v1.Stream.Create') {aborted}"
                        )
                elif (
                    aborted_type is None or
                    not isinstance(aborted, aborted_type)
                ):
                    # Not logging when within `node` as we already log there.
                    if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                        logger.warning(
                            f"Unhandled (in 'rbt.mcp.v1.Stream.Create') {aborted}; propagating as 'Unknown'\n" +
                            ''.join(IMPORT_traceback.format_exception(aborted))
                        )
                    # If this wasn't a declared error than we
                    # propagate it as `Unknown`.
                    raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                        IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                        # TODO(benh): consider whether or not we want to
                        # include the 'package.service.method' which may
                        # get concatenated together forming a kind of
                        # "stack trace"; while it's super helpful for
                        # debugging, it does expose implementation
                        # information.
                        message=f"unhandled (in 'rbt.mcp.v1.Stream.Create') {aborted}"
                    )

            raise
        except IMPORT_asyncio.CancelledError:
            # It's pretty normal for an RPC to be cancelled; it's not useful to
            # print a stack trace.
            raise
        except IMPORT_google_protobuf_message.DecodeError as decode_error:
            # We usually see this error when we are trying to construct a proto
            # message which is too deeply nested: protobuf has a limit of 100
            # nested messages. See the limits here:
            #   https://protobuf.dev/programming-guides/proto-limits/

            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Create') "
                    f"{type(decode_error).__name__}{': ' + str(decode_error) if len(str(decode_error)) > 0 else ''}; "
                    "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                    "See the limits here: https://protobuf.dev/programming-guides/proto-limits/" +
                    ''.join(IMPORT_traceback.format_exception(decode_error))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Create') {decode_error}; "
                        "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                        "See the limits here: https://protobuf.dev/programming-guides/proto-limits/"
            )
        except BaseException as exception:
            # Not logging when within `node` as we already log there.
            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Create') "
                    f"{type(exception).__name__}{': ' + str(exception) if len(str(exception)) > 0 else ''}; "
                    "propagating as 'Unknown'\n" +
                    ''.join(IMPORT_traceback.format_exception(exception))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                # TODO(benh): consider whether or not we want to
                # include the 'package.service.method' which may
                # get concatenated together forming a kind of
                # "stack trace"; while it's super helpful for
                # debugging, it does expose implementation
                # information.
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Create') {type(exception).__name__}: {exception}"
            )

    @IMPORT_reboot_aio_tracing.function_span(
        # We expect an `EffectValidationRetry` exception; that's not an error.
        set_status_on_exception=False
    )
    async def _Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        *,
        validating_effects: bool,
        grpc_context: IMPORT_typing.Optional[IMPORT_grpc.aio.ServicerContext] = None,
    ) -> google.protobuf.empty_pb2.Empty:
        # Try to verify the token if a token verifier exists.
        context.auth = await self._maybe_verify_token(
            headers=context._headers, method='Create'
        )

        # Check if we already have performed this mutation!
        #
        # We do this _before_ calling 'transactionally()' because
        # if this call is for a transaction method _and_ we've
        # already performed the transaction then we don't want to
        # become a transaction participant (again) we just want to
        # return the transaction's response.
        idempotent_mutation = self._state_manager.check_for_idempotent_mutation(
            context
        )

        if idempotent_mutation is not None:
            response = google.protobuf.empty_pb2.Empty()
            response.ParseFromString(idempotent_mutation.response)
            return response

        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.CreateAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )
            async with self._state_manager.writer(
                context,
                self._servicer.__state_type__,
                self.tasks_dispatcher,
                authorize=self._maybe_authorize(
                    method_name='rbt.mcp.v1.StreamMethods.Create',
                    headers=context._headers,
                    auth=context.auth,
                    request=request,
                ),
                transaction=transaction,
                from_constructor=False,
                requires_constructor=False,
            ) as (state, writer):

                effects = await self.__Create(
                    context,
                    state,
                    request,
                    validating_effects=validating_effects,
                )

                await writer.complete(effects)

                # TODO: We need a single `Effects` superclass for all methods, so we
                # would need to make it "partially" generic (with per-method subclasses
                # filling out the rest of the generic parameters) in order to fix this.
                return effects.response  # type: ignore[return-value]

    async def _schedule_Create(
        self,
        *,
        request: google.protobuf.empty_pb2.Empty,
        headers: IMPORT_reboot_aio_headers.Headers,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> tuple[IMPORT_reboot_aio_contexts.WriterContext, google.protobuf.empty_pb2.Empty]:
        context: IMPORT_reboot_aio_contexts.WriterContext = self.create_context(
            headers=headers,
            state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            method='Create',
            context_type=IMPORT_reboot_aio_contexts.WriterContext,
        )
        response = google.protobuf.empty_pb2.Empty()

        # Check if we already have performed this mutation!
        #
        # We do this _before_ calling 'transactionally()' because
        # if this call is for a transaction method _and_ we've
        # already performed the transaction then we don't want to
        # become a transaction participant (again) we just want to
        # return the transaction's response.
        idempotent_mutation = self._state_manager.check_for_idempotent_mutation(
            context
        )

        if idempotent_mutation is not None:
            response.ParseFromString(idempotent_mutation.response)

            # We should have only scheduled a single task!
            assert len(idempotent_mutation.task_ids) == 1
            assert grpc_context is not None
            grpc_context.set_trailing_metadata(
                grpc_context.trailing_metadata() +
                (
                    (
                        IMPORT_reboot_aio_headers.TASK_ID_UUID,
                        str(IMPORT_uuid.UUID(bytes=idempotent_mutation.task_ids[0].task_uuid))
                    ),
                )
            )

            return context, response

        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.CreateAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )

            # Try to verify the token if a token verifier exists.
            context.auth = await self._maybe_verify_token(
                headers=headers, method='Create'
            )

            async with self._state_manager.writer(
                context,
                self._servicer.__state_type__,
                self.tasks_dispatcher,
                transaction=transaction,
                authorize=self._maybe_authorize(
                    method_name='rbt.mcp.v1.StreamMethods.Create',
                    headers=context._headers,
                    auth=context.auth,
                    request=request,
                ),
                from_constructor=False,
                requires_constructor=False
            ) as (state, writer):

                task = await StreamServicerTasks(
                    context=context,
                    state_ref=context._state_ref,
                ).Create(
                    request,
                    schedule=context._headers.task_schedule,
                )

                effects = IMPORT_reboot_aio_state_managers.Effects(
                    response=response,
                    state=state,
                    tasks=[task],
                )

                assert effects.tasks is not None

                await writer.complete(effects)

                assert grpc_context is not None

                grpc_context.set_trailing_metadata(
                    grpc_context.trailing_metadata() +
                    (
                        (
                            IMPORT_reboot_aio_headers.TASK_ID_UUID,
                            str(IMPORT_uuid.UUID(bytes=task.task_id.task_uuid))
                        ),
                    )
                )

                return context, response

        return context, response


    # Entrypoint for non-reactive network calls (i.e. typical gRPC calls).
    async def Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> google.protobuf.empty_pb2.Empty:
        headers = IMPORT_reboot_aio_headers.Headers.from_grpc_context(grpc_context)
        assert headers.application_id is not None  # Guaranteed by `Headers`.

        # Confirm whether this is the right consensus to be serving this
        # request.
        authoritative_consensus = self.placement_client.consensus_for_actor(
            headers.application_id,
            headers.state_ref,
        )
        if authoritative_consensus != self.consensus_id:
            # This is NOT the correct consensus. Fail.
            await grpc_context.abort(
                IMPORT_grpc.StatusCode.UNAVAILABLE,
                f"Consensus '{self.consensus_id}' is not authoritative for this "
                f"request; consensus '{authoritative_consensus}' is.",
            )
            raise  # Unreachable but necessary for mypy.

        @IMPORT_reboot_aio_internals_middleware.maybe_run_function_twice_to_validate_effects
        async def _run(
            validating_effects: bool,
        ) -> google.protobuf.empty_pb2.Empty:
            context: IMPORT_typing.Optional[IMPORT_reboot_aio_contexts.Context] = None
            try:
                if headers.task_schedule is not None:
                    context, response = await self._schedule_Create(
                        headers=headers,
                        request=request,
                        grpc_context=grpc_context,
                    )
                    return response

                context = self.create_context(
                    headers=headers,
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Create',
                    context_type=IMPORT_reboot_aio_contexts.WriterContext,
                )
                assert context is not None

                return await self._Create(
                    request,
                    context,
                    validating_effects=validating_effects,
                    grpc_context=grpc_context,
                )
            except IMPORT_reboot_aio_contexts.EffectValidationRetry:
                # Doing effect validation, just let this propagate.
                raise
            except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                status = IMPORT_rpc_status_sync.to_status(aborted.to_status())
                # Need to add transaction participants here because
                # calling `grpc_context.abort_with_status()` will
                # ignore any other trailing metadata.
                if context is not None and context.transaction_id is not None:
                    status = status._replace(
                        trailing_metadata=status.trailing_metadata + context.participants.to_grpc_metadata()
                    )
                await grpc_context.abort_with_status(status)
                raise  # Unreachable but necessary for mypy.
            except IMPORT_asyncio.CancelledError:
                # It's pretty normal for an RPC to be cancelled; it's not useful to
                # print a stack trace.
                raise
            except BaseException as exception:
                # Print the exception stack trace for easier debugging. Note
                # that we don't include the stack trace in an error message
                # for the same reason that gRPC doesn't do so by default,
                # see https://github.com/grpc/grpc/issues/14897, but since this
                # should only get logged on the server side it is safe.
                logger.warning(
                    'Unhandled exception\n' +
                    ''.join(IMPORT_traceback.format_exc() if IMPORT_reboot_nodejs_python.should_print_stacktrace() else [f"{type(exception).__name__}: {exception}"])
                )

                # Re-raise the exception for gRPC to handle!
                #
                # TODO: gRPC will print a stack trace from this
                # exception which we don't want if we're executing via
                # Node.js.
                raise
            finally:
                if context is not None and context.transaction_id is not None:
                    # Propagate transaction participants.
                    grpc_context.set_trailing_metadata(
                        grpc_context.trailing_metadata() +
                        context.participants.to_grpc_metadata()
                    )

        with IMPORT_reboot_aio_tracing.context_from_headers(headers):
            return await _run()

    async def __Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        *,
        validating_effects: bool,
    ) -> Stream.PutEffects:
        try:
            response = (
                await self._servicer._Put(
                    context=context,
                    state=state,
                    request=request
                )
            )
            IMPORT_reboot_aio_types.assert_type(
                response,
                [rbt.mcp.v1.stream_pb2.PutResponse],
            )
            self.maybe_raise_effect_validation_retry(
                logger=logger,
                idempotency_manager=context,
                method_name='Stream.Put',
                validating_effects=validating_effects,
                context=context,
            )
            return Stream.PutEffects(
                state=state,
                response=response,
                tasks=context._tasks,
                _colocated_upserts=context._colocated_upserts,
            )
        except IMPORT_reboot_aio_contexts.RetryReactively:
            # Retrying reactively, just let this propagate.
            raise
        except IMPORT_reboot_aio_contexts.EffectValidationRetry:
            # Doing effect validation, just let this propagate.
            raise
        except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
            # If the caller aborted due to a retryable error, just
            # propagate the aborted instead of propagating `Unknown`
            # so that a client can transparently retry.
            if IMPORT_rebootdev.aio.aborted.is_retryable(aborted):
                raise aborted
            # Log any _unhandled_ abort stack traces to make it
            # easier for debugging.
            #
            # NOTE: we don't log if we're a task as it will be logged
            # in `public/rebootdev/aio/internals/tasks_dispatcher.py` instead.
            aborted_type: IMPORT_typing.Optional[type] = None
            aborted_type = Stream.PutAborted
            if isinstance(aborted, IMPORT_rebootdev.aio.aborted.SystemAborted):
                # Not logging when within `node` as we already log there.
                if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                    logger.warning(
                        f"Unhandled (in 'rbt.mcp.v1.Stream.Put') {aborted}; propagating as 'Unknown'\n" +
                        ''.join(IMPORT_traceback.format_exception(aborted))
                    )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                    # TODO(benh): consider whether or not we want to
                    # include the 'package.service.method' which may
                    # get concatenated together forming a kind of
                    # "stack trace"; while it's super helpful for
                    # debugging, it does expose implementation
                    # information.
                    message=f"unhandled (in 'rbt.mcp.v1.Stream.Put') {aborted}"
                )
            else:
                if (
                    aborted_type is not None and
                    not isinstance(aborted, aborted_type) and
                    aborted_type.is_declared_error(aborted.error)
                ):
                    # We propagate declared errors that might have
                    # come from another call, i.e., we might have an
                    # `Aborted` but not for this method but the
                    # `Aborted` that we have has an error that this
                    # method declared. This allows a developer to
                    # simply add the declared error to their `.proto`
                    # file rather than having to catch and re-raise
                    # the error with their own aborted type.
                    if context.task is None:
                        logger.warning(
                            f"Propagating unhandled but declared error (in 'rbt.mcp.v1.Stream.Put') {aborted}"
                        )
                elif (
                    aborted_type is None or
                    not isinstance(aborted, aborted_type)
                ):
                    # Not logging when within `node` as we already log there.
                    if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                        logger.warning(
                            f"Unhandled (in 'rbt.mcp.v1.Stream.Put') {aborted}; propagating as 'Unknown'\n" +
                            ''.join(IMPORT_traceback.format_exception(aborted))
                        )
                    # If this wasn't a declared error than we
                    # propagate it as `Unknown`.
                    raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                        IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                        # TODO(benh): consider whether or not we want to
                        # include the 'package.service.method' which may
                        # get concatenated together forming a kind of
                        # "stack trace"; while it's super helpful for
                        # debugging, it does expose implementation
                        # information.
                        message=f"unhandled (in 'rbt.mcp.v1.Stream.Put') {aborted}"
                    )

            raise
        except IMPORT_asyncio.CancelledError:
            # It's pretty normal for an RPC to be cancelled; it's not useful to
            # print a stack trace.
            raise
        except IMPORT_google_protobuf_message.DecodeError as decode_error:
            # We usually see this error when we are trying to construct a proto
            # message which is too deeply nested: protobuf has a limit of 100
            # nested messages. See the limits here:
            #   https://protobuf.dev/programming-guides/proto-limits/

            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Put') "
                    f"{type(decode_error).__name__}{': ' + str(decode_error) if len(str(decode_error)) > 0 else ''}; "
                    "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                    "See the limits here: https://protobuf.dev/programming-guides/proto-limits/" +
                    ''.join(IMPORT_traceback.format_exception(decode_error))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Put') {decode_error}; "
                        "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                        "See the limits here: https://protobuf.dev/programming-guides/proto-limits/"
            )
        except BaseException as exception:
            # Not logging when within `node` as we already log there.
            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Put') "
                    f"{type(exception).__name__}{': ' + str(exception) if len(str(exception)) > 0 else ''}; "
                    "propagating as 'Unknown'\n" +
                    ''.join(IMPORT_traceback.format_exception(exception))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                # TODO(benh): consider whether or not we want to
                # include the 'package.service.method' which may
                # get concatenated together forming a kind of
                # "stack trace"; while it's super helpful for
                # debugging, it does expose implementation
                # information.
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Put') {type(exception).__name__}: {exception}"
            )

    @IMPORT_reboot_aio_tracing.function_span(
        # We expect an `EffectValidationRetry` exception; that's not an error.
        set_status_on_exception=False
    )
    async def _Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        *,
        validating_effects: bool,
        grpc_context: IMPORT_typing.Optional[IMPORT_grpc.aio.ServicerContext] = None,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        # Try to verify the token if a token verifier exists.
        context.auth = await self._maybe_verify_token(
            headers=context._headers, method='Put'
        )

        # Check if we already have performed this mutation!
        #
        # We do this _before_ calling 'transactionally()' because
        # if this call is for a transaction method _and_ we've
        # already performed the transaction then we don't want to
        # become a transaction participant (again) we just want to
        # return the transaction's response.
        idempotent_mutation = self._state_manager.check_for_idempotent_mutation(
            context
        )

        if idempotent_mutation is not None:
            response = rbt.mcp.v1.stream_pb2.PutResponse()
            response.ParseFromString(idempotent_mutation.response)
            return response

        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.PutAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )
            async with self._state_manager.writer(
                context,
                self._servicer.__state_type__,
                self.tasks_dispatcher,
                authorize=self._maybe_authorize(
                    method_name='rbt.mcp.v1.StreamMethods.Put',
                    headers=context._headers,
                    auth=context.auth,
                    request=request,
                ),
                transaction=transaction,
                from_constructor=False,
                requires_constructor=False,
            ) as (state, writer):

                effects = await self.__Put(
                    context,
                    state,
                    request,
                    validating_effects=validating_effects,
                )

                await writer.complete(effects)

                # TODO: We need a single `Effects` superclass for all methods, so we
                # would need to make it "partially" generic (with per-method subclasses
                # filling out the rest of the generic parameters) in order to fix this.
                return effects.response  # type: ignore[return-value]

    async def _schedule_Put(
        self,
        *,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        headers: IMPORT_reboot_aio_headers.Headers,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> tuple[IMPORT_reboot_aio_contexts.WriterContext, rbt.mcp.v1.stream_pb2.PutResponse]:
        context: IMPORT_reboot_aio_contexts.WriterContext = self.create_context(
            headers=headers,
            state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            method='Put',
            context_type=IMPORT_reboot_aio_contexts.WriterContext,
        )
        response = rbt.mcp.v1.stream_pb2.PutResponse()

        # Check if we already have performed this mutation!
        #
        # We do this _before_ calling 'transactionally()' because
        # if this call is for a transaction method _and_ we've
        # already performed the transaction then we don't want to
        # become a transaction participant (again) we just want to
        # return the transaction's response.
        idempotent_mutation = self._state_manager.check_for_idempotent_mutation(
            context
        )

        if idempotent_mutation is not None:
            response.ParseFromString(idempotent_mutation.response)

            # We should have only scheduled a single task!
            assert len(idempotent_mutation.task_ids) == 1
            assert grpc_context is not None
            grpc_context.set_trailing_metadata(
                grpc_context.trailing_metadata() +
                (
                    (
                        IMPORT_reboot_aio_headers.TASK_ID_UUID,
                        str(IMPORT_uuid.UUID(bytes=idempotent_mutation.task_ids[0].task_uuid))
                    ),
                )
            )

            return context, response

        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.PutAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )

            # Try to verify the token if a token verifier exists.
            context.auth = await self._maybe_verify_token(
                headers=headers, method='Put'
            )

            async with self._state_manager.writer(
                context,
                self._servicer.__state_type__,
                self.tasks_dispatcher,
                transaction=transaction,
                authorize=self._maybe_authorize(
                    method_name='rbt.mcp.v1.StreamMethods.Put',
                    headers=context._headers,
                    auth=context.auth,
                    request=request,
                ),
                from_constructor=False,
                requires_constructor=False
            ) as (state, writer):

                task = await StreamServicerTasks(
                    context=context,
                    state_ref=context._state_ref,
                ).Put(
                    request,
                    schedule=context._headers.task_schedule,
                )

                effects = IMPORT_reboot_aio_state_managers.Effects(
                    response=response,
                    state=state,
                    tasks=[task],
                )

                assert effects.tasks is not None

                await writer.complete(effects)

                assert grpc_context is not None

                grpc_context.set_trailing_metadata(
                    grpc_context.trailing_metadata() +
                    (
                        (
                            IMPORT_reboot_aio_headers.TASK_ID_UUID,
                            str(IMPORT_uuid.UUID(bytes=task.task_id.task_uuid))
                        ),
                    )
                )

                return context, response

        return context, response


    # Entrypoint for non-reactive network calls (i.e. typical gRPC calls).
    async def Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        headers = IMPORT_reboot_aio_headers.Headers.from_grpc_context(grpc_context)
        assert headers.application_id is not None  # Guaranteed by `Headers`.

        # Confirm whether this is the right consensus to be serving this
        # request.
        authoritative_consensus = self.placement_client.consensus_for_actor(
            headers.application_id,
            headers.state_ref,
        )
        if authoritative_consensus != self.consensus_id:
            # This is NOT the correct consensus. Fail.
            await grpc_context.abort(
                IMPORT_grpc.StatusCode.UNAVAILABLE,
                f"Consensus '{self.consensus_id}' is not authoritative for this "
                f"request; consensus '{authoritative_consensus}' is.",
            )
            raise  # Unreachable but necessary for mypy.

        @IMPORT_reboot_aio_internals_middleware.maybe_run_function_twice_to_validate_effects
        async def _run(
            validating_effects: bool,
        ) -> rbt.mcp.v1.stream_pb2.PutResponse:
            context: IMPORT_typing.Optional[IMPORT_reboot_aio_contexts.Context] = None
            try:
                if headers.task_schedule is not None:
                    context, response = await self._schedule_Put(
                        headers=headers,
                        request=request,
                        grpc_context=grpc_context,
                    )
                    return response

                context = self.create_context(
                    headers=headers,
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Put',
                    context_type=IMPORT_reboot_aio_contexts.WriterContext,
                )
                assert context is not None

                return await self._Put(
                    request,
                    context,
                    validating_effects=validating_effects,
                    grpc_context=grpc_context,
                )
            except IMPORT_reboot_aio_contexts.EffectValidationRetry:
                # Doing effect validation, just let this propagate.
                raise
            except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                status = IMPORT_rpc_status_sync.to_status(aborted.to_status())
                # Need to add transaction participants here because
                # calling `grpc_context.abort_with_status()` will
                # ignore any other trailing metadata.
                if context is not None and context.transaction_id is not None:
                    status = status._replace(
                        trailing_metadata=status.trailing_metadata + context.participants.to_grpc_metadata()
                    )
                await grpc_context.abort_with_status(status)
                raise  # Unreachable but necessary for mypy.
            except IMPORT_asyncio.CancelledError:
                # It's pretty normal for an RPC to be cancelled; it's not useful to
                # print a stack trace.
                raise
            except BaseException as exception:
                # Print the exception stack trace for easier debugging. Note
                # that we don't include the stack trace in an error message
                # for the same reason that gRPC doesn't do so by default,
                # see https://github.com/grpc/grpc/issues/14897, but since this
                # should only get logged on the server side it is safe.
                logger.warning(
                    'Unhandled exception\n' +
                    ''.join(IMPORT_traceback.format_exc() if IMPORT_reboot_nodejs_python.should_print_stacktrace() else [f"{type(exception).__name__}: {exception}"])
                )

                # Re-raise the exception for gRPC to handle!
                #
                # TODO: gRPC will print a stack trace from this
                # exception which we don't want if we're executing via
                # Node.js.
                raise
            finally:
                if context is not None and context.transaction_id is not None:
                    # Propagate transaction participants.
                    grpc_context.set_trailing_metadata(
                        grpc_context.trailing_metadata() +
                        context.participants.to_grpc_metadata()
                    )

        with IMPORT_reboot_aio_tracing.context_from_headers(headers):
            return await _run()

    async def __Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        *,
        validating_effects: bool,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        try:
            response = (
                await self._servicer._Replay(
                    context=context,
                    state=state,
                    request=request
                )
            )
            IMPORT_reboot_aio_types.assert_type(
                response,
                [rbt.mcp.v1.stream_pb2.ReplayResponse],
            )
            self.maybe_raise_effect_validation_retry(
                logger=logger,
                idempotency_manager=context,
                method_name='Stream.Replay',
                validating_effects=validating_effects,
                context=context,
            )
            return response
        except IMPORT_reboot_aio_contexts.RetryReactively:
            # Retrying reactively, just let this propagate.
            raise
        except IMPORT_reboot_aio_contexts.EffectValidationRetry:
            # Doing effect validation, just let this propagate.
            raise
        except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
            # If the caller aborted due to a retryable error, just
            # propagate the aborted instead of propagating `Unknown`
            # so that a client can transparently retry.
            if IMPORT_rebootdev.aio.aborted.is_retryable(aborted):
                raise aborted
            # Log any _unhandled_ abort stack traces to make it
            # easier for debugging.
            #
            # NOTE: we don't log if we're a task as it will be logged
            # in `public/rebootdev/aio/internals/tasks_dispatcher.py` instead.
            aborted_type: IMPORT_typing.Optional[type] = None
            aborted_type = Stream.ReplayAborted
            if isinstance(aborted, IMPORT_rebootdev.aio.aborted.SystemAborted):
                # Not logging when within `node` as we already log there.
                if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                    logger.warning(
                        f"Unhandled (in 'rbt.mcp.v1.Stream.Replay') {aborted}; propagating as 'Unknown'\n" +
                        ''.join(IMPORT_traceback.format_exception(aborted))
                    )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                    # TODO(benh): consider whether or not we want to
                    # include the 'package.service.method' which may
                    # get concatenated together forming a kind of
                    # "stack trace"; while it's super helpful for
                    # debugging, it does expose implementation
                    # information.
                    message=f"unhandled (in 'rbt.mcp.v1.Stream.Replay') {aborted}"
                )
            else:
                if (
                    aborted_type is not None and
                    not isinstance(aborted, aborted_type) and
                    aborted_type.is_declared_error(aborted.error)
                ):
                    # We propagate declared errors that might have
                    # come from another call, i.e., we might have an
                    # `Aborted` but not for this method but the
                    # `Aborted` that we have has an error that this
                    # method declared. This allows a developer to
                    # simply add the declared error to their `.proto`
                    # file rather than having to catch and re-raise
                    # the error with their own aborted type.
                    if context.task is None:
                        logger.warning(
                            f"Propagating unhandled but declared error (in 'rbt.mcp.v1.Stream.Replay') {aborted}"
                        )
                elif (
                    aborted_type is None or
                    not isinstance(aborted, aborted_type)
                ):
                    # Not logging when within `node` as we already log there.
                    if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                        logger.warning(
                            f"Unhandled (in 'rbt.mcp.v1.Stream.Replay') {aborted}; propagating as 'Unknown'\n" +
                            ''.join(IMPORT_traceback.format_exception(aborted))
                        )
                    # If this wasn't a declared error than we
                    # propagate it as `Unknown`.
                    raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                        IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                        # TODO(benh): consider whether or not we want to
                        # include the 'package.service.method' which may
                        # get concatenated together forming a kind of
                        # "stack trace"; while it's super helpful for
                        # debugging, it does expose implementation
                        # information.
                        message=f"unhandled (in 'rbt.mcp.v1.Stream.Replay') {aborted}"
                    )

            raise
        except IMPORT_asyncio.CancelledError:
            # It's pretty normal for an RPC to be cancelled; it's not useful to
            # print a stack trace.
            raise
        except IMPORT_google_protobuf_message.DecodeError as decode_error:
            # We usually see this error when we are trying to construct a proto
            # message which is too deeply nested: protobuf has a limit of 100
            # nested messages. See the limits here:
            #   https://protobuf.dev/programming-guides/proto-limits/

            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Replay') "
                    f"{type(decode_error).__name__}{': ' + str(decode_error) if len(str(decode_error)) > 0 else ''}; "
                    "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                    "See the limits here: https://protobuf.dev/programming-guides/proto-limits/" +
                    ''.join(IMPORT_traceback.format_exception(decode_error))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Replay') {decode_error}; "
                        "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                        "See the limits here: https://protobuf.dev/programming-guides/proto-limits/"
            )
        except BaseException as exception:
            # Not logging when within `node` as we already log there.
            if IMPORT_reboot_nodejs_python.should_print_stacktrace():
                logger.warning(
                    "Unhandled (in 'rbt.mcp.v1.Stream.Replay') "
                    f"{type(exception).__name__}{': ' + str(exception) if len(str(exception)) > 0 else ''}; "
                    "propagating as 'Unknown'\n" +
                    ''.join(IMPORT_traceback.format_exception(exception))
                )
            raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                # TODO(benh): consider whether or not we want to
                # include the 'package.service.method' which may
                # get concatenated together forming a kind of
                # "stack trace"; while it's super helpful for
                # debugging, it does expose implementation
                # information.
                message=f"unhandled (in 'rbt.mcp.v1.Stream.Replay') {type(exception).__name__}: {exception}"
            )

    @IMPORT_reboot_aio_tracing.function_span(
        # We expect an `EffectValidationRetry` exception; that's not an error.
        set_status_on_exception=False
    )
    async def _Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        *,
        validating_effects: bool,
        grpc_context: IMPORT_typing.Optional[IMPORT_grpc.aio.ServicerContext] = None,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        # Try to verify the token if a token verifier exists.
        context.auth = await self._maybe_verify_token(
            headers=context._headers, method='Replay'
        )


        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.ReplayAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )
            authorizer = self._maybe_authorize(
                method_name='rbt.mcp.v1.StreamMethods.Replay',
                headers=context._headers,
                auth=context.auth,
                request=request,
            )
            async with self._state_manager.reader(
                context,
                self._servicer.__state_type__,
                authorize=authorizer,
            ) as state:
                response = await self.__Replay(
                    context,
                    state,
                    request,
                    validating_effects=validating_effects,
                )
                return response

    async def _schedule_Replay(
        self,
        *,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        headers: IMPORT_reboot_aio_headers.Headers,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> tuple[IMPORT_reboot_aio_contexts.WriterContext, rbt.mcp.v1.stream_pb2.ReplayResponse]:
        context: IMPORT_reboot_aio_contexts.WriterContext = self.create_context(
            headers=headers,
            state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            method='Replay',
            context_type=IMPORT_reboot_aio_contexts.WriterContext,
        )
        response = rbt.mcp.v1.stream_pb2.ReplayResponse()


        async with self._state_manager.transactionally(
            context,
            self.tasks_dispatcher,
            aborted_type=Stream.ReplayAborted,
        ) as transaction:
            if transaction is not None:
                context.participants.add(
                    self._servicer.__state_type_name__, context._state_ref
                )

            # Try to verify the token if a token verifier exists.
            context.auth = await self._maybe_verify_token(
                headers=headers, method='Replay'
            )

            async with self._state_manager.writer(
                context,
                self._servicer.__state_type__,
                self.tasks_dispatcher,
                transaction=transaction,
                authorize=self._maybe_authorize(
                    method_name='rbt.mcp.v1.StreamMethods.Replay',
                    headers=context._headers,
                    auth=context.auth,
                    request=request,
                ),
                from_constructor=False,
                requires_constructor=False
            ) as (state, writer):

                task = await StreamServicerTasks(
                    context=context,
                    state_ref=context._state_ref,
                ).Replay(
                    request,
                    schedule=context._headers.task_schedule,
                )

                effects = IMPORT_reboot_aio_state_managers.Effects(
                    response=response,
                    state=state,
                    tasks=[task],
                )

                assert effects.tasks is not None

                await writer.complete(effects)

                assert grpc_context is not None

                grpc_context.set_trailing_metadata(
                    grpc_context.trailing_metadata() +
                    (
                        (
                            IMPORT_reboot_aio_headers.TASK_ID_UUID,
                            str(IMPORT_uuid.UUID(bytes=task.task_id.task_uuid))
                        ),
                    )
                )

                return context, response

        return context, response


    # Entrypoint for non-reactive network calls (i.e. typical gRPC calls).
    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        grpc_context: IMPORT_grpc.aio.ServicerContext,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        headers = IMPORT_reboot_aio_headers.Headers.from_grpc_context(grpc_context)
        assert headers.application_id is not None  # Guaranteed by `Headers`.

        # Confirm whether this is the right consensus to be serving this
        # request.
        authoritative_consensus = self.placement_client.consensus_for_actor(
            headers.application_id,
            headers.state_ref,
        )
        if authoritative_consensus != self.consensus_id:
            # This is NOT the correct consensus. Fail.
            await grpc_context.abort(
                IMPORT_grpc.StatusCode.UNAVAILABLE,
                f"Consensus '{self.consensus_id}' is not authoritative for this "
                f"request; consensus '{authoritative_consensus}' is.",
            )
            raise  # Unreachable but necessary for mypy.

        @IMPORT_reboot_aio_internals_middleware.maybe_run_function_twice_to_validate_effects
        async def _run(
            validating_effects: bool,
        ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
            context: IMPORT_typing.Optional[IMPORT_reboot_aio_contexts.Context] = None
            try:
                if headers.task_schedule is not None:
                    context, response = await self._schedule_Replay(
                        headers=headers,
                        request=request,
                        grpc_context=grpc_context,
                    )
                    return response

                context = self.create_context(
                    headers=headers,
                    state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    method='Replay',
                    context_type=IMPORT_reboot_aio_contexts.ReaderContext,
                )
                assert context is not None

                return await self._Replay(
                    request,
                    context,
                    validating_effects=validating_effects,
                    grpc_context=grpc_context,
                )
            except IMPORT_reboot_aio_contexts.EffectValidationRetry:
                # Doing effect validation, just let this propagate.
                raise
            except IMPORT_rebootdev.aio.aborted.Aborted as aborted:
                status = IMPORT_rpc_status_sync.to_status(aborted.to_status())
                # Need to add transaction participants here because
                # calling `grpc_context.abort_with_status()` will
                # ignore any other trailing metadata.
                if context is not None and context.transaction_id is not None:
                    status = status._replace(
                        trailing_metadata=status.trailing_metadata + context.participants.to_grpc_metadata()
                    )
                await grpc_context.abort_with_status(status)
                raise  # Unreachable but necessary for mypy.
            except IMPORT_asyncio.CancelledError:
                # It's pretty normal for an RPC to be cancelled; it's not useful to
                # print a stack trace.
                raise
            except BaseException as exception:
                # Print the exception stack trace for easier debugging. Note
                # that we don't include the stack trace in an error message
                # for the same reason that gRPC doesn't do so by default,
                # see https://github.com/grpc/grpc/issues/14897, but since this
                # should only get logged on the server side it is safe.
                logger.warning(
                    'Unhandled exception\n' +
                    ''.join(IMPORT_traceback.format_exc() if IMPORT_reboot_nodejs_python.should_print_stacktrace() else [f"{type(exception).__name__}: {exception}"])
                )

                # Re-raise the exception for gRPC to handle!
                #
                # TODO: gRPC will print a stack trace from this
                # exception which we don't want if we're executing via
                # Node.js.
                raise
            finally:
                if context is not None and context.transaction_id is not None:
                    # Propagate transaction participants.
                    grpc_context.set_trailing_metadata(
                        grpc_context.trailing_metadata() +
                        context.participants.to_grpc_metadata()
                    )

        with IMPORT_reboot_aio_tracing.context_from_headers(headers):
            return await _run()

    def _maybe_authorize(
        self,
        *,
        method_name: str,
        headers: IMPORT_reboot_aio_headers.Headers,
        auth: IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.Auth],
        request: IMPORT_typing.Optional[StreamRequestTypes] = None,
    ) -> IMPORT_typing.Optional[IMPORT_typing.Callable[[IMPORT_typing.Optional[StreamStateType]], IMPORT_typing.Awaitable[None]]]:
        """Returns a function to check authorization for the given method.

        Raises `PermissionDenied` in case Authorizer is present but the request
        is not authorized.
        """
        # To authorize internal calls, we use an internal magic token.
        if headers.bearer_token == __internal_magic_token__:
            return None

        assert self._authorizer is not None

        async def authorize(state: IMPORT_typing.Optional[StreamStateType]) -> None:
            # Create context for the authorizer. This is a `ReaderContext`
            # independently of the calling context.
            with self.use_context(
                headers=(
                    # Get headers suitable for doing authorization.
                    headers.copy_for_token_verification_and_authorization()
                ),
                state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                method=method_name,
                context_type=IMPORT_reboot_aio_contexts.ReaderContext,
            ) as context:
                context.auth = auth

                # Get the authorizer decision.
                authorization_decision = await self._authorizer.authorize(
                    method_name=method_name,
                    context=context,
                    state=state,
                    request=request,
                )

            # Enforce correct authorizer decision type.
            try:
                IMPORT_reboot_aio_types.assert_type(
                    authorization_decision,
                    [
                        IMPORT_rbt_v1alpha1.errors_pb2.Ok,
                        IMPORT_rbt_v1alpha1.errors_pb2.Unauthenticated,
                        IMPORT_rbt_v1alpha1.errors_pb2.PermissionDenied,
                    ]
                )
            except TypeError as e:
                # Retyping.cast the exception to provide more context.
                authorizer_type = f"{type(self._authorizer).__module__}.{type(self._authorizer).__name__}"
                raise TypeError(
                    f"Authorizer '{authorizer_type}' "
                    f"returned unexpected type '{type(authorization_decision).__name__}' "
                    f"for method '{method_name}' on "
                    f"`rbt.mcp.v1.Stream('{headers.state_ref.id}')`"
                ) from e

            # If the decision is not `True`, raise a `SystemAborted` with either a
            # `PermissionDenied` error (in case of `False`) or an `Unauthenticated`
            # error.
            if not isinstance(authorization_decision, IMPORT_rbt_v1alpha1.errors_pb2.Ok):
                if isinstance(authorization_decision, IMPORT_rbt_v1alpha1.errors_pb2.Unauthenticated):
                    logger.warning(
                        f"Unauthenticated call to '{method_name}' on "
                        f"`rbt.mcp.v1.Stream('{headers.state_ref.id}')`"
                    )

                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    authorization_decision,
                    message=
                    f"You are not authorized to call '{method_name}' on "
                    f"`rbt.mcp.v1.Stream('{headers.state_ref.id}')`"
                )

        return authorize

    async def _maybe_verify_token(
        self,
        *,
        headers: IMPORT_reboot_aio_headers.Headers,
        method: str,
    ) -> IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.Auth]:
        """Verify the bearer token and if a token verifier is present.

        Returns the (optional) `rebootdev.aio.auth.Auth` object
        produced by the token verifier if the token can be verified.
        """
        if self._token_verifier is not None:
            if headers.bearer_token == __internal_magic_token__:
                return None

            with self.use_context(
                headers=(
                    # Get headers suitable for doing token verification.
                    headers.copy_for_token_verification_and_authorization()
                ),
                state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                method=method,
                context_type=IMPORT_reboot_aio_contexts.ReaderContext,
            ) as context:
                return await self._token_verifier.verify_token(
                    context=context,
                    token=headers.bearer_token,
                )

        return None


############################ Client Stubs ############################
# This section is relevant for clients accessing a Reboot service. Since
# servicers are themselves often clients also, this code is generated for
# them also.


class _StreamStub(IMPORT_reboot_aio_stubs.Stub):

    __state_type_name__ = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream')

    def __init__(
        self,
        *,
        context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        # Within a Reboot context we do not pass on the caller's bearer token, as that might
        # have security implications - we cannot simply trust any service we are calling with
        # the user's credentials. Instead, the developer can rely on the default app-internal
        # auth, or override that and set an explicit bearer token.
        #
        # In the case of `ExternalContext`, however, its `bearer_token` was set specifically
        # by the developer for the purpose of making these calls.
        app_internal_authorization: IMPORT_typing.Optional[str] = None
        if isinstance(context, IMPORT_reboot_aio_external.ExternalContext):
            # Note that only `ExternalContext` even has a `bearer_token` field.
            bearer_token = context.bearer_token
            app_internal_authorization = context.app_internal_authorization

        super().__init__(
            channel_manager=context.channel_manager,
            idempotency_manager=context,
            state_ref=state_ref,
            context=context if isinstance(context, IMPORT_reboot_aio_contexts.Context) else None,
            bearer_token=bearer_token,
            app_internal_authorization=app_internal_authorization,
        )

        # All the channels for all services of this state will go to the same
        # place, so we can just get a single channel and share it across all
        # stubs.
        channel = self._channel_manager.get_channel_to_state(
            self.__state_type_name__, state_ref
        )
        self._rbt_mcp_v1_streammethods_stub = rbt.mcp.v1.stream_pb2_grpc.StreamMethodsStub(channel)


class StreamReaderStub(_StreamStub):

    def __init__(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        *,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.ReaderContext, IMPORT_reboot_aio_contexts.WriterContext, IMPORT_reboot_aio_contexts.TransactionContext, IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])
        super().__init__(
            context=context,
            state_ref=state_ref,
            bearer_token=bearer_token,
        )

    # Stream specific methods:


    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream')
        service_name = IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods')
        method = 'Replay'

        async def call():
            async with self._call(
                state_type_name,
                service_name,
                method,
                self._rbt_mcp_v1_streammethods_stub.Replay,
                request,
                unary=True,
                reader=True,
                response_type=rbt.mcp.v1.stream_pb2.ReplayResponse,
                aborted_type=Stream.ReplayAborted,
                metadata=metadata,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable)
                return await call

        if isinstance(self._context, IMPORT_reboot_aio_contexts.WorkflowContext):
            # Use the idempotency manager to make sure that this
            # reader is being called following the rules.
            with self._context.idempotently(
                state_type_name=state_type_name,
                state_ref=self._headers.state_ref,
                service_name=service_name,
                method=method,
                mutation=False,
                request=request,
                metadata=metadata,
                idempotency=idempotency,
                # Only need to pass `aborted_type` for mutations.
                aborted_type=None,
            ) as idempotency_key:
                assert idempotency is not None
                # Check if this reader is from an `.always()` and if
                # so, don't memoize!
                if idempotency.always:
                    return await call()

                assert idempotency_key is not None
                return await IMPORT_reboot_aio_workflows.at_least_once(
                    (
                        # TODO: for easier debugging include the
                        # original alias (or generated alias in the
                        # case of `.per_iteration()` w/o an alias)
                        # instead of just `idempotency_key`.
                        f'{ service_name }.{ method } ({str(idempotency_key)})',
                        # NOTE: we want this to be `PER_WORKFLOW`
                        # because any per iteration concerns should
                        # have already been taken care of by caller
                        # using `.per_iteration()`.
                        IMPORT_reboot_aio_workflows.PER_WORKFLOW
                    ),
                    self._context,
                    call,
                    type=rbt.mcp.v1.stream_pb2.ReplayResponse,
                )
        return await call()



class StreamWriterStub(_StreamStub):

    def __init__(
        self,
        context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        *,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.TransactionContext, IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])
        super().__init__(
            context=context,
            state_ref=state_ref,
            bearer_token=bearer_token,
        )

    # Stream specific methods:
    async def Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> google.protobuf.empty_pb2.Empty:
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Create',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.CreateAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Create',
                self._rbt_mcp_v1_streammethods_stub.Create,
                request,
                unary=True,
                reader=False,
                response_type=google.protobuf.empty_pb2.Empty,
                aborted_type=Stream.CreateAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                return await call

    async def Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Put',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.PutAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Put',
                self._rbt_mcp_v1_streammethods_stub.Put,
                request,
                unary=True,
                reader=False,
                response_type=rbt.mcp.v1.stream_pb2.PutResponse,
                aborted_type=Stream.PutAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                return await call

    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        async with self._call(
            IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            'Replay',
            self._rbt_mcp_v1_streammethods_stub.Replay,
            request,
            unary=True,
            reader=True,
            response_type=rbt.mcp.v1.stream_pb2.ReplayResponse,
            aborted_type=Stream.ReplayAborted,
            metadata=metadata,
            bearer_token=bearer_token,
        ) as call:
            assert isinstance(call, IMPORT_typing.Awaitable), type(call)
            return await call


class StreamWorkflowStub(_StreamStub):

    def __init__(
        self,
        *,
        context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.TransactionContext, IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])
        super().__init__(
            context=context,
            state_ref=state_ref,
            bearer_token=bearer_token,
        )

    # Stream specific methods:
    async def Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> google.protobuf.empty_pb2.Empty:
        idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Create',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.CreateAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Create',
                self._rbt_mcp_v1_streammethods_stub.Create,
                request,
                unary=True,
                reader=False,
                response_type=google.protobuf.empty_pb2.Empty,
                aborted_type=Stream.CreateAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                return await call

    async def Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Put',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.PutAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Put',
                self._rbt_mcp_v1_streammethods_stub.Put,
                request,
                unary=True,
                reader=False,
                response_type=rbt.mcp.v1.stream_pb2.PutResponse,
                aborted_type=Stream.PutAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                return await call

    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        async with self._call(
            IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            'Replay',
            self._rbt_mcp_v1_streammethods_stub.Replay,
            request,
            unary=True,
            reader=True,
            response_type=rbt.mcp.v1.stream_pb2.ReplayResponse,
            aborted_type=Stream.ReplayAborted,
            metadata=metadata,
            bearer_token=bearer_token,
        ) as call:
            assert isinstance(call, IMPORT_typing.Awaitable), type(call)
            return await call



class StreamTasksStub(_StreamStub):

    def __init__(
        self,
        context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        *,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.TransactionContext, IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])
        super().__init__(
            context=context,
            state_ref=state_ref,
            bearer_token=bearer_token,
        )

    # Stream specific methods:
    async def Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
        idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Create',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.CreateAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Create',
                self._rbt_mcp_v1_streammethods_stub.Create,
                request,
                unary=True,
                reader=False,
                response_type=google.protobuf.empty_pb2.Empty,
                aborted_type=Stream.CreateAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                await call
                for (key, value) in await call.trailing_metadata():  # type: ignore[misc, attr-defined]
                    if key == IMPORT_reboot_aio_headers.TASK_ID_UUID:
                        return IMPORT_rbt_v1alpha1.tasks_pb2.TaskId(
                            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                            state_ref=self._headers.state_ref.to_str(),
                            task_uuid=IMPORT_uuid.UUID(value).bytes,
                        )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Internal(),
                    message='Trailing metadata missing for task schedule',
                )
    async def Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
        idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Put',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.PutAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Put',
                self._rbt_mcp_v1_streammethods_stub.Put,
                request,
                unary=True,
                reader=False,
                response_type=rbt.mcp.v1.stream_pb2.PutResponse,
                aborted_type=Stream.PutAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                await call
                for (key, value) in await call.trailing_metadata():  # type: ignore[misc, attr-defined]
                    if key == IMPORT_reboot_aio_headers.TASK_ID_UUID:
                        return IMPORT_rbt_v1alpha1.tasks_pb2.TaskId(
                            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                            state_ref=self._headers.state_ref.to_str(),
                            task_uuid=IMPORT_uuid.UUID(value).bytes,
                        )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Internal(),
                    message='Trailing metadata missing for task schedule',
                )
    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
        *,
        metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
        idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
        with self._idempotency_manager.idempotently(
            state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._headers.state_ref,
            service_name=IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
            method='Replay',
            mutation=True,
            request=request,
            metadata=metadata,
            idempotency=idempotency,
            aborted_type=Stream.ReplayAborted,
        ) as idempotency_key:
            async with self._call(
                IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
                'Replay',
                self._rbt_mcp_v1_streammethods_stub.Replay,
                request,
                unary=True,
                reader=False,
                response_type=rbt.mcp.v1.stream_pb2.ReplayResponse,
                aborted_type=Stream.ReplayAborted,
                metadata=metadata,
                idempotency_key=idempotency_key,
                bearer_token=bearer_token,
            ) as call:
                assert isinstance(call, IMPORT_typing.Awaitable), type(call)
                await call
                for (key, value) in await call.trailing_metadata():  # type: ignore[misc, attr-defined]
                    if key == IMPORT_reboot_aio_headers.TASK_ID_UUID:
                        return IMPORT_rbt_v1alpha1.tasks_pb2.TaskId(
                            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                            state_ref=self._headers.state_ref.to_str(),
                            task_uuid=IMPORT_uuid.UUID(value).bytes,
                        )
                raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                    IMPORT_rbt_v1alpha1.errors_pb2.Internal(),
                    message='Trailing metadata missing for task schedule',
                )


class StreamServicerTasks:

    _context: IMPORT_reboot_aio_contexts.WriterContext

    def __init__(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        *,
        state_ref: IMPORT_reboot_aio_types.StateRef,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ):
        IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.WriterContext])
        self._context = context
        self._state_ref = state_ref

    # Stream specific methods:
    async def Create(
        self,
        request: google.protobuf.empty_pb2.Empty,
        *,
        schedule: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
    ) -> IMPORT_reboot_aio_tasks.TaskEffect:
        schedule = ensure_has_timezone(when=schedule)
        task = IMPORT_reboot_aio_tasks.TaskEffect(
            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._state_ref,
            method_name='Create',
            request=request,
            schedule=(IMPORT_reboot_time_DateTimeWithTimeZone.now() + schedule) if isinstance(
                schedule, IMPORT_datetime_timedelta
            ) else schedule,
        )

        self._context._tasks.append(task)

        return task

    async def Put(
        self,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
        *,
        schedule: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
    ) -> IMPORT_reboot_aio_tasks.TaskEffect:
        schedule = ensure_has_timezone(when=schedule)
        task = IMPORT_reboot_aio_tasks.TaskEffect(
            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._state_ref,
            method_name='Put',
            request=request,
            schedule=(IMPORT_reboot_time_DateTimeWithTimeZone.now() + schedule) if isinstance(
                schedule, IMPORT_datetime_timedelta
            ) else schedule,
        )

        self._context._tasks.append(task)

        return task

    async def Replay(
        self,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
        *,
        schedule: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
    ) -> IMPORT_reboot_aio_tasks.TaskEffect:
        schedule = ensure_has_timezone(when=schedule)
        task = IMPORT_reboot_aio_tasks.TaskEffect(
            state_type=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
            state_ref=self._state_ref,
            method_name='Replay',
            request=request,
            schedule=(IMPORT_reboot_time_DateTimeWithTimeZone.now() + schedule) if isinstance(
                schedule, IMPORT_datetime_timedelta
            ) else schedule,
        )

        self._context._tasks.append(task)

        return task



############################ Authorizers ############################
# Relevant to servicers; irrelevant to clients.

StreamStateType: IMPORT_typing.TypeAlias = rbt.mcp.v1.stream_pb2.Stream
StreamRequestTypes: IMPORT_typing.TypeAlias = \
        google.protobuf.empty_pb2.Empty \
        | rbt.mcp.v1.stream_pb2.PutRequest \
        | rbt.mcp.v1.stream_pb2.ReplayRequest

class StreamAuthorizer(
    IMPORT_rebootdev.aio.auth.authorizers.Authorizer[StreamStateType, StreamRequestTypes],
):
    StateType: IMPORT_typing.TypeAlias = StreamStateType
    RequestTypes: IMPORT_typing.TypeAlias = StreamRequestTypes
    Decision: IMPORT_typing.TypeAlias = IMPORT_rebootdev.aio.auth.authorizers.Authorizer.Decision

    def __init__(
        self,
        *,
        Create: IMPORT_typing.Optional[
            IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule[
              rbt.mcp.v1.stream_pb2.Stream,
              google.protobuf.empty_pb2.Empty,
            ]
        ] = None,
        Put: IMPORT_typing.Optional[
            IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule[
              rbt.mcp.v1.stream_pb2.Stream,
              rbt.mcp.v1.stream_pb2.PutRequest,
            ]
        ] = None,
        Replay: IMPORT_typing.Optional[
            IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule[
              rbt.mcp.v1.stream_pb2.Stream,
              rbt.mcp.v1.stream_pb2.ReplayRequest,
            ]
        ] = None,
        # NOTE: using `_` prefix for `_default` so as not to collide
        # with any method names since a prefixed `_` is forbidden by
        # our protoc plugins.
        _default: IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule[
            rbt.mcp.v1.stream_pb2.Stream,
            IMPORT_google_protobuf_message.Message,
        ] = IMPORT_rebootdev.aio.auth.authorizers.allow_if(
            all=[IMPORT_rebootdev.aio.auth.authorizers.is_app_internal],
        ),
    ):
        self._Create = Create
        self._Put = Put
        self._Replay = Replay
        self.__default = _default

    async def authorize(
        self,
        *,
        method_name: str,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: IMPORT_typing.Optional[StreamStateType],
        request: IMPORT_typing.Optional[StreamRequestTypes],
        **kwargs,
    ) -> IMPORT_rebootdev.aio.auth.authorizers.Authorizer.Decision:
        if method_name == 'rbt.mcp.v1.StreamMethods.Create':
            return await self.Create(
                context=context,
                state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
                request=IMPORT_typing.cast(google.protobuf.empty_pb2.Empty, request),
            )
        elif method_name == 'rbt.mcp.v1.StreamMethods.Put':
            return await self.Put(
                context=context,
                state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
                request=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.PutRequest, request),
            )
        elif method_name == 'rbt.mcp.v1.StreamMethods.Replay':
            return await self.Replay(
                context=context,
                state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
                request=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.ReplayRequest, request),
            )
        else:
            return IMPORT_rbt_v1alpha1.errors_pb2.PermissionDenied()

    # For 'rbt.mcp.v1.StreamMethods.Create'.
    async def Create(
        self,
        *,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> IMPORT_rebootdev.aio.auth.authorizers.Authorizer.Decision:
        return await (self._Create or self.__default).execute(
            context=context,
            state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
            request=IMPORT_typing.cast(google.protobuf.empty_pb2.Empty, request),
        )

    # For 'rbt.mcp.v1.StreamMethods.Put'.
    async def Put(
        self,
        *,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> IMPORT_rebootdev.aio.auth.authorizers.Authorizer.Decision:
        return await (self._Put or self.__default).execute(
            context=context,
            state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
            request=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.PutRequest, request),
        )

    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    async def Replay(
        self,
        *,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> IMPORT_rebootdev.aio.auth.authorizers.Authorizer.Decision:
        return await (self._Replay or self.__default).execute(
            context=context,
            state=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.Stream, state),
            request=IMPORT_typing.cast(rbt.mcp.v1.stream_pb2.ReplayRequest, request),
        )



############################ Reboot Servicers ############################
# Base classes for server-side implementations of Reboot servicers.
# Irrelevant to clients.

class StreamBaseServicer(IMPORT_reboot_aio_servicers.Servicer):
    Authorizer: IMPORT_typing.TypeAlias = StreamAuthorizer

    __service_names__ = [
        IMPORT_reboot_aio_types.ServiceName('rbt.mcp.v1.StreamMethods'),
    ]
    __state_type_name__ = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream')
    __state_type__ = rbt.mcp.v1.stream_pb2.Stream
    __file_descriptor__ = rbt.mcp.v1.stream_pb2.DESCRIPTOR

    def __init__(self):
        super().__init__()
        # NOTE: need to hold on to the middleware so we can do inline
        # writes (see 'self.write(...)').
        #
        # Because '_middleware' is not really private this does mean
        # users may do possibly dangerous things, but this is no more
        # likely given they could have already overridden
        # 'create_middleware()'.
        self._middleware: IMPORT_typing.Optional[StreamServicerMiddleware] = None

    def create_middleware(
        self,
        *,
        application_id: IMPORT_reboot_aio_types.ApplicationId,
        consensus_id: IMPORT_reboot_aio_types.ConsensusId,
        state_manager: IMPORT_reboot_aio_state_managers.StateManager,
        placement_client: IMPORT_reboot_aio_placement.PlacementClient,
        channel_manager: IMPORT_reboot_aio_internals_channel_manager._ChannelManager,
        tasks_cache: IMPORT_reboot_aio_internals_tasks_cache.TasksCache,
        token_verifier: IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.token_verifiers.TokenVerifier],
        effect_validation: IMPORT_reboot_aio_contexts.EffectValidation,
        app_internal_api_key_secret: str,
        ready: IMPORT_asyncio.Event,
    ) -> StreamServicerMiddleware:
        self._middleware = StreamServicerMiddleware(
            servicer=self,
            application_id=application_id,
            consensus_id=consensus_id,
            state_manager=state_manager,
            placement_client=placement_client,
            channel_manager=channel_manager,
            tasks_cache=tasks_cache,
            token_verifier=token_verifier,
            effect_validation=effect_validation,
            app_internal_api_key_secret=app_internal_api_key_secret,
            ready=ready,
        )
        return self._middleware

    def authorizer(self) -> IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.authorizers.Authorizer | IMPORT_rebootdev.aio.auth.authorizers.AuthorizerRule]:
        return None

    def token_verifier(self) -> IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.token_verifiers.TokenVerifier]:
        return None

    def ref(
        self,
        *,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> Stream.WeakReference[Stream.WeakReference._WriterSchedule]:
        context = IMPORT_reboot_aio_contexts.Context.get()

        if context is None:
            raise RuntimeError(
                'Missing asyncio context variable `context`; '
                'are you using this class without Reboot?'
            )

        return Stream.WeakReference(
            # TODO(https://github.com/reboot-dev/mono/issues/3226): add support for calling other applications.
            # For now this always stays within the application that creates the context.
            application_id=None,
            state_id=context._state_ref.id,
            schedule_type=Stream.WeakReference._WriterSchedule,
            # If the user didn't specify a bearer token we may still end up using the app-internal bearer token,
            # but that's decided at the time of the call.
            bearer_token=bearer_token,
            servicer=self,
        )

    class Effects(IMPORT_reboot_aio_state_managers.Effects):
        def __init__(
            self,
            *,
            state: rbt.mcp.v1.stream_pb2.Stream,
            response: IMPORT_typing.Optional[IMPORT_google_protobuf_message.Message] = None,
            tasks: IMPORT_typing.Optional[list[IMPORT_reboot_aio_tasks.TaskEffect]] = None,
            _colocated_upserts: IMPORT_typing.Optional[list[tuple[str, IMPORT_typing.Optional[bytes]]]] = None,
        ):
            IMPORT_reboot_aio_types.assert_type(state, [rbt.mcp.v1.stream_pb2.Stream])

            super().__init__(state=state, response=response, tasks=tasks, _colocated_upserts=_colocated_upserts)

    # For 'rbt.mcp.v1.StreamMethods.Create'.
    class CreateEffects(Effects):
        def __init__(
            self,
            *,
            state: rbt.mcp.v1.stream_pb2.Stream,
            response: google.protobuf.empty_pb2.Empty,
            tasks: IMPORT_typing.Optional[list[IMPORT_reboot_aio_tasks.TaskEffect]] = None,
            _colocated_upserts: IMPORT_typing.Optional[list[tuple[str, IMPORT_typing.Optional[bytes]]]] = None,
        ):
            IMPORT_reboot_aio_types.assert_type(state, [rbt.mcp.v1.stream_pb2.Stream])
            IMPORT_reboot_aio_types.assert_type(response, [google.protobuf.empty_pb2.Empty])

            super().__init__(state=state, response=response, tasks=tasks, _colocated_upserts=_colocated_upserts)


    # For 'rbt.mcp.v1.StreamMethods.Put'.
    class PutEffects(Effects):
        def __init__(
            self,
            *,
            state: rbt.mcp.v1.stream_pb2.Stream,
            response: rbt.mcp.v1.stream_pb2.PutResponse,
            tasks: IMPORT_typing.Optional[list[IMPORT_reboot_aio_tasks.TaskEffect]] = None,
            _colocated_upserts: IMPORT_typing.Optional[list[tuple[str, IMPORT_typing.Optional[bytes]]]] = None,
        ):
            IMPORT_reboot_aio_types.assert_type(state, [rbt.mcp.v1.stream_pb2.Stream])
            IMPORT_reboot_aio_types.assert_type(response, [rbt.mcp.v1.stream_pb2.PutResponse])

            super().__init__(state=state, response=response, tasks=tasks, _colocated_upserts=_colocated_upserts)




    InlineWriterCallableResult = IMPORT_typing.TypeVar('InlineWriterCallableResult', covariant=True)

    class InlineWriterCallable(IMPORT_typing.Protocol[InlineWriterCallableResult]):
        async def __call__(
            self,
            state: rbt.mcp.v1.stream_pb2.Stream
        ) -> StreamBaseServicer.InlineWriterCallableResult:
            ...

    class WorkflowState:

        def __init__(
            self,
            servicer,
        ):
            self._servicer = servicer

        async def read(
            self, context: IMPORT_reboot_aio_contexts.WorkflowContext
        ) -> rbt.mcp.v1.stream_pb2.Stream:
            """Read the current state within a workflow."""
            return await (
                self.always() if context.within_until()
                else (
                    self.per_iteration() if context.within_loop()
                    else self.per_workflow()
                )
            ).read(context)

        @IMPORT_typing.overload
        async def write(
            self,
            idempotency_alias: str,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[None],
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            *,
            type: type = type(None),
        ) -> None:
            ...

        @IMPORT_typing.overload
        async def write(
            self,
            idempotency_alias: str,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            *,
            type: type[StreamBaseServicer.InlineWriterCallableResult],
        ) -> StreamBaseServicer.InlineWriterCallableResult:
            ...

        async def write(
            self,
            idempotency_alias: str,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            *,
            type: type = type(None),
        ) -> StreamBaseServicer.InlineWriterCallableResult:
            """Perform an "inline write" within a workflow."""
            return await (
                self.per_iteration(idempotency_alias) if context.within_loop()
                else self.per_workflow(idempotency_alias)
            ).write(
                context, writer, __options__, type=type
            )

        class _Idempotently:

            def __init__(
                self,
                *,
                servicer: StreamBaseServicer,
                alias: IMPORT_typing.Optional[str],
                how: IMPORT_reboot_aio_workflows.How,
            ):
                self._servicer = servicer
                self._alias = alias
                self._how = how

            async def read(
                self, context: IMPORT_reboot_aio_contexts.WorkflowContext
            ) -> rbt.mcp.v1.stream_pb2.Stream:
                """Read the current state within a workflow."""
                return await self._read(
                    self._servicer,
                    context.idempotency(
                        key=IMPORT_uuid.uuid4(),
                        generated=True,
                    ) if self._how == IMPORT_reboot_aio_workflows.ALWAYS else context.idempotency(
                        alias=self._alias,
                        each_iteration=self._how == IMPORT_reboot_aio_workflows.PER_ITERATION
                    ),
                    context,
                )

            @staticmethod
            async def _read(
                servicer: StreamBaseServicer,
                idempotency: IMPORT_reboot_aio_idempotency.Idempotency,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
            ) -> rbt.mcp.v1.stream_pb2.Stream:
                """Read the current state within a workflow."""
                IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.WorkflowContext])

                if servicer._middleware is None:
                    raise RuntimeError(
                        'Reboot middleware was not created; '
                        'are you using this class without Reboot?'
                    )

                async def read():
                    assert servicer._middleware is not None
                    return await servicer._middleware._state_manager.read(
                        context, servicer.__state_type__
                    )

                if idempotency.always:
                    return await read()

                state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream')

                # Use the idempotency manager to make sure that this
                # reader is being called following the rules.
                with context.idempotently(
                    state_type_name=state_type_name,
                    state_ref=context._state_ref,
                    # Not calling a method so `service_name`,
                    # `method`, `request`, etc are irrelevant.
                    service_name=None,
                    method=None,
                    mutation=False,
                    request=None,
                    metadata=None,
                    idempotency=idempotency,
                    # Only need to pass `aborted_type` for mutations.
                    aborted_type=None,
                ) as idempotency_key:
                    assert idempotency_key is not None
                    return await IMPORT_reboot_aio_workflows.at_least_once(
                        (
                            # TODO: for easier debugging include the
                            # original alias (or generated alias in
                            # the case of `.per_iteration()` w/o an
                            # alias) instead of just
                            # `idempotency_key`.
                            f"inline reader of '{ state_type_name }' ({str(idempotency_key)})",
                            # NOTE: we want this to be `PER_WORKFLOW`
                            # because any per iteration concerns
                            # should have already been taken care of
                            # by caller using `.per_iteration()`.
                            IMPORT_reboot_aio_workflows.PER_WORKFLOW
                        ),
                        context,
                        read,
                        type=rbt.mcp.v1.stream_pb2.Stream,
                    )

            @IMPORT_typing.overload
            async def write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[None],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                type: type = type(None),
                check_type: bool = True,
            ) -> None:
                ...

            @IMPORT_typing.overload
            async def write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                type: type[StreamBaseServicer.InlineWriterCallableResult],
                check_type: bool = True,
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                ...

            async def write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                type: type = type(None),
                check_type: bool = True,
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                return await self._write(
                    context,
                    writer,
                    __options__,
                    type_result=type,
                    check_type=check_type,
                )

            async def _write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                type_result: type,
                check_type: bool,
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                unidempotently = self._how == IMPORT_reboot_aio_workflows.ALWAYS
                idempotency = (
                    context.idempotency(
                        key=IMPORT_uuid.uuid4(),
                        generated=True,
                    ) if unidempotently else context.idempotency(
                        alias=self._alias,
                        each_iteration=self._how == IMPORT_reboot_aio_workflows.PER_ITERATION
                    )
                )

                return await self._write_validating_effects(
                    self._servicer,
                    idempotency,
                    context,
                    writer,
                    __options__,
                    type_result=type_result,
                    check_type=check_type,
                    unidempotently=unidempotently,
                    checkpoint=context.checkpoint(),
                )

            @staticmethod
            @IMPORT_reboot_aio_internals_middleware.maybe_run_function_twice_to_validate_effects
            async def _write_validating_effects(
                validating_effects: bool,
                servicer: StreamBaseServicer,
                idempotency: IMPORT_reboot_aio_idempotency.Idempotency,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                type_result: type,
                check_type: bool,
                unidempotently: bool,
                checkpoint: IMPORT_reboot_aio_idempotency.Checkpoint,
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    raise RuntimeError(
                        'Found redundant idempotency in `Options`'
                    )

                IMPORT_reboot_aio_types.assert_type(context, [IMPORT_reboot_aio_contexts.WorkflowContext])

                if servicer._middleware is None:
                    raise RuntimeError(
                        'Reboot middleware was not created; '
                        'are you using this class without Reboot?'
                    )

                metadata: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None

                if __options__ is not None:
                    if __options__.metadata is not None:
                        metadata = __options__.metadata

                if metadata is None:
                    metadata = ()

                headers = IMPORT_reboot_aio_headers.Headers(
                    application_id=context.application_id,
                    state_ref=context._state_ref,
                )

                metadata += headers.to_grpc_metadata()

                idempotency_key: IMPORT_typing.Optional[IMPORT_uuid.UUID]
                with context.idempotently(
                    state_type_name=IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                    state_ref=context._state_ref,
                    service_name=None,  # Indicates an inline writer.
                    method=None,  # Indicates an inline writer.
                    mutation=True,
                    request=None,  # Indicates an inline writer.
                    metadata=metadata,
                    idempotency=idempotency,
                    aborted_type=None,  # Indicates an inline writer.
                ) as idempotency_key:

                    if any(t[0] == IMPORT_reboot_aio_headers.IDEMPOTENCY_KEY_HEADER for t in metadata):
                        raise ValueError(
                            f"Do not set '{IMPORT_reboot_aio_headers.IDEMPOTENCY_KEY_HEADER}' metadata yourself"
                        )

                    if idempotency_key is not None:
                        metadata += (
                            (IMPORT_reboot_aio_headers.IDEMPOTENCY_KEY_HEADER, str(idempotency_key)),
                        )

                    with servicer._middleware.use_context(
                        headers=IMPORT_reboot_aio_headers.Headers.from_grpc_metadata(metadata),
                        state_type_name = IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                        method='inline writer',
                        context_type=IMPORT_reboot_aio_contexts.WriterContext,
                    ) as writer_context:
                        # Check if we already have performed this mutation!
                        #
                        # We do this _before_ calling 'transactionally()' because
                        # if this call is for a transaction method _and_ we've
                        # already performed the transaction then we don't want to
                        # become a transaction participant (again) we just want to
                        # return the transaction's response.
                        idempotent_mutation = (
                            servicer._middleware._state_manager.check_for_idempotent_mutation(
                                writer_context
                            )
                        )

                        if idempotent_mutation is not None:
                            assert len(idempotent_mutation.response) != 0
                            response = IMPORT_google_protobuf_wrappers_pb2.BytesValue()
                            response.ParseFromString(idempotent_mutation.response)
                            result: StreamBaseServicer.InlineWriterCallableResult = IMPORT_pickle.loads(response.value)

                            if check_type and type(result) is not type_result:
                                raise TypeError(
                                    f"Stored result of type '{type(result).__name__}' from 'writer' "
                                    f"is not of expected type '{type_result.__name__}'; have you changed "
                                    "the 'type' that you expect after having stored a result?"
                                )

                            return result

                        async with servicer._middleware._state_manager.transactionally(
                            writer_context,
                            servicer._middleware.tasks_dispatcher,
                            aborted_type=None,
                        ) as transaction:
                            async with servicer._middleware._state_manager.writer(
                                writer_context,
                                servicer.__state_type__,
                                servicer._middleware.tasks_dispatcher,
                                # TODO: Decide if we want to do any kind of authorization for inline
                                # writers otherwise passing `None` here is fine.
                                authorize=None,
                                transaction=transaction,
                            ) as (state, state_manager_writer):
                                # Serialize the state so we can see if it changed.
                                serialized_state = state.SerializeToString(
                                    deterministic=True,
                                )

                                result = await writer(state=state)

                                if check_type and type(result) is not type_result:
                                    raise TypeError(
                                        f"Result of type '{type(result).__name__}' from 'writer' is "
                                        f"not of expected type '{type_result.__name__}'; "
                                        "did you specify an incorrect 'type'?"
                                    )

                                task: IMPORT_typing.Optional[IMPORT_reboot_aio_tasks.TaskEffect] = context.task

                                assert task is not None, (
                                    "Should always have a task when running a `workflow`"
                                )

                                method_name = f"Stream.{task.method_name} inline writer"

                                if idempotency.alias is not None:
                                    method_name += " with idempotency alias '" + idempotency.alias + "'"
                                elif idempotency.key is not None:
                                    method_name += " with idempotency key=" + str(idempotency.key)

                                servicer._middleware.maybe_raise_effect_validation_retry(
                                    logger=logger,
                                    idempotency_manager=context,
                                    method_name=method_name,
                                    validating_effects=validating_effects,
                                    context=context,
                                    checkpoint=checkpoint,
                                )

                                # We don't pass the context to the
                                # writer, so we don't expect there to
                                # be any scheduled tasks!
                                assert len(context._tasks) == 0

                                effects = IMPORT_reboot_aio_state_managers.Effects(
                                    state=(
                                        # Pass `None` if the state hasn't changed!
                                        state if serialized_state != state.SerializeToString(
                                            deterministic=True,
                                        )
                                        else None
                                    ),
                                    response=IMPORT_google_protobuf_wrappers_pb2.BytesValue(
                                        value=IMPORT_pickle.dumps(result)
                                    ),
                                )

                                await state_manager_writer.complete(effects)

                                return result

        def per_workflow(self, alias: IMPORT_typing.Optional[str] = None):
            return StreamBaseServicer.WorkflowState._Idempotently(
                servicer=self._servicer,
                alias=alias,
                how=IMPORT_reboot_aio_workflows.PER_WORKFLOW,
            )

        def per_iteration(self, alias: IMPORT_typing.Optional[str] = None):
            return StreamBaseServicer.WorkflowState._Idempotently(
                servicer=self._servicer,
                alias=alias,
                how=IMPORT_reboot_aio_workflows.PER_ITERATION,
            )

        class _Always:
            """Helper class for providing better types for `write` that don't
            require passing `type` or `check_type`."""

            def __init__(
                self,
                *,
                servicer: StreamBaseServicer,
            ):
                self._servicer = servicer

            async def read(
                self, context: IMPORT_reboot_aio_contexts.WorkflowContext
            ) -> rbt.mcp.v1.stream_pb2.Stream:
                return await StreamBaseServicer.WorkflowState._Idempotently(
                    servicer=self._servicer,
                    alias=None,
                    how=IMPORT_reboot_aio_workflows.ALWAYS,
                ).read(context)

            async def write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                return await StreamBaseServicer.WorkflowState._Idempotently(
                    servicer=self._servicer,
                    alias=None,
                    how=IMPORT_reboot_aio_workflows.ALWAYS,
                )._write(
                    context,
                    writer,
                    __options__,
                    type_result=type(None),
                    check_type=False,
                )

        def always(self):
            return StreamBaseServicer.WorkflowState._Always(
                servicer=self._servicer,
            )

    # For 'rbt.mcp.v1.StreamMethods.Create'.
    @IMPORT_abc_abstractmethod
    async def _Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Put'.
    @IMPORT_abc_abstractmethod
    async def _Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    @IMPORT_abc_abstractmethod
    async def _Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        raise NotImplementedError



class StreamSingletonServicer(StreamBaseServicer):

    @property
    def state(self):
        return StreamBaseServicer.WorkflowState(
            servicer=self
        )

    # For 'rbt.mcp.v1.StreamMethods.Create'.
    @IMPORT_abc_abstractmethod
    async def Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Put'.
    @IMPORT_abc_abstractmethod
    async def Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    @IMPORT_abc_abstractmethod
    async def Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        raise NotImplementedError


    # For 'rbt.mcp.v1.StreamMethods.Create'.
    async def _Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        # Wrap the call to the developer's method in a `span` so that it
        # is traced using its fully-qualified Python name.
        with IMPORT_reboot_aio_tracing.span(
                state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(self)}.Create()",
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                python_specific=True,
        ):
            return await self.Create(context, state, request)


    # For 'rbt.mcp.v1.StreamMethods.Put'.
    async def _Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        # Wrap the call to the developer's method in a `span` so that it
        # is traced using its fully-qualified Python name.
        with IMPORT_reboot_aio_tracing.span(
                state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(self)}.Put()",
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                python_specific=True,
        ):
            return await self.Put(context, state, request)


    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    async def _Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        # Wrap the call to the developer's method in a `span` so that it
        # is traced using its fully-qualified Python name.
        with IMPORT_reboot_aio_tracing.span(
                state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(self)}.Replay()",
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                python_specific=True,
        ):
            response = (
                self.Replay(
                    context,
                    state,
                    request,
                )
            )
            return await response



class StreamServicer(StreamBaseServicer):

    _state: IMPORT_contextvars.ContextVar[
        IMPORT_typing.Optional[rbt.mcp.v1.stream_pb2.Stream]
    ] = IMPORT_contextvars.ContextVar(
        'Provides access to state for each call, i.e., there may be '
        'multiple readers executing concurrently but each might have '
        'a different `state`',
        default=None,
    )

    _workflow: IMPORT_contextvars.ContextVar[bool] = IMPORT_contextvars.ContextVar(
        'Whether or not current context is executing a workflow',
        default=False,
    )

    # An instance of the derived class for each state.
    _instances: dict[str, StreamServicer] = {}

    def _instance(self, state_id: str):
        instances = StreamServicer._instances
        instance = instances.get(state_id)
        if instance is None:
            instance = self.__class__()
            instance._middleware = self._middleware
        instances[state_id] = instance
        return instance

    @property
    def state(self) -> rbt.mcp.v1.stream_pb2.Stream:
        state = StreamServicer._state.get()
        if state is None:
            raise RuntimeError(
                "`state` property is only relevant within a `Servicer` method"
            )
        workflow = StreamServicer._workflow.get()
        if workflow:
            raise RuntimeError(
                "`self.state` is not valid within a `workflow` because a "
                "`workflow ` is not _atomic_; use "
                "`await self.ref().read(context)` instead"
            )
        return state

    @state.setter
    def state(self, new_state: rbt.mcp.v1.stream_pb2.Stream):
        state = StreamServicer._state.get()
        if state is None:
            raise RuntimeError(
                "`state` property is only relevant within a `Servicer` method"
            )
        workflow = StreamServicer._workflow.get()
        if workflow:
            raise RuntimeError(
                "`self.state` is not valid within a `workflow` because a "
                "`workflow ` is not _atomic_; use "
                "`await self.ref().write(...)` instead"
            )
        state.CopyFrom(new_state)

    # For 'rbt.mcp.v1.StreamMethods.Create'.
    @IMPORT_abc_abstractmethod
    async def Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Put'.
    @IMPORT_abc_abstractmethod
    async def Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        raise NotImplementedError

    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    @IMPORT_abc_abstractmethod
    async def Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        raise NotImplementedError


    # For 'rbt.mcp.v1.StreamMethods.Create'.
    async def _Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        # We should have an asyncio task and thus context per request,
        # let's confirm this assumption by making sure that
        # `_state is None`.
        assert StreamServicer._state.get() is None
        StreamServicer._state.set(state)
        try:
            # Wrap the call to the developer's method in a `span` so that it
            # is traced using its fully-qualified Python name.
            instance = self._instance(context.state_id)
            with IMPORT_reboot_aio_tracing.span(
                    state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                    span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(instance)}.Create()",
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                    python_specific=True,
            ):
                return await instance.Create(context, request)
        finally:
            StreamServicer._state.set(None)

    # For 'rbt.mcp.v1.StreamMethods.Put'.
    async def _Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        # We should have an asyncio task and thus context per request,
        # let's confirm this assumption by making sure that
        # `_state is None`.
        assert StreamServicer._state.get() is None
        StreamServicer._state.set(state)
        try:
            # Wrap the call to the developer's method in a `span` so that it
            # is traced using its fully-qualified Python name.
            instance = self._instance(context.state_id)
            with IMPORT_reboot_aio_tracing.span(
                    state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                    span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(instance)}.Put()",
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                    python_specific=True,
            ):
                return await instance.Put(context, request)
        finally:
            StreamServicer._state.set(None)

    # For 'rbt.mcp.v1.StreamMethods.Replay'.
    async def _Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        # We should have an asyncio task and thus context per request,
        # let's confirm this assumption by making sure that
        # `_state is None`.
        assert StreamServicer._state.get() is None
        StreamServicer._state.set(state)
        try:
            # Wrap the call to the developer's method in a `span` so that it
            # is traced using its fully-qualified Python name.
            instance = self._instance(context.state_id)
            with IMPORT_reboot_aio_tracing.span(
                    state_name=f"rbt.mcp.v1.Stream('{context.state_id}')",
                    span_name=f"{IMPORT_reboot_aio_tracing.qualified_type_name(instance)}.Replay()",
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                    python_specific=True,
            ):
                return await instance.Replay(context, request)
        finally:
            StreamServicer._state.set(None)



############################ Clients ############################
# The main developer-facing entrypoints for any Reboot type. Relevant to both
# clients and servicers (who use it to find the right servicer base types, as well
# as often being clients themselves).

# Attach an explicit time time zone to "naive" `datetime` objects. A "naive" `datetime` doesn't have a
# time zone. Such objects are typically interpreted as representing local time, but could be confused
# for objects representing UTC. This helper function disambiguates by explicitly attaching the local
# time zone to `datetime` objects that don't already have an explicit time zone. If the `datetime` object
# is already timezone-aware, we still convert it to our custom `DateTimeWithTimeZone` type.
def ensure_has_timezone(
    *,
    when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
) -> IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone | IMPORT_datetime_timedelta]:
    if isinstance(when, IMPORT_datetime_datetime):
        return IMPORT_reboot_time_DateTimeWithTimeZone.from_datetime(when)
    return when

Stream_ScheduleTypeVar = IMPORT_typing.TypeVar('Stream_ScheduleTypeVar', 'Stream.WeakReference._Schedule', 'Stream.WeakReference._WriterSchedule')
Stream_IdempotentlyScheduleTypeVar = IMPORT_typing.TypeVar('Stream_IdempotentlyScheduleTypeVar', 'Stream.WeakReference._Schedule', 'Stream.WeakReference._WriterSchedule')

Stream_UntilCallableType = IMPORT_typing.TypeVar('Stream_UntilCallableType')

class StreamSingleton:
    Servicer: IMPORT_typing.TypeAlias = StreamSingletonServicer


class Stream:


    Servicer: IMPORT_typing.TypeAlias = StreamServicer

    singleton: IMPORT_typing.TypeAlias = StreamSingleton

    Effects: IMPORT_typing.TypeAlias = StreamBaseServicer.Effects

    Authorizer: IMPORT_typing.TypeAlias = StreamAuthorizer

    State: IMPORT_typing.TypeAlias = rbt.mcp.v1.stream_pb2.Stream

    __state_type_name__ = IMPORT_reboot_aio_types.StateTypeName("rbt.mcp.v1.Stream")

    class CreateTask:
        """Represents a scheduled task running for the
        state. Note that this is not a coroutine because we are trying
        to convey the semantics that the task is already running (or
        will soon be).
        """

        @classmethod
        def retrieve(
            cls,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ):
            return cls(context, task_id=task_id)

        def __init__(
            self,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ) -> None:
            # Depending on the context type (inside or outside a Reboot application)
            # we may or may not know the application ID. If we don't know it, then
            # the `ExternalContext.gateway` will determine it.
            #
            # TODO: in the future we expect to support cross-application calls, in
            #       which case the developer may explicitly pass in an application ID
            #       here.
            self._application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId] = None
            if isinstance(context, IMPORT_reboot_aio_contexts.Context):
                self._application_id = context.application_id
            self._channel_manager = context.channel_manager
            self._task_id = task_id

        @property
        def task_id(self) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
            return self._task_id

        def __await__(self) -> IMPORT_typing.Generator[None, None, google.protobuf.empty_pb2.Empty]:
            """Awaits for task to finish and returns its response."""
            async def wait_for_task() -> google.protobuf.empty_pb2.Empty:
                channel = self._channel_manager.get_channel_to_state(
                    self._task_id.state_type,
                    IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                )

                stub = IMPORT_rbt_v1alpha1.tasks_pb2_grpc.TasksStub(channel)

                try:
                    call = IMPORT_reboot_aio_stubs.UnaryRetriedCall(
                        call=None,  # `RetriedCall` can create the call itself.
                        stub_method=stub.Wait,
                        method_name="Wait",
                        request=IMPORT_rbt_v1alpha1.tasks_pb2.WaitRequest(task_id=self._task_id),
                        metadata=IMPORT_reboot_aio_headers.Headers(
                            state_ref=IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                            application_id=self._application_id,
                        ).to_grpc_metadata(),
                        aborted_type=IMPORT_rebootdev.aio.aborted.SystemAborted,
                    )

                    wait_for_task_response = await call
                except IMPORT_rebootdev.aio.aborted.SystemAborted as error:
                    if error.code == IMPORT_grpc.StatusCode.NOT_FOUND:
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.UnknownTask()
                        ) from None

                    raise
                else:
                    response_or_error: IMPORT_typing.Optional[IMPORT_google_protobuf_any_pb2.Any] = None
                    is_error = False

                    if wait_for_task_response.response_or_error.WhichOneof("response_or_error") == "response":
                        response_or_error = wait_for_task_response.response_or_error.response
                    else:
                        is_error = True
                        response_or_error = wait_for_task_response.response_or_error.error

                    assert response_or_error is not None
                    assert response_or_error.TypeName() != ""

                    response = google.protobuf.empty_pb2.Empty()

                    if (
                        not is_error and response_or_error.TypeName() != response.DESCRIPTOR.full_name
                    ):
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.InvalidArgument(),
                            message=
                            f"task with UUID {str(IMPORT_uuid.UUID(bytes=self._task_id.task_uuid))} "
                            f"has a response of type '{response_or_error.TypeName()}' "
                            "but expecting type 'google.protobuf.empty_pb2.Empty'; "
                            "are you waiting on a task of the correct method?",
                        ) from None

                    if is_error:
                        # Currently only cancelled error is supported.
                        raise IMPORT_asyncio.CancelledError("Task was cancelled by a TasksServicer")
                    else:
                        response_or_error.Unpack(response)
                        return response

            return wait_for_task().__await__()

    CreateEffects: IMPORT_typing.TypeAlias = StreamBaseServicer.CreateEffects

    class CreateAborted(IMPORT_rebootdev.aio.aborted.Aborted):


        Error = IMPORT_typing.Union[
            IMPORT_rebootdev.aio.aborted.GrpcError,
            IMPORT_rebootdev.aio.aborted.RebootError,
        ]

        METHOD_ERROR_TYPES: list[type[Error]] = [
        ]

        ERROR_TYPES: list[type[Error]] = (
            METHOD_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.REBOOT_ERROR_TYPES
        )

        _error: Error
        _code: IMPORT_grpc.StatusCode
        _message: IMPORT_typing.Optional[str]

        def __init__(
            self,
            error:  IMPORT_rebootdev.aio.aborted.GrpcError,
            *,
            message: IMPORT_typing.Optional[str] = None,
            # Do not set this value when constructing in order to
            # raise. This is only used internally when constructing
            # from aborted calls.
            error_types: list[type[Error]] = (
                METHOD_ERROR_TYPES + IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES
            ),
        ):
            super().__init__()

            IMPORT_reboot_aio_types.assert_type(error, error_types)

            self._error = error

            code = self.grpc_status_code_from_error(self._error)

            if code is None:
                # Must be a Reboot specific or declared method error.
                code = IMPORT_grpc.StatusCode.ABORTED

            self._code = code

            self._message = message

        @property
        def error(self) -> Error:
            return self._error

        @property
        def code(self) -> IMPORT_grpc.StatusCode:
            return self._code

        @property
        def message(self) -> IMPORT_typing.Optional[str]:
            return self._message

        @classmethod
        def from_status(cls, status: IMPORT_google_rpc_status_pb2.Status):
            error = cls.error_from_google_rpc_status_details(
                status,
                cls.ERROR_TYPES,
            )

            message = status.message if len(status.message) > 0 else None

            if error is not None:
                return cls(error, message=message, error_types=cls.ERROR_TYPES)

            error = cls.error_from_google_rpc_status_code(status)

            assert error is not None

            # TODO(benh): also consider getting the type names from
            # `status.details` and including that in `message` to make
            # debugging easier.

            return cls(error, message=message)

        @classmethod
        def from_grpc_aio_rpc_error(cls, aio_rpc_error: IMPORT_grpc.aio.AioRpcError):
            return cls(
                cls.error_from_grpc_aio_rpc_error(aio_rpc_error),
                message=aio_rpc_error.details(),
            )

        @classmethod
        def is_declared_error(cls, message: IMPORT_google_protobuf_message.Message) -> bool:
            return False

    class PutTask:
        """Represents a scheduled task running for the
        state. Note that this is not a coroutine because we are trying
        to convey the semantics that the task is already running (or
        will soon be).
        """

        @classmethod
        def retrieve(
            cls,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ):
            return cls(context, task_id=task_id)

        def __init__(
            self,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ) -> None:
            # Depending on the context type (inside or outside a Reboot application)
            # we may or may not know the application ID. If we don't know it, then
            # the `ExternalContext.gateway` will determine it.
            #
            # TODO: in the future we expect to support cross-application calls, in
            #       which case the developer may explicitly pass in an application ID
            #       here.
            self._application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId] = None
            if isinstance(context, IMPORT_reboot_aio_contexts.Context):
                self._application_id = context.application_id
            self._channel_manager = context.channel_manager
            self._task_id = task_id

        @property
        def task_id(self) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
            return self._task_id

        def __await__(self) -> IMPORT_typing.Generator[None, None, rbt.mcp.v1.stream_pb2.PutResponse]:
            """Awaits for task to finish and returns its response."""
            async def wait_for_task() -> rbt.mcp.v1.stream_pb2.PutResponse:
                channel = self._channel_manager.get_channel_to_state(
                    self._task_id.state_type,
                    IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                )

                stub = IMPORT_rbt_v1alpha1.tasks_pb2_grpc.TasksStub(channel)

                try:
                    call = IMPORT_reboot_aio_stubs.UnaryRetriedCall(
                        call=None,  # `RetriedCall` can create the call itself.
                        stub_method=stub.Wait,
                        method_name="Wait",
                        request=IMPORT_rbt_v1alpha1.tasks_pb2.WaitRequest(task_id=self._task_id),
                        metadata=IMPORT_reboot_aio_headers.Headers(
                            state_ref=IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                            application_id=self._application_id,
                        ).to_grpc_metadata(),
                        aborted_type=IMPORT_rebootdev.aio.aborted.SystemAborted,
                    )

                    wait_for_task_response = await call
                except IMPORT_rebootdev.aio.aborted.SystemAborted as error:
                    if error.code == IMPORT_grpc.StatusCode.NOT_FOUND:
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.UnknownTask()
                        ) from None

                    raise
                else:
                    response_or_error: IMPORT_typing.Optional[IMPORT_google_protobuf_any_pb2.Any] = None
                    is_error = False

                    if wait_for_task_response.response_or_error.WhichOneof("response_or_error") == "response":
                        response_or_error = wait_for_task_response.response_or_error.response
                    else:
                        is_error = True
                        response_or_error = wait_for_task_response.response_or_error.error

                    assert response_or_error is not None
                    assert response_or_error.TypeName() != ""

                    response = rbt.mcp.v1.stream_pb2.PutResponse()

                    if (
                        not is_error and response_or_error.TypeName() != response.DESCRIPTOR.full_name
                    ):
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.InvalidArgument(),
                            message=
                            f"task with UUID {str(IMPORT_uuid.UUID(bytes=self._task_id.task_uuid))} "
                            f"has a response of type '{response_or_error.TypeName()}' "
                            "but expecting type 'rbt.mcp.v1.stream_pb2.PutResponse'; "
                            "are you waiting on a task of the correct method?",
                        ) from None

                    if is_error:
                        # Currently only cancelled error is supported.
                        raise IMPORT_asyncio.CancelledError("Task was cancelled by a TasksServicer")
                    else:
                        response_or_error.Unpack(response)
                        return response

            return wait_for_task().__await__()

    PutEffects: IMPORT_typing.TypeAlias = StreamBaseServicer.PutEffects

    class PutAborted(IMPORT_rebootdev.aio.aborted.Aborted):


        Error = IMPORT_typing.Union[
            IMPORT_rebootdev.aio.aborted.GrpcError,
            IMPORT_rebootdev.aio.aborted.RebootError,
        ]

        METHOD_ERROR_TYPES: list[type[Error]] = [
        ]

        ERROR_TYPES: list[type[Error]] = (
            METHOD_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.REBOOT_ERROR_TYPES
        )

        _error: Error
        _code: IMPORT_grpc.StatusCode
        _message: IMPORT_typing.Optional[str]

        def __init__(
            self,
            error:  IMPORT_rebootdev.aio.aborted.GrpcError,
            *,
            message: IMPORT_typing.Optional[str] = None,
            # Do not set this value when constructing in order to
            # raise. This is only used internally when constructing
            # from aborted calls.
            error_types: list[type[Error]] = (
                METHOD_ERROR_TYPES + IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES
            ),
        ):
            super().__init__()

            IMPORT_reboot_aio_types.assert_type(error, error_types)

            self._error = error

            code = self.grpc_status_code_from_error(self._error)

            if code is None:
                # Must be a Reboot specific or declared method error.
                code = IMPORT_grpc.StatusCode.ABORTED

            self._code = code

            self._message = message

        @property
        def error(self) -> Error:
            return self._error

        @property
        def code(self) -> IMPORT_grpc.StatusCode:
            return self._code

        @property
        def message(self) -> IMPORT_typing.Optional[str]:
            return self._message

        @classmethod
        def from_status(cls, status: IMPORT_google_rpc_status_pb2.Status):
            error = cls.error_from_google_rpc_status_details(
                status,
                cls.ERROR_TYPES,
            )

            message = status.message if len(status.message) > 0 else None

            if error is not None:
                return cls(error, message=message, error_types=cls.ERROR_TYPES)

            error = cls.error_from_google_rpc_status_code(status)

            assert error is not None

            # TODO(benh): also consider getting the type names from
            # `status.details` and including that in `message` to make
            # debugging easier.

            return cls(error, message=message)

        @classmethod
        def from_grpc_aio_rpc_error(cls, aio_rpc_error: IMPORT_grpc.aio.AioRpcError):
            return cls(
                cls.error_from_grpc_aio_rpc_error(aio_rpc_error),
                message=aio_rpc_error.details(),
            )

        @classmethod
        def is_declared_error(cls, message: IMPORT_google_protobuf_message.Message) -> bool:
            return False

    class ReplayTask:
        """Represents a scheduled task running for the
        state. Note that this is not a coroutine because we are trying
        to convey the semantics that the task is already running (or
        will soon be).
        """

        @classmethod
        def retrieve(
            cls,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ):
            return cls(context, task_id=task_id)

        def __init__(
            self,
            context: IMPORT_reboot_aio_contexts.Context | IMPORT_reboot_aio_external.ExternalContext,
            *,
            task_id: IMPORT_rbt_v1alpha1.tasks_pb2.TaskId,
        ) -> None:
            # Depending on the context type (inside or outside a Reboot application)
            # we may or may not know the application ID. If we don't know it, then
            # the `ExternalContext.gateway` will determine it.
            #
            # TODO: in the future we expect to support cross-application calls, in
            #       which case the developer may explicitly pass in an application ID
            #       here.
            self._application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId] = None
            if isinstance(context, IMPORT_reboot_aio_contexts.Context):
                self._application_id = context.application_id
            self._channel_manager = context.channel_manager
            self._task_id = task_id

        @property
        def task_id(self) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
            return self._task_id

        def __await__(self) -> IMPORT_typing.Generator[None, None, rbt.mcp.v1.stream_pb2.ReplayResponse]:
            """Awaits for task to finish and returns its response."""
            async def wait_for_task() -> rbt.mcp.v1.stream_pb2.ReplayResponse:
                channel = self._channel_manager.get_channel_to_state(
                    self._task_id.state_type,
                    IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                )

                stub = IMPORT_rbt_v1alpha1.tasks_pb2_grpc.TasksStub(channel)

                try:
                    call = IMPORT_reboot_aio_stubs.UnaryRetriedCall(
                        call=None,  # `RetriedCall` can create the call itself.
                        stub_method=stub.Wait,
                        method_name="Wait",
                        request=IMPORT_rbt_v1alpha1.tasks_pb2.WaitRequest(task_id=self._task_id),
                        metadata=IMPORT_reboot_aio_headers.Headers(
                            state_ref=IMPORT_reboot_aio_types.StateRef(self._task_id.state_ref),
                            application_id=self._application_id,
                        ).to_grpc_metadata(),
                        aborted_type=IMPORT_rebootdev.aio.aborted.SystemAborted,
                    )

                    wait_for_task_response = await call
                except IMPORT_rebootdev.aio.aborted.SystemAborted as error:
                    if error.code == IMPORT_grpc.StatusCode.NOT_FOUND:
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.UnknownTask()
                        ) from None

                    raise
                else:
                    response_or_error: IMPORT_typing.Optional[IMPORT_google_protobuf_any_pb2.Any] = None
                    is_error = False

                    if wait_for_task_response.response_or_error.WhichOneof("response_or_error") == "response":
                        response_or_error = wait_for_task_response.response_or_error.response
                    else:
                        is_error = True
                        response_or_error = wait_for_task_response.response_or_error.error

                    assert response_or_error is not None
                    assert response_or_error.TypeName() != ""

                    response = rbt.mcp.v1.stream_pb2.ReplayResponse()

                    if (
                        not is_error and response_or_error.TypeName() != response.DESCRIPTOR.full_name
                    ):
                        raise IMPORT_rebootdev.aio.aborted.SystemAborted(
                            IMPORT_rbt_v1alpha1.errors_pb2.InvalidArgument(),
                            message=
                            f"task with UUID {str(IMPORT_uuid.UUID(bytes=self._task_id.task_uuid))} "
                            f"has a response of type '{response_or_error.TypeName()}' "
                            "but expecting type 'rbt.mcp.v1.stream_pb2.ReplayResponse'; "
                            "are you waiting on a task of the correct method?",
                        ) from None

                    if is_error:
                        # Currently only cancelled error is supported.
                        raise IMPORT_asyncio.CancelledError("Task was cancelled by a TasksServicer")
                    else:
                        response_or_error.Unpack(response)
                        return response

            return wait_for_task().__await__()


    class ReplayAborted(IMPORT_rebootdev.aio.aborted.Aborted):


        Error = IMPORT_typing.Union[
            IMPORT_rebootdev.aio.aborted.GrpcError,
            IMPORT_rebootdev.aio.aborted.RebootError,
        ]

        METHOD_ERROR_TYPES: list[type[Error]] = [
        ]

        ERROR_TYPES: list[type[Error]] = (
            METHOD_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES +
            IMPORT_rebootdev.aio.aborted.REBOOT_ERROR_TYPES
        )

        _error: Error
        _code: IMPORT_grpc.StatusCode
        _message: IMPORT_typing.Optional[str]

        def __init__(
            self,
            error:  IMPORT_rebootdev.aio.aborted.GrpcError,
            *,
            message: IMPORT_typing.Optional[str] = None,
            # Do not set this value when constructing in order to
            # raise. This is only used internally when constructing
            # from aborted calls.
            error_types: list[type[Error]] = (
                METHOD_ERROR_TYPES + IMPORT_rebootdev.aio.aborted.GRPC_ERROR_TYPES
            ),
        ):
            super().__init__()

            IMPORT_reboot_aio_types.assert_type(error, error_types)

            self._error = error

            code = self.grpc_status_code_from_error(self._error)

            if code is None:
                # Must be a Reboot specific or declared method error.
                code = IMPORT_grpc.StatusCode.ABORTED

            self._code = code

            self._message = message

        @property
        def error(self) -> Error:
            return self._error

        @property
        def code(self) -> IMPORT_grpc.StatusCode:
            return self._code

        @property
        def message(self) -> IMPORT_typing.Optional[str]:
            return self._message

        @classmethod
        def from_status(cls, status: IMPORT_google_rpc_status_pb2.Status):
            error = cls.error_from_google_rpc_status_details(
                status,
                cls.ERROR_TYPES,
            )

            message = status.message if len(status.message) > 0 else None

            if error is not None:
                return cls(error, message=message, error_types=cls.ERROR_TYPES)

            error = cls.error_from_google_rpc_status_code(status)

            assert error is not None

            # TODO(benh): also consider getting the type names from
            # `status.details` and including that in `message` to make
            # debugging easier.

            return cls(error, message=message)

        @classmethod
        def from_grpc_aio_rpc_error(cls, aio_rpc_error: IMPORT_grpc.aio.AioRpcError):
            return cls(
                cls.error_from_grpc_aio_rpc_error(aio_rpc_error),
                message=aio_rpc_error.details(),
            )

        @classmethod
        def is_declared_error(cls, message: IMPORT_google_protobuf_message.Message) -> bool:
            return False


    class WeakReference(IMPORT_typing.Generic[Stream_ScheduleTypeVar]):

        _schedule_type: type[Stream_ScheduleTypeVar]

        def __init__(
            self,
            # When application ID is None, refers to a state within the application given by the context.
            application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId],
            state_id: IMPORT_reboot_aio_types.StateId,
            *,
            schedule_type: type[Stream_ScheduleTypeVar],
            bearer_token: IMPORT_typing.Optional[str] = None,
            servicer: IMPORT_typing.Optional[StreamBaseServicer] = None,
        ):
            self._application_id = application_id
            self._state_ref = IMPORT_reboot_aio_types.StateRef.from_id(
              Stream.__state_type_name__,
              state_id,
            )
            self._schedule_type = schedule_type
            self._idempotency_manager: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.IdempotencyManager] = None
            self._reader_stub: IMPORT_typing.Optional[StreamReaderStub] = None
            self._writer_stub: IMPORT_typing.Optional[StreamWriterStub] = None
            self._workflow_stub: IMPORT_typing.Optional[StreamWorkflowStub] = None
            self._tasks_stub: IMPORT_typing.Optional[StreamTasksStub] = None
            self._bearer_token = bearer_token
            self._servicer = servicer

        @property
        def state_id(self) -> IMPORT_reboot_aio_types.StateId:
            return self._state_ref.id

        def _reader(
            self,
            context: IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        ) -> StreamReaderStub:
            if self._reader_stub is None:
                self._reader_stub = StreamReaderStub(
                    context=context,
                    state_ref=self._state_ref,
                    bearer_token=self._bearer_token,
                )
            assert self._reader_stub is not None
            if self._idempotency_manager is None:
                self._idempotency_manager = context
            elif self._idempotency_manager != context:
                raise IMPORT_reboot_aio_call.MixedContextsError(
                    "This `WeakReference` for `Stream` with ID "
                    f"'{self.state_id}' has previously been used by a "
                    "different `Context`. That is not allowed. "
                    "Instead create a new `WeakReference` for every `Context` by calling "
                    f"`Stream.ref('{self.state_id}')`."
                )
            return self._reader_stub

        def _writer(
            self,
            context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        ) -> StreamWriterStub:
            if self._writer_stub is None:
                self._writer_stub = StreamWriterStub(
                    context=context,
                    state_ref=self._state_ref,
                    bearer_token=self._bearer_token,
                )
            assert self._writer_stub is not None
            if self._idempotency_manager is None:
                self._idempotency_manager = context
            elif self._idempotency_manager != context:
                raise IMPORT_reboot_aio_call.MixedContextsError(
                    "This `WeakReference` for `Stream` with ID "
                    f"'{self.state_id}' has previously been used by a "
                    "different `Context`. That is not allowed. "
                    "Instead create a new `WeakReference` for every `Context` by calling "
                    f"`Stream.ref('{self.state_id}')`."
                )
            return self._writer_stub

        def _workflow(
            self,
            context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        ) -> StreamWorkflowStub:
            if self._workflow_stub is None:
                self._workflow_stub = StreamWorkflowStub(
                    context=context,
                    state_ref=self._state_ref,
                    bearer_token=self._bearer_token,
                )
            assert self._workflow_stub is not None
            if self._idempotency_manager is None:
                self._idempotency_manager = context
            elif self._idempotency_manager != context:
                raise IMPORT_reboot_aio_call.MixedContextsError(
                    "This `WeakReference` for `Stream` with ID "
                    f"'{self.state_id}' has previously been used by a "
                    "different `Context`. That is not allowed. "
                    "Instead create a new `WeakReference` for every `Context` by calling "
                    f"`Stream.ref('{self.state_id}')`."
                )
            return self._workflow_stub

        def _tasks(
            self,
            context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        ) -> StreamTasksStub:
            if self._tasks_stub is None:
                self._tasks_stub = StreamTasksStub(
                    context=context,
                    state_ref=self._state_ref,
                    bearer_token=self._bearer_token,
                )
            assert self._tasks_stub is not None
            if self._idempotency_manager is None:
                self._idempotency_manager = context
            elif self._idempotency_manager != context:
                raise IMPORT_reboot_aio_call.MixedContextsError(
                    "This `WeakReference` for `Stream` with ID "
                    f"'{self.state_id}' has previously been used by a "
                    "different `Context`. That is not allowed. "
                    "Instead create a new `WeakReference` for every `Context` by calling "
                    f"`Stream.ref('{self.state_id}')`."
                )
            return self._tasks_stub

        class _Reactively:

            def __init__(
                self,
                *,
                application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId],
                state_ref: IMPORT_reboot_aio_types.StateRef,
                bearer_token: IMPORT_typing.Optional[str] = None,
            ):
                self._application_id = application_id
                self._state_ref = state_ref
                self._bearer_token = bearer_token

            async def Replay(
                # In methods which are dealing with user input, (i.e.,
                # proto message field names), we should use '__double_underscored__'
                # variables to avoid any potential name conflicts with the method's
                # parameters.
                # The '__self__' parameter is a convention in Python to
                # indicate that this method is a bound method, so we use
                # '__this__' instead.
                __this__,
                # Explicitly-reactive calls only make sense in the context of either...
                # (A) an external client, or...
                # (B) methods that may reasonably run for a long time, which in Reboot means: readers or workflows.
                __context__: IMPORT_reboot_aio_external.ExternalContext | IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WorkflowContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> IMPORT_typing.AsyncIterator[rbt.mcp.v1.stream_pb2.ReplayResponse]:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_external.ExternalContext, IMPORT_reboot_aio_contexts.ReaderContext, IMPORT_reboot_aio_contexts.WorkflowContext])

                # TODO: mypy-protobuf declares that
                # `google.protobuf.message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.ReplayRequest(
                    last_event_id=last_event_id,  # type: ignore[arg-type]
                )

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __bearer_token__: IMPORT_typing.Optional[str] = None
                __app_internal_authorization__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                if __bearer_token__ is None:
                    __bearer_token__ = __this__._bearer_token
                if __bearer_token__ is None and isinstance(__context__, IMPORT_reboot_aio_external.ExternalContext):
                    # Within a Reboot context we do not pass on the caller's bearer token, as that might
                    # have security implications - we cannot simply trust any service we are calling with
                    # the user's credentials. Instead, the developer can rely on the default app-internal
                    # auth, or override that and set an explicit bearer token.
                    #
                    # In the case of `ExternalContext`, however, its `bearer_token` was set specifically
                    # by the developer for the purpose of making these calls. Note that only
                    # `ExternalContext` even has a `bearer_token` field.
                    __bearer_token__ = __context__.bearer_token

                if __metadata__ is None:
                    __metadata__ = ()

                if isinstance(__context__, IMPORT_reboot_aio_contexts.Context):
                    if __this__._application_id is None:
                        # Given our context type (inside a Reboot application) we can default to
                        # making the application send traffic to itself.
                        __this__._application_id = __context__.application_id
                        # It is safe to use app-internal auth given we know we're talking to
                        # the same application.
                        __app_internal_authorization__ = __context__._app_internal_api_key_secret

                __headers__ = IMPORT_reboot_aio_headers.Headers(
                    bearer_token=__bearer_token__,
                    state_ref=__this__._state_ref,
                    application_id=__this__._application_id,
                    app_internal_authorization=__app_internal_authorization__
                )

                __metadata__ += __headers__.to_grpc_metadata()

                __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff()
                while True:
                    try:
                        async with __context__.channel_manager.get_channel_to_state(
                            IMPORT_reboot_aio_types.StateTypeName('rbt.mcp.v1.Stream'),
                            __this__._state_ref,
                        ) as __channel__:

                            __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub(
                                __channel__
                            ).Query(
                                IMPORT_rbt_v1alpha1.react_pb2.QueryRequest(
                                    method='Replay',
                                    request=__request__.SerializeToString(),
                                ),
                                metadata=__metadata__,
                            )

                            async for __query_response__ in __call__:
                                # Clear the backoff so we don't wait
                                # as long the next time we get
                                # disconnected.
                                __query_backoff__.clear()

                                # The backend may have sent us this query
                                # response only to let us know that a new
                                # idempotency key has been recorded; there may
                                # not be a new response. Python callers don't
                                # (currently) care about such an event, so we
                                # simply ignore it.
                                if not __query_response__.HasField("response"):
                                    continue

                                __response__ = rbt.mcp.v1.stream_pb2.ReplayResponse()
                                __response__.ParseFromString(__query_response__.response)
                                yield __response__

                    except BaseException as exception:
                        # We expect to get disconnected from the server
                        # from time to time, e.g., when it is being
                        # updated, but we don't want that error to
                        # propagate, we just want to retry.
                        if IMPORT_rebootdev.aio.aborted.is_grpc_retryable_exception(exception):
                            logger.debug(
                                "Reactive read to 'rbt.mcp.v1.StreamMethods.Replay' "
                                f"failed with a retryable error: '{exception}'; "
                                "will retry..."
                            )
                            await __query_backoff__()
                            continue
                        raise


        def reactively(self):
            return Stream.WeakReference._Reactively(
                application_id=self._application_id,
                state_ref=self._state_ref,
                bearer_token=self._bearer_token,
            )

        class _Idempotently(IMPORT_typing.Generic[Stream_IdempotentlyScheduleTypeVar]):

            _weak_reference: Stream.WeakReference[Stream_IdempotentlyScheduleTypeVar]

            def __init__(
                self,
                *,
                weak_reference: Stream.WeakReference[Stream_IdempotentlyScheduleTypeVar],
                idempotency: IMPORT_reboot_aio_idempotency.Idempotency,
            ):
                self._weak_reference = weak_reference
                self._idempotency = idempotency

            def schedule(
                self,
                *,
                when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
            ) -> Stream_IdempotentlyScheduleTypeVar:
                return self._weak_reference._schedule_type(
                    self._weak_reference._application_id,
                    self._weak_reference._tasks,
                    when=when,
                    idempotency=self._idempotency,
                )

            def spawn(
                self,
                *,
                when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
            ) -> Stream.WeakReference._Spawn:
                return Stream.WeakReference._Spawn(
                    self._weak_reference._application_id,
                    self._weak_reference._tasks,
                    when=when,
                    idempotency=self._idempotency,
                )

            async def Read(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
            ) -> rbt.mcp.v1.stream_pb2.Stream:
                if self._weak_reference._servicer is None:
                    raise RuntimeError(
                        "`Read()` is currently only supported within workflows; "
                        "Please reach out and let us know your use case if this "
                        "is important for you!"
                    )

                return await StreamBaseServicer.WorkflowState._Idempotently._read(
                    self._weak_reference._servicer,
                    self._idempotency,
                    context,
                )

            @IMPORT_typing.overload
            async def Write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[None],
                *,
                type: type = type(None),
            ) -> None:
                ...

            @IMPORT_typing.overload
            async def Write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                *,
                type: type[StreamBaseServicer.InlineWriterCallableResult],
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                ...

            async def Write(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
                *,
                type: type = type(None),
            ) -> StreamBaseServicer.InlineWriterCallableResult:
                if self._weak_reference._servicer is None:
                    raise RuntimeError(
                        "`Write()` is currently only supported within workflows; "
                        "Please reach out and let us know your use case if this "
                        "is important for you!"
                    )

                return await StreamBaseServicer.WorkflowState._Idempotently._write_validating_effects(
                    self._weak_reference._servicer,
                    self._idempotency,
                    context,
                    writer,
                    type_result=type,
                    check_type=not self._idempotency.always,
                    unidempotently=self._idempotency.always,
                    checkpoint=context.checkpoint(),
                )

            async def Create(
                # In methods which are dealing with user input, (i.e.,
                # proto message field names), we should use '__double_underscored__'
                # variables to avoid any potential name conflicts with the method's
                # parameters.
                # The '__self__' parameter is a convention in Python to
                # indicate that this method is a bound method, so we use
                # '__this__' instead.
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            ) -> google.protobuf.empty_pb2.Empty:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=google.protobuf.empty_pb2.Empty)

                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    raise RuntimeError(
                        'Found redundant idempotency in `Options`'
                    )

                __options__ = IMPORT_dataclasses.replace(
                    __options__,
                    idempotency_key=__this__._idempotency.key,
                    idempotency_alias=__this__._idempotency.alias,
                    generate_idempotency=__this__._idempotency.generate,
                    generated_idempotency=__this__._idempotency.generated,
                )

                return await __this__._weak_reference.Create(
                    __context__,
                    __options__,
                )

            async def Put(
                # In methods which are dealing with user input, (i.e.,
                # proto message field names), we should use '__double_underscored__'
                # variables to avoid any potential name conflicts with the method's
                # parameters.
                # The '__self__' parameter is a convention in Python to
                # indicate that this method is a bound method, so we use
                # '__this__' instead.
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                event_id: IMPORT_typing.Optional[str] = None,
                message_bytes: IMPORT_typing.Optional[bytes] = None,
            ) -> rbt.mcp.v1.stream_pb2.PutResponse:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)

                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    raise RuntimeError(
                        'Found redundant idempotency in `Options`'
                    )

                __options__ = IMPORT_dataclasses.replace(
                    __options__,
                    idempotency_key=__this__._idempotency.key,
                    idempotency_alias=__this__._idempotency.alias,
                    generate_idempotency=__this__._idempotency.generate,
                    generated_idempotency=__this__._idempotency.generated,
                )

                return await __this__._weak_reference.Put(
                    __context__,
                    __options__,
                    event_id=event_id,
                    message_bytes=message_bytes,
                )

            async def Replay(
                # In methods which are dealing with user input, (i.e.,
                # proto message field names), we should use '__double_underscored__'
                # variables to avoid any potential name conflicts with the method's
                # parameters.
                # The '__self__' parameter is a convention in Python to
                # indicate that this method is a bound method, so we use
                # '__this__' instead.
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)

                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    raise RuntimeError(
                        'Found redundant idempotency in `Options`'
                    )

                __options__ = IMPORT_dataclasses.replace(
                    __options__,
                    idempotency_key=__this__._idempotency.key,
                    idempotency_alias=__this__._idempotency.alias,
                    generate_idempotency=__this__._idempotency.generate,
                    generated_idempotency=__this__._idempotency.generated,
                )

                return await __this__._weak_reference.Replay(
                    __context__,
                    __options__,
                    last_event_id=last_event_id,
                )


        @IMPORT_typing.overload
        def idempotently(self, alias: IMPORT_typing.Optional[str] = None, *, each_iteration: bool = False) -> Stream.WeakReference._Idempotently[Stream_ScheduleTypeVar]:
            ...

        @IMPORT_typing.overload
        def idempotently(self, *, key: IMPORT_uuid.UUID, generated: bool = False) -> Stream.WeakReference._Idempotently[Stream_ScheduleTypeVar]:
            ...

        def idempotently(
            self,
            alias: IMPORT_typing.Optional[str] = None,
            *,
            key: IMPORT_typing.Optional[IMPORT_uuid.UUID] = None,
            each_iteration: IMPORT_typing.Optional[bool] = None,
            generated: bool = False,
        ) -> Stream.WeakReference._Idempotently[Stream_ScheduleTypeVar]:
            return Stream.WeakReference._Idempotently(
                weak_reference=self,
                idempotency=IMPORT_reboot_aio_contexts.Context.idempotency(
                    alias=alias,
                    key=key,
                    each_iteration=each_iteration,
                    generated=generated,
                )
            )

        def per_workflow(self, alias: IMPORT_typing.Optional[str] = None):
            return self.idempotently(alias)

        def per_iteration(self, alias: IMPORT_typing.Optional[str] = None):
            return self.idempotently(alias, each_iteration=True)

        def always(self):
            return self.idempotently(key=IMPORT_uuid.uuid4(), generated=True)

        class _UntilChangesSatisfies(IMPORT_typing.Generic[Stream_UntilCallableType]):

            _idempotency_alias: str
            _context: IMPORT_reboot_aio_contexts.WorkflowContext
            _callable: IMPORT_typing.Callable[[], IMPORT_typing.Awaitable[Stream_UntilCallableType]]
            _type: type[Stream_UntilCallableType]

            def __init__(
                self,
                *,
                idempotency_alias: str,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
                callable: IMPORT_typing.Callable[[], IMPORT_typing.Awaitable[Stream_UntilCallableType]],
                type: type[Stream_UntilCallableType],
            ):
                self._idempotency_alias = idempotency_alias
                self._context = context
                self._callable = callable
                self._type = type

            async def changes(self):
                return await IMPORT_reboot_aio_workflows.until_changes(
                    self._idempotency_alias,
                    self._context,
                    self._callable,
                    type=self._type,
                )

            async def satisfies(
                self,
                condition: IMPORT_typing.Callable[[Stream_UntilCallableType], bool],
            ):

                async def converge():
                    response = await self._callable()
                    if condition(response):
                        return response
                    return False

                return await IMPORT_reboot_aio_workflows.until(
                    self._idempotency_alias,
                    self._context,
                    converge,
                    type=self._type,
                )

        class _Until:

            _weak_reference: Stream.WeakReference
            _idempotency_alias: str

            def __init__(
                self,
                *,
                weak_reference: Stream.WeakReference,
                idempotency_alias: str,
            ):
                self._weak_reference = weak_reference
                self._idempotency_alias = idempotency_alias

            def Read(
                self,
                context: IMPORT_reboot_aio_contexts.WorkflowContext,
            ) -> Stream.WeakReference._UntilChangesSatisfies[rbt.mcp.v1.stream_pb2.Stream]:
                IMPORT_reboot_aio_types.assert_type(
                    context,
                    [IMPORT_reboot_aio_contexts.WorkflowContext],
                )

                async def callable():
                    return await self._weak_reference.Read(context)

                return Stream.WeakReference._UntilChangesSatisfies(
                    idempotency_alias=self._idempotency_alias,
                    context=context,
                    callable=callable,
                    type=rbt.mcp.v1.stream_pb2.Stream,
                )

            def Replay(
                # In methods which are dealing with user input, (i.e.,
                # proto message field names), we should use '__double_underscored__'
                # variables to avoid any potential name conflicts with the method's
                # parameters.
                # The '__self__' parameter is a convention in Python to
                # indicate that this method is a bound method, so we use
                # '__this__' instead.
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WorkflowContext,
                __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> Stream.WeakReference._UntilChangesSatisfies[rbt.mcp.v1.stream_pb2.ReplayResponse]:
                IMPORT_reboot_aio_types.assert_type(
                    __context__,
                    [IMPORT_reboot_aio_contexts.WorkflowContext],
                )

                async def callable():
                    return await __this__._weak_reference.Replay(
                        __context__,
                        __options__,
                        last_event_id=last_event_id,
                    )

                return Stream.WeakReference._UntilChangesSatisfies(
                    idempotency_alias=__this__._idempotency_alias,
                    context=__context__,
                    callable=callable,
                    type=rbt.mcp.v1.stream_pb2.ReplayResponse,
                )


        def until(self, alias: str):
            return Stream.WeakReference._Until(
                weak_reference=self,
                idempotency_alias=alias,
            )

        def schedule(
            self,
            *,
            when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
        ) -> Stream_ScheduleTypeVar:
            return self._schedule_type(self._application_id, self._tasks, when=when)

        class _Schedule:

            def __init__(
                self,
                application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId],
                tasks: IMPORT_typing.Callable[[IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext], StreamTasksStub],
                *,
                when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
                idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
            ) -> None:
                self._application_id = application_id
                self._tasks = tasks
                self._when = ensure_has_timezone(when=when)
                self._idempotency = idempotency

            # Stream callable tasks:
            async def Create(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.TransactionContext])

                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = google.protobuf.empty_pb2.Empty(
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Create(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return __task_id__

            async def Put(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                event_id: IMPORT_typing.Optional[str] = None,
                message_bytes: IMPORT_typing.Optional[bytes] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.TransactionContext])

                if event_id is not None and not isinstance(
                    event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'event_id' is not "
                        f"of required type 'str'"
                    )
                if message_bytes is not None and not isinstance(
                    message_bytes,
                    bytes,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'message_bytes' is not "
                        f"of required type 'bytes'"
                    )
                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.PutRequest(
                    event_id=event_id,  # type: ignore[arg-type]
                    message_bytes=message_bytes,  # type: ignore[arg-type]
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Put(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return __task_id__

            async def Replay(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.TransactionContext])

                if last_event_id is not None and not isinstance(
                    last_event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.ReplayRequest': field 'last_event_id' is not "
                        f"of required type 'str'"
                    )
                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.ReplayRequest(
                    last_event_id=last_event_id,  # type: ignore[arg-type]
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Replay(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return __task_id__


        # A `WriterContext` can not call any methods in `_Schedule` to
        # prevent a writer from doing a `Foo.ref()` and trying to
        # schedule. However, we want to allow a writer to schedule
        # when we are constructing a `WeakReference` from
        # `self.ref()` so instead we return a `_WriterSchedule` to
        # provide type safety that allows a `WriterContext` to
        # schedule (for itself).
        class _WriterSchedule:

            def __init__(
                self,
                application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId],
                tasks: IMPORT_typing.Callable[[IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext], StreamTasksStub],
                *,
                when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
                idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
            ) -> None:
                self._tasks = tasks
                self._when = ensure_has_timezone(when=when)
                self._idempotency = idempotency

            # Stream callable tasks:
            async def Create(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # Only `writer`s and `transaction`s should ``schedule()`, a
                # `workflow` should `spawn()`.
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WriterContext, IMPORT_reboot_aio_contexts.TransactionContext])

                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=google.protobuf.empty_pb2.Empty)

                # TODO: mypy-protobuf declares that
                # `google.protobuf.message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = google.protobuf.empty_pb2.Empty(
                )
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WriterContext):
                    return (await StreamServicerTasks(
                        context=__context__,
                        state_ref=__context__._state_ref,
                    ).Create(
                        __request__,
                        schedule=__this__._when,
                    )).task_id

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency is not None:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                return await __this__._tasks(
                    __context__
                ).Create(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

            async def Put(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                event_id: IMPORT_typing.Optional[str] = None,
                message_bytes: IMPORT_typing.Optional[bytes] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # Only `writer`s and `transaction`s should ``schedule()`, a
                # `workflow` should `spawn()`.
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WriterContext, IMPORT_reboot_aio_contexts.TransactionContext])

                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)

                if event_id is not None and not isinstance(
                    event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'event_id' is not "
                        f"of required type 'str'"
                    )
                if message_bytes is not None and not isinstance(
                    message_bytes,
                    bytes,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'message_bytes' is not "
                        f"of required type 'bytes'"
                    )
                # TODO: mypy-protobuf declares that
                # `google.protobuf.message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.PutRequest(
                    event_id=event_id,  # type: ignore[arg-type]
                    message_bytes=message_bytes,  # type: ignore[arg-type]
                )
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WriterContext):
                    return (await StreamServicerTasks(
                        context=__context__,
                        state_ref=__context__._state_ref,
                    ).Put(
                        __request__,
                        schedule=__this__._when,
                    )).task_id

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency is not None:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                return await __this__._tasks(
                    __context__
                ).Put(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

            async def Replay(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> IMPORT_rbt_v1alpha1.tasks_pb2.TaskId:
                # Only `writer`s and `transaction`s should ``schedule()`, a
                # `workflow` should `spawn()`.
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WriterContext, IMPORT_reboot_aio_contexts.TransactionContext])

                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)

                if last_event_id is not None and not isinstance(
                    last_event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.ReplayRequest': field 'last_event_id' is not "
                        f"of required type 'str'"
                    )
                # TODO: mypy-protobuf declares that
                # `google.protobuf.message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.ReplayRequest(
                    last_event_id=last_event_id,  # type: ignore[arg-type]
                )
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WriterContext):
                    return (await StreamServicerTasks(
                        context=__context__,
                        state_ref=__context__._state_ref,
                    ).Replay(
                        __request__,
                        schedule=__this__._when,
                    )).task_id

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency is not None:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                return await __this__._tasks(
                    __context__
                ).Replay(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )


        def spawn(
            self,
            *,
            when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
        ) -> Stream.WeakReference._Spawn:
            # Within a `workflow`, all "bare" `spawn()` calls are
            # syntactic sugar for `per_workflow()`, unless we're
            # within a control loop, in which case they are syntactic
            # sugar for `per_iteration()`.
            context = IMPORT_reboot_aio_contexts.Context.get()
            if context is not None:
                if isinstance(context, IMPORT_reboot_aio_contexts.WorkflowContext):
                    return (
                        self.per_iteration() if context.within_loop()
                        else self.per_workflow()
                    ).spawn(when=when)
                elif isinstance(context, IMPORT_reboot_aio_external.InitializeContext):
                    return self.idempotently().spawn(when=when)

            return Stream.WeakReference._Spawn(
                self._application_id, self._tasks, when=when
            )

        class _Spawn:

            def __init__(
                self,
                application_id: IMPORT_typing.Optional[IMPORT_reboot_aio_types.ApplicationId],
                tasks: IMPORT_typing.Callable[[IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext], StreamTasksStub],
                *,
                when: IMPORT_typing.Optional[IMPORT_datetime_datetime | IMPORT_datetime_timedelta] = None,
                idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None,
            ) -> None:
                self._application_id = application_id
                self._tasks = tasks
                self._when = ensure_has_timezone(when=when)
                self._idempotency = idempotency

            # Stream callable tasks:
            async def Create(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
            ) -> Stream.CreateTask:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=google.protobuf.empty_pb2.Empty)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])

                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = google.protobuf.empty_pb2.Empty(
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Create(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return Stream.CreateTask(
                    __context__,
                    task_id=__task_id__,
                )

            async def Put(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                event_id: IMPORT_typing.Optional[str] = None,
                message_bytes: IMPORT_typing.Optional[bytes] = None,
            ) -> Stream.PutTask:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])

                if event_id is not None and not isinstance(
                    event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'event_id' is not "
                        f"of required type 'str'"
                    )
                if message_bytes is not None and not isinstance(
                    message_bytes,
                    bytes,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'message_bytes' is not "
                        f"of required type 'bytes'"
                    )
                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.PutRequest(
                    event_id=event_id,  # type: ignore[arg-type]
                    message_bytes=message_bytes,  # type: ignore[arg-type]
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Put(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return Stream.PutTask(
                    __context__,
                    task_id=__task_id__,
                )

            async def Replay(
                __this__,
                __context__: IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
                __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
                *,
                last_event_id: IMPORT_typing.Optional[str] = None,
            ) -> Stream.ReplayTask:
                # UX improvement: check that neither positional argument was accidentally
                # given a gRPC request type.
                IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
                IMPORT_reboot_aio_types.assert_type(__context__, [IMPORT_reboot_aio_contexts.WorkflowContext, IMPORT_reboot_aio_external.ExternalContext])

                if last_event_id is not None and not isinstance(
                    last_event_id,
                    str,
                ):
                    raise TypeError(
                        f"Can not construct protobuf message of type "
                        f"'rbt.mcp.v1.stream_pb2.ReplayRequest': field 'last_event_id' is not "
                        f"of required type 'str'"
                    )
                # TODO: mypy-protobuf declares that
                # `IMPORT_google_protobuf_message.Message` constructor arguments are
                # always non-None, when in reality they are optional.
                __request__ = rbt.mcp.v1.stream_pb2.ReplayRequest(
                    last_event_id=last_event_id,  # type: ignore[arg-type]
                )

                __schedule__: IMPORT_typing.Optional[IMPORT_reboot_time_DateTimeWithTimeZone] = (IMPORT_reboot_time_DateTimeWithTimeZone.now() + __this__._when) if isinstance(
                    __this__._when, IMPORT_datetime_timedelta
                ) else __this__._when

                __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
                __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = __this__._idempotency
                __bearer_token__: IMPORT_typing.Optional[str] = None

                if __options__ is not None:
                    IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                    if __options__.idempotency:
                        if __idempotency__ is not None:
                            raise RuntimeError(
                                'Found redundant idempotency in `Options`'
                            )
                        __idempotency__ = __options__.idempotency
                    if __options__.metadata is not None:
                        __metadata__ = __options__.metadata
                    if __options__.bearer_token is not None:
                        __bearer_token__ = __options__.bearer_token

                # Add scheduling information to the metadata.
                __metadata__ = (
                    (IMPORT_reboot_aio_headers.TASK_SCHEDULE,
                    __schedule__.isoformat() if __schedule__ else ''),
                ) + (__metadata__ or tuple())

                __task_id__ = await __this__._tasks(
                    __context__
                ).Replay(
                    __request__,
                    idempotency=__idempotency__,
                    metadata=__metadata__,
                    bearer_token=__bearer_token__,
                )

                return Stream.ReplayTask(
                    __context__,
                    task_id=__task_id__,
                )


        async def Read(
            self,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
        ) -> rbt.mcp.v1.stream_pb2.Stream:
            return await (
                self.always() if context.within_until()
                else (
                    self.per_iteration() if context.within_loop()
                    else self.per_workflow()
                )
            ).Read(context)

        @IMPORT_typing.overload
        async def Write(
            self,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[None],
            *,
            type: type = type(None),
        ) -> None:
            ...

        @IMPORT_typing.overload
        async def Write(
            self,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
            *,
            type: type[StreamBaseServicer.InlineWriterCallableResult],
        ) -> StreamBaseServicer.InlineWriterCallableResult:
            ...

        async def Write(
            self,
            context: IMPORT_reboot_aio_contexts.WorkflowContext,
            writer: StreamBaseServicer.InlineWriterCallable[StreamBaseServicer.InlineWriterCallableResult],
            *,
            type: type = type(None),
        ) -> StreamBaseServicer.InlineWriterCallableResult:
            """Perform an "inline write" within a workflow."""
            return await (
                self.always() if context.within_until()
                else (
                    self.per_iteration() if context.within_loop()
                    else self.per_workflow()
                )
            ).Write(
                context, writer, type=type
            )

        # Stream specific methods:
        async def Create(
            __this__,
            __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
        ) -> google.protobuf.empty_pb2.Empty:
            # UX improvement: check that neither positional argument was accidentally
            # given a gRPC request type.
            IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=google.protobuf.empty_pb2.Empty)
            IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=google.protobuf.empty_pb2.Empty)

            # Within a `workflow`, all "bare" calls are
            # `per_workflow()` calls, unless we're within a control
            # loop, in which case they are syntactic sugar for
            # `per_iteration()`.
            if __options__ is None or __options__.idempotency is None:
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WorkflowContext):
                    return await (
                        __this__.per_iteration() if __context__.within_loop()
                        else __this__.per_workflow()
                    ).Create(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                    )
                elif isinstance(__context__, IMPORT_reboot_aio_external.InitializeContext):
                    return await __this__.idempotently().Create(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                    )

            # TODO: mypy-protobuf declares that
            # `google.protobuf.message.Message` constructor arguments are
            # always non-None, when in reality they are optional.
            __request__ = google.protobuf.empty_pb2.Empty(
            )
            __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None
            __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
            __bearer_token__: IMPORT_typing.Optional[str] = None
            if __options__ is not None:
                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    __idempotency__ = __options__.idempotency
                if __options__.metadata is not None:
                    __metadata__ = __options__.metadata
                if __options__.bearer_token is not None:
                    __bearer_token__ = __options__.bearer_token

            return await __this__._writer(__context__).Create(
                __request__,
                idempotency=__idempotency__,
                metadata=__metadata__,
                bearer_token=__bearer_token__,
            )

        async def Put(
            __this__,
            __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
            *,
            event_id: IMPORT_typing.Optional[str] = None,
            message_bytes: IMPORT_typing.Optional[bytes] = None,
        ) -> rbt.mcp.v1.stream_pb2.PutResponse:
            # UX improvement: check that neither positional argument was accidentally
            # given a gRPC request type.
            IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)
            IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.PutRequest)

            # Within a `workflow`, all "bare" calls are
            # `per_workflow()` calls, unless we're within a control
            # loop, in which case they are syntactic sugar for
            # `per_iteration()`.
            if __options__ is None or __options__.idempotency is None:
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WorkflowContext):
                    return await (
                        __this__.per_iteration() if __context__.within_loop()
                        else __this__.per_workflow()
                    ).Put(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                        event_id=event_id,
                        message_bytes=message_bytes,
                    )
                elif isinstance(__context__, IMPORT_reboot_aio_external.InitializeContext):
                    return await __this__.idempotently().Put(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                        event_id=event_id,
                        message_bytes=message_bytes,
                    )

            if event_id is not None and not isinstance(
                event_id,
                str,
            ):
                raise TypeError(
                    f"Can not construct protobuf message of type "
                    f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'event_id' is not "
                    f"of required type 'str'"
                )
            if message_bytes is not None and not isinstance(
                message_bytes,
                bytes,
            ):
                raise TypeError(
                    f"Can not construct protobuf message of type "
                    f"'rbt.mcp.v1.stream_pb2.PutRequest': field 'message_bytes' is not "
                    f"of required type 'bytes'"
                )
            # TODO: mypy-protobuf declares that
            # `google.protobuf.message.Message` constructor arguments are
            # always non-None, when in reality they are optional.
            __request__ = rbt.mcp.v1.stream_pb2.PutRequest(
                event_id=event_id,  # type: ignore[arg-type]
                message_bytes=message_bytes,  # type: ignore[arg-type]
            )
            __idempotency__: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None
            __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
            __bearer_token__: IMPORT_typing.Optional[str] = None
            if __options__ is not None:
                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.idempotency is not None:
                    __idempotency__ = __options__.idempotency
                if __options__.metadata is not None:
                    __metadata__ = __options__.metadata
                if __options__.bearer_token is not None:
                    __bearer_token__ = __options__.bearer_token

            return await __this__._writer(__context__).Put(
                __request__,
                idempotency=__idempotency__,
                metadata=__metadata__,
                bearer_token=__bearer_token__,
            )

        async def Replay(
            __this__,
            __context__: IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_typing.Optional[IMPORT_reboot_aio_call.Options] = None,
            *,
            last_event_id: IMPORT_typing.Optional[str] = None,
        ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
            # UX improvement: check that neither positional argument was accidentally
            # given a gRPC request type.
            IMPORT_reboot_aio_types.assert_not_request_type(__context__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)
            IMPORT_reboot_aio_types.assert_not_request_type(__options__, request_type=rbt.mcp.v1.stream_pb2.ReplayRequest)

            # Within a `workflow`, all "bare" calls are
            # `per_workflow()` calls, unless we're within a control
            # loop, in which case they are syntactic sugar for
            # `per_iteration()`.
            #
            # Unless we are "within until" in which case all "bare"
            # calls are `.always().
            if __options__ is None or __options__.idempotency is None:
                if isinstance(__context__, IMPORT_reboot_aio_contexts.WorkflowContext):
                    return await (
                        __this__.always() if __context__.within_until()
                        else (
                            __this__.per_iteration() if __context__.within_loop()
                            else __this__.per_workflow()
                        )
                    ).Replay(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                        last_event_id=last_event_id,
                    )
                elif isinstance(__context__, IMPORT_reboot_aio_external.InitializeContext):
                    return await __this__.idempotently().Replay(
                        __context__,
                        __options__ or IMPORT_reboot_aio_call.Options(),
                        last_event_id=last_event_id,
                    )

            if last_event_id is not None and not isinstance(
                last_event_id,
                str,
            ):
                raise TypeError(
                    f"Can not construct protobuf message of type "
                    f"'rbt.mcp.v1.stream_pb2.ReplayRequest': field 'last_event_id' is not "
                    f"of required type 'str'"
                )
            # TODO: mypy-protobuf declares that
            # `google.protobuf.message.Message` constructor arguments are
            # always non-None, when in reality they are optional.
            __request__ = rbt.mcp.v1.stream_pb2.ReplayRequest(
                last_event_id=last_event_id,  # type: ignore[arg-type]
            )
            __metadata__: IMPORT_typing.Optional[IMPORT_reboot_aio_types.GrpcMetadata] = None
            __bearer_token__: IMPORT_typing.Optional[str] = None
            if __options__ is not None:
                IMPORT_reboot_aio_types.assert_type(__options__, [IMPORT_reboot_aio_call.Options])
                if __options__.metadata is not None:
                    __metadata__ = __options__.metadata
                if __options__.bearer_token is not None:
                    __bearer_token__ = __options__.bearer_token
            return await __this__._reader(__context__).Replay(
                __request__,
                metadata=__metadata__,
                bearer_token=__bearer_token__,
                idempotency=__options__.idempotency if __options__ is not None else None,
            )

    class _Forall:

        _ids: list[str]

        def __init__(self, ids: list[str]):
            self._ids = ids

        async def Create(
            # In methods which are dealing with user input, (i.e.,
            # proto message field names), we should use '__double_underscored__'
            # variables to avoid any potential name conflicts with the method's
            # parameters.
            # The '__self__' parameter is a convention in Python to
            # indicate that this method is a bound method, so we use
            # '__this__' instead.
            __this__,
            __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
        ) -> list[google.protobuf.empty_pb2.Empty]:
            return await IMPORT_asyncio.gather(
                *[
                    Stream.ref(
                        id
                    ).Create(
                        __context__,
                        __options__,
                    ) for id in __this__._ids
                ]
            )

        async def Put(
            # In methods which are dealing with user input, (i.e.,
            # proto message field names), we should use '__double_underscored__'
            # variables to avoid any potential name conflicts with the method's
            # parameters.
            # The '__self__' parameter is a convention in Python to
            # indicate that this method is a bound method, so we use
            # '__this__' instead.
            __this__,
            __context__: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            *,
            event_id: IMPORT_typing.Optional[str] = None,
            message_bytes: IMPORT_typing.Optional[bytes] = None,
        ) -> list[rbt.mcp.v1.stream_pb2.PutResponse]:
            return await IMPORT_asyncio.gather(
                *[
                    Stream.ref(
                        id
                    ).Put(
                        __context__,
                        __options__,
                        event_id=event_id,
                        message_bytes=message_bytes,
                    ) for id in __this__._ids
                ]
            )

        async def Replay(
            # In methods which are dealing with user input, (i.e.,
            # proto message field names), we should use '__double_underscored__'
            # variables to avoid any potential name conflicts with the method's
            # parameters.
            # The '__self__' parameter is a convention in Python to
            # indicate that this method is a bound method, so we use
            # '__this__' instead.
            __this__,
            __context__: IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
            __options__: IMPORT_reboot_aio_call.Options = IMPORT_reboot_aio_call.Options(),
            *,
            last_event_id: IMPORT_typing.Optional[str] = None,
        ) -> list[rbt.mcp.v1.stream_pb2.ReplayResponse]:
            return await IMPORT_asyncio.gather(
                *[
                    Stream.ref(
                        id
                    ).Replay(
                        __context__,
                        __options__,
                        last_event_id=last_event_id,
                    ) for id in __this__._ids
                ]
            )


    @classmethod
    def forall(cls, ids: list[str]) -> Stream._Forall:
        return Stream._Forall(ids)

    @classmethod
    def ref(
        cls,
        state_id: IMPORT_reboot_aio_types.StateId,
        *,
        bearer_token: IMPORT_typing.Optional[str] = None,
    ) -> Stream.WeakReference[Stream.WeakReference._Schedule]:
        return Stream.WeakReference(
            # TODO(https://github.com/reboot-dev/mono/issues/3226): add support for calling other applications.
            # For now this always stays within the application that creates the context.
            application_id=None,
            state_id=state_id,
            schedule_type=Stream.WeakReference._Schedule,
            bearer_token=bearer_token,
        )


    @IMPORT_typing.overload
    @classmethod
    def idempotently(cls, alias: IMPORT_typing.Optional[str] = None, *, each_iteration: bool = False) -> Stream._ConstructIdempotently:
        ...

    @IMPORT_typing.overload
    @classmethod
    def idempotently(cls, *, key: IMPORT_uuid.UUID, generated: bool = False) -> Stream._ConstructIdempotently:
        ...

    @classmethod
    def idempotently(
        cls,
        alias: IMPORT_typing.Optional[str] = None,
        *,
        key: IMPORT_typing.Optional[IMPORT_uuid.UUID] = None,
        each_iteration: IMPORT_typing.Optional[bool] = None,
        generated: bool = False,
    ) -> Stream._ConstructIdempotently:
        return Stream._ConstructIdempotently(
            _idempotency=IMPORT_reboot_aio_contexts.Context.idempotency(
                alias=alias,
                key=key,
                each_iteration=each_iteration,
                generated=generated,
            ),
        )

    @classmethod
    def per_workflow(
        cls,
        alias: IMPORT_typing.Optional[str] = None,
    ):
        return cls.idempotently(alias)

    @classmethod
    def per_iteration(
        cls,
        alias: IMPORT_typing.Optional[str] = None,
    ):
        return cls.idempotently(alias, each_iteration=True)

    @classmethod
    def always(cls):
        return cls.idempotently(key=IMPORT_uuid.uuid4(), generated=True)

    @IMPORT_dataclasses.dataclass(frozen=True)
    class _ConstructIdempotently:

        _idempotency: IMPORT_reboot_aio_idempotency.Idempotency



############################ Servicer Node adapters ############################
# Used by Node.js servicer implementations to access Python code and vice-versa.
# Relevant to servicers, irrelevant to clients.

class StreamServicerNodeAdaptor(Stream.singleton.Servicer):

    async def _wait_for_cancelled(
        self,
        future: IMPORT_asyncio.Future,
        method: str,
    ):
        while True:
            done, pending = await IMPORT_asyncio.wait(
                [future],
                timeout=5,  # seconds
            )
            # Check if we've timed out and log a warning that their
            # call has been cancelled but it is still running.
            if len(done) == 0:
                logger.warning(
                    f"Call to method '{method}' has been cancelled by the caller, "
                    "BUT WE ARE STILL WAITING for it complete. You can use the promise "
                    "`context.cancelled` to check if the caller has cancelled so you "
                    "don't do unnecessary work or wait for something that may never occur."
                )
                continue
            break

        # Now need to actually `await` the future so that we don't
        # have an unretrieved exception that gets logged.
        #
        # NOTE: this will raise an exception if the method raised even
        # though the call has already been cancelled but it makes it
        # more clear that the method raised so that is why we're not
        # catching and swallowing any exception.
        await future

    def __init__(self):
        self._js_servicer_reference = self._construct_js_servicer()  # type: ignore[attr-defined]

    def authorizer(self) -> IMPORT_typing.Optional[IMPORT_rebootdev.aio.auth.authorizers.Authorizer]:
        return self._construct_authorizer(self._js_servicer_reference)  # type: ignore[attr-defined]

    async def _read(
        self,
        context: IMPORT_reboot_aio_contexts.WorkflowContext,
        json_options: str,
    ) -> str:
        options = IMPORT_json.loads(json_options)

        alias = options.get('alias')

        assert 'how' in options
        how = options['how']
        if how == IMPORT_reboot_aio_workflows.ALWAYS:
            assert alias is None
            return IMPORT_google_protobuf_json_format.MessageToJson(
                await super().state.always().read(context)
            )

        assert how in [
            IMPORT_reboot_aio_workflows.PER_WORKFLOW,
            IMPORT_reboot_aio_workflows.PER_ITERATION,
        ]

        return IMPORT_google_protobuf_json_format.MessageToJson(
            await (
                super().state.per_workflow(alias)
                if how == IMPORT_reboot_aio_workflows.PER_WORKFLOW
                else super().state.per_iteration(alias)
            ).read(context)
        )

    async def _write(
        self,
        context: IMPORT_reboot_aio_contexts.WorkflowContext,
        writer: IMPORT_typing.Callable[[str], IMPORT_typing.Awaitable[str]],
        json_options: str,
    ) -> str:

        async def _writer(state: IMPORT_google_protobuf_message.Message):
            with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="_writer on NodeAdaptor",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
            ):
                json_result_state = await writer(
                    IMPORT_google_protobuf_json_format.MessageToJson(state)
                )

                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="_write - State Copy on NodeAdaptor",
                    # The naming above matches Python, but not TypeScript.
                    python_specific=True,
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                ):
                    result_state = IMPORT_json.loads(json_result_state)

                    state.CopyFrom(
                        IMPORT_google_protobuf_json_format.ParseDict(
                            result_state['state'],
                            self.__state_type__(),
                        )
                    )

                    assert 'result' in result_state
                    result = result_state['result']
                    assert type(result) == str
                    return result

        options = IMPORT_json.loads(json_options)

        alias = options.get('alias')

        assert 'how' in options
        how = options['how']

        if how == IMPORT_reboot_aio_workflows.ALWAYS:
            assert alias is None
            return await super().state.always().write(
                context,
                _writer,
            )

        assert how in [
            IMPORT_reboot_aio_workflows.PER_WORKFLOW,
            IMPORT_reboot_aio_workflows.PER_ITERATION,
        ]

        return await (
            super().state.per_workflow(alias)
            if how == IMPORT_reboot_aio_workflows.PER_WORKFLOW
            else super().state.per_iteration(alias)
        ).write(context, _writer, type=str)

    # Stream specific methods:
    async def Create(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: google.protobuf.empty_pb2.Empty,
    ) -> google.protobuf.empty_pb2.Empty:
        with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="NodeAdaptor Create",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
        ):
            with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="Create and serialize `TrampolineCall`",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
            ):
                bytes_call = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineCall(
                    kind=IMPORT_rbt_v1alpha1_nodejs_pb2.writer,
                    context=IMPORT_rbt_v1alpha1_nodejs_pb2.Context(
                        method='Create',
                        state_id=context.state_id,
                        state_type_name=context.state_type_name,
                        caller_bearer_token=context.caller_bearer_token,
                        cookie=context.cookie,
                        app_internal=context.app_internal,
                        auth=(
                            None if context.auth is None
                            else context.auth.to_proto_bytes()
                        ),
                    ),
                    state=state.SerializeToString(),
                    request=request.SerializeToString(),
                ).SerializeToString()

            cancelled: IMPORT_asyncio.Future[None] = IMPORT_asyncio.Future()

            bytes_result_future: IMPORT_typing.Optional[IMPORT_asyncio.Future[str]] = None

            try:
                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="trampoline",
                    # The naming above matches Python, but not TypeScript.
                    python_specific=True,
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                ):
                    bytes_result_future = self._trampoline(  # type: ignore[attr-defined]
                        self._js_servicer_reference,
                        context,
                        cancelled,
                        bytes_call,
                    )
                    # NOTE: we need to `asyncio.shield` so that we can still
                    # correctly wait for this future to complete even if we
                    # are cancelled.
                    assert bytes_result_future is not None
                    bytes_result = await IMPORT_asyncio.shield(bytes_result_future)
            except IMPORT_asyncio.CancelledError:
                cancelled.set_result(None)

                # NOTE: we MUST wait for `bytes_result_future` because this
                # is a `writer` or `transaction` and we CAN NOT execute
                # multiple simultaneously.
                if bytes_result_future is not None:
                    await self._wait_for_cancelled(
                        bytes_result_future,
                        'Stream.Create',
                    )

                raise
            except:
                # Make sure we cancel the `cancelled` future either if an
                # exception is thrown or if the result is reeturned so
                # that we don't keep around resources related to it that
                # might cause us to run out of memory or worse, keep Node
                # from exiting because it is waiting for Python.
                cancelled.cancel()
                raise
            else:
                cancelled.cancel()

                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="result ParseFromString",
                    # The naming above matches Python, but not TypeScript.
                    python_specific=True,
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                ):
                    result = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineResult.FromString(
                        bytes_result
                    )

                if result.HasField('state'):
                    with IMPORT_reboot_aio_tracing.span(
                        state_name=f"{context.state_type_name}('{context.state_id}')",
                        span_name="state ParseFromString",
                        # The naming above matches Python, but not TypeScript.
                        python_specific=True,
                        level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                    ):
                        state.CopyFrom(
                            rbt.mcp.v1.stream_pb2.Stream.FromString(
                                result.state
                            )
                        )

                if result.HasField('status_json'):
                    raise (
                        Stream
                        .CreateAborted
                        .from_status(
                            IMPORT_google_protobuf_json_format.Parse(
                                result.status_json,
                                IMPORT_google_rpc_status_pb2.Status(),
                            )
                        )
                    )

                assert result.HasField('response')

                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="response ParseFromString",
                ):
                    return google.protobuf.empty_pb2.Empty.FromString(result.response)
        raise RuntimeError("Unexpected result from Create")

    async def Put(
        self,
        context: IMPORT_reboot_aio_contexts.WriterContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.PutRequest,
    ) -> rbt.mcp.v1.stream_pb2.PutResponse:
        with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="NodeAdaptor Put",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
        ):
            with IMPORT_reboot_aio_tracing.span(
                state_name=f"{context.state_type_name}('{context.state_id}')",
                span_name="Create and serialize `TrampolineCall`",
                # The naming above matches Python, but not TypeScript.
                python_specific=True,
                level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
            ):
                bytes_call = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineCall(
                    kind=IMPORT_rbt_v1alpha1_nodejs_pb2.writer,
                    context=IMPORT_rbt_v1alpha1_nodejs_pb2.Context(
                        method='Put',
                        state_id=context.state_id,
                        state_type_name=context.state_type_name,
                        caller_bearer_token=context.caller_bearer_token,
                        cookie=context.cookie,
                        app_internal=context.app_internal,
                        auth=(
                            None if context.auth is None
                            else context.auth.to_proto_bytes()
                        ),
                    ),
                    state=state.SerializeToString(),
                    request=request.SerializeToString(),
                ).SerializeToString()

            cancelled: IMPORT_asyncio.Future[None] = IMPORT_asyncio.Future()

            bytes_result_future: IMPORT_typing.Optional[IMPORT_asyncio.Future[str]] = None

            try:
                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="trampoline",
                    # The naming above matches Python, but not TypeScript.
                    python_specific=True,
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                ):
                    bytes_result_future = self._trampoline(  # type: ignore[attr-defined]
                        self._js_servicer_reference,
                        context,
                        cancelled,
                        bytes_call,
                    )
                    # NOTE: we need to `asyncio.shield` so that we can still
                    # correctly wait for this future to complete even if we
                    # are cancelled.
                    assert bytes_result_future is not None
                    bytes_result = await IMPORT_asyncio.shield(bytes_result_future)
            except IMPORT_asyncio.CancelledError:
                cancelled.set_result(None)

                # NOTE: we MUST wait for `bytes_result_future` because this
                # is a `writer` or `transaction` and we CAN NOT execute
                # multiple simultaneously.
                if bytes_result_future is not None:
                    await self._wait_for_cancelled(
                        bytes_result_future,
                        'Stream.Put',
                    )

                raise
            except:
                # Make sure we cancel the `cancelled` future either if an
                # exception is thrown or if the result is reeturned so
                # that we don't keep around resources related to it that
                # might cause us to run out of memory or worse, keep Node
                # from exiting because it is waiting for Python.
                cancelled.cancel()
                raise
            else:
                cancelled.cancel()

                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="result ParseFromString",
                    # The naming above matches Python, but not TypeScript.
                    python_specific=True,
                    level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                ):
                    result = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineResult.FromString(
                        bytes_result
                    )

                if result.HasField('state'):
                    with IMPORT_reboot_aio_tracing.span(
                        state_name=f"{context.state_type_name}('{context.state_id}')",
                        span_name="state ParseFromString",
                        # The naming above matches Python, but not TypeScript.
                        python_specific=True,
                        level=IMPORT_reboot_aio_tracing.TraceLevel.CUSTOMER,
                    ):
                        state.CopyFrom(
                            rbt.mcp.v1.stream_pb2.Stream.FromString(
                                result.state
                            )
                        )

                if result.HasField('status_json'):
                    raise (
                        Stream
                        .PutAborted
                        .from_status(
                            IMPORT_google_protobuf_json_format.Parse(
                                result.status_json,
                                IMPORT_google_rpc_status_pb2.Status(),
                            )
                        )
                    )

                assert result.HasField('response')

                with IMPORT_reboot_aio_tracing.span(
                    state_name=f"{context.state_type_name}('{context.state_id}')",
                    span_name="response ParseFromString",
                ):
                    return rbt.mcp.v1.stream_pb2.PutResponse.FromString(result.response)
        raise RuntimeError("Unexpected result from Put")

    async def Replay(
        self,
        context: IMPORT_reboot_aio_contexts.ReaderContext,
        state: rbt.mcp.v1.stream_pb2.Stream,
        request: rbt.mcp.v1.stream_pb2.ReplayRequest,
    ) -> rbt.mcp.v1.stream_pb2.ReplayResponse:
        bytes_call = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineCall(
            kind=IMPORT_rbt_v1alpha1_nodejs_pb2.reader,
            context=IMPORT_rbt_v1alpha1_nodejs_pb2.Context(
                method='Replay',
                state_id=context.state_id,
                state_type_name=context.state_type_name,
                caller_bearer_token=context.caller_bearer_token,
                cookie=context.cookie,
                app_internal=context.app_internal,
                auth=(
                    None if context.auth is None
                    else context.auth.to_proto_bytes()
                ),
            ),
            state=state.SerializeToString(),
            request=request.SerializeToString(),
        ).SerializeToString()

        cancelled: IMPORT_asyncio.Future[None] = IMPORT_asyncio.Future()

        bytes_result_future: IMPORT_typing.Optional[IMPORT_asyncio.Future[str]] = None

        try:
            bytes_result_future = self._trampoline(  # type: ignore[attr-defined]
                self._js_servicer_reference,
                context,
                cancelled,
                bytes_call,
            )
            # NOTE: we need to `asyncio.shield` so that we can still
            # correctly wait for this future to complete even if we
            # are cancelled.
            assert bytes_result_future is not None
            bytes_result = await IMPORT_asyncio.shield(bytes_result_future)
        except IMPORT_asyncio.CancelledError:
            cancelled.set_result(None)

            # NOTE: unlike for a `writer` or `transaction`, we DO NOT
            # _need_ to wait for `bytes_result_future` because this is a
            # reader and we can execute multiple readers
            # simultaneously. That being said, we still want to give
            # good feedback that the RPC has been cancelled, and there
            # is no harm waiting because other readers can still be
            # called.
            if bytes_result_future is not None:
                await self._wait_for_cancelled(
                    bytes_result_future,
                    'Stream.Replay',
                )

            raise
        except:
            # Make sure we cancel the `cancelled` future either if an
            # exception is thrown or if the result is reeturned so
            # that we don't keep around resources related to it that
            # might cause us to run out of memory or worse, keep Node
            # from exiting because it is waiting for Python.
            cancelled.cancel()
            raise
        else:
            cancelled.cancel()

            result = IMPORT_rbt_v1alpha1_nodejs_pb2.TrampolineResult.FromString(
                bytes_result
            )

            if result.HasField('status_json'):
                raise (
                    Stream
                    .ReplayAborted
                    .from_status(
                        IMPORT_google_protobuf_json_format.Parse(
                            result.status_json,
                            IMPORT_google_rpc_status_pb2.Status(),
                        )
                    )
                )

            assert result.HasField('response')

            return rbt.mcp.v1.stream_pb2.ReplayResponse.FromString(result.response)
        raise RuntimeError("Unexpected result from Replay")



############################ Reference Node adapters ############################
# Used by Node.js WeakReference implementations to access Python code and
# vice-versa. Relevant to clients.

class StreamWeakReferenceNodeAdaptor(Stream.WeakReference[Stream.WeakReference._Schedule]):

    async def _call(  # type: ignore[override]
        self,
        *,
        callable: IMPORT_typing.Callable[[IMPORT_google_protobuf_message.Message], IMPORT_typing.Awaitable],
        aborted_type: type[IMPORT_rebootdev.aio.aborted.Aborted],
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
    ) -> str:
        request = request_type()

        try:
            IMPORT_google_protobuf_json_format.Parse(json_request, request)
            response = await callable(request)
        except IMPORT_google_protobuf_json_format.ParseError as parse_error:
            aborted_error = IMPORT_rebootdev.aio.aborted.SystemAborted(
                IMPORT_rbt_v1alpha1.errors_pb2.Unknown(),
                message=f"{parse_error}; "
                       "This is usually caused by a deeply nested protobuf message, which is not supported by protobuf.\n"
                        "See the limits here: https://protobuf.dev/programming-guides/proto-limits/"
                )

            return IMPORT_json.dumps(
                {
                    'status': IMPORT_google_protobuf_json_format.MessageToDict(
                        aborted_error.to_status()
                    )
                }
            )
        except BaseException as exception:
            if isinstance(exception, aborted_type):
                return IMPORT_json.dumps(
                    {
                        'status': IMPORT_google_protobuf_json_format.MessageToDict(
                            exception.to_status()
                        )
                    }
                )
            raise
        else:
            return IMPORT_json.dumps(
                {
                    'response': IMPORT_google_protobuf_json_format.MessageToDict(
                        response
                    )
                }
            )

    async def _schedule(  # type: ignore[override]
        self,
        *,
        method: str,
        context: IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        schedule: IMPORT_reboot_time_DateTimeWithTimeZone,
        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency],
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
    ) -> str:
        request = request_type()

        IMPORT_google_protobuf_json_format.Parse(json_request, request)

        if isinstance(context, IMPORT_reboot_aio_contexts.WriterContext):
            task = await getattr(
                StreamServicerTasks(
                    context=context,
                    state_ref=context._state_ref,
                ),
                method,
            )(request, schedule=schedule)

            return IMPORT_json.dumps(
                {
                    'taskId': IMPORT_google_protobuf_json_format.MessageToDict(
                        task.task_id
                    )
                }
            )

        # Add scheduling information to the metadata.
        metadata: IMPORT_reboot_aio_types.GrpcMetadata = (
            (IMPORT_reboot_aio_headers.TASK_SCHEDULE, schedule.isoformat()),
        )

        task_id = await getattr(super()._tasks(context), method)(
            request,
            idempotency=idempotency,
            metadata=metadata,
        )

        return IMPORT_json.dumps(
            {
                'taskId': IMPORT_google_protobuf_json_format.MessageToDict(task_id)
            }
        )

    async def _reader(  # type: ignore[override]
        self,
        method: str,
        context: IMPORT_reboot_aio_contexts.ReaderContext | IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
        json_options: str,
    ) -> str:
        options = IMPORT_json.loads(json_options)

        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None

        if 'idempotency' in options:
            idempotency = IMPORT_reboot_aio_contexts.Context.idempotency(
                alias=options['idempotency'].get('alias'),
                key=options['idempotency'].get('key'),
                each_iteration=options['idempotency'].get('eachIteration'),
                generated=options['idempotency'].get('generated', False),
            )

        method_handle = IMPORT_functools.partial(
            getattr(super()._reader(context), method),
            bearer_token=options.get("bearerToken"),
            idempotency=idempotency,
        )
        return await self._call(
            callable=method_handle,
            aborted_type=getattr(
                Stream, method + 'Aborted'
            ),
            request_type=request_type,
            json_request=json_request,
        )

    async def _writer(  # type: ignore[override]
        self,
        method: str,
        context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
        json_options: str,
    ) -> str:
        options = IMPORT_json.loads(json_options)

        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None

        if 'idempotency' in options:
            idempotency = IMPORT_reboot_aio_contexts.Context.idempotency(
                alias=options['idempotency'].get('alias'),
                key=options['idempotency'].get('key'),
                each_iteration=options['idempotency'].get('eachIteration'),
                generated=options['idempotency'].get('generated', False),
            )

        if 'schedule' in options:
            when = IMPORT_google_protobuf_timestamp_pb2.Timestamp()
            when.FromJsonString(options['schedule']['when'])
            return await self._schedule(
                method=method,
                context=context,
                schedule=IMPORT_reboot_time_DateTimeWithTimeZone.from_protobuf_timestamp(when),
                idempotency=idempotency,
                request_type=request_type,
                json_request=json_request,
            )

        method_handle = IMPORT_functools.partial(
            getattr(super()._writer(context), method),
            idempotency=idempotency,
            bearer_token=options.get("bearerToken"),
        )
        return await self._call(
            callable=method_handle,
            aborted_type=getattr(
                Stream, method + 'Aborted'
            ),
            request_type=request_type,
            json_request=json_request,
        )

    async def _transaction(  # type: ignore[override]
        self,
        method: str,
        context: IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
        json_options: str,
    ) -> str:
        options = IMPORT_json.loads(json_options)

        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None

        if 'idempotency' in options:
            idempotency = IMPORT_reboot_aio_contexts.Context.idempotency(
                alias=options['idempotency'].get('alias'),
                key=options['idempotency'].get('key'),
                each_iteration=options['idempotency'].get('eachIteration'),
                generated=options['idempotency'].get('generated', False),
            )

        if 'schedule' in options:
            when = IMPORT_google_protobuf_timestamp_pb2.Timestamp()
            when.FromJsonString(options['schedule']['when'])
            return await self._schedule(
                method=method,
                context=context,
                schedule=IMPORT_reboot_time_DateTimeWithTimeZone.from_protobuf_timestamp(when),
                idempotency=idempotency,
                request_type=request_type,
                json_request=json_request,
            )

        method_handle = IMPORT_functools.partial(
            getattr(super()._workflow(context), method),
            idempotency=idempotency,
            bearer_token=options.get("bearerToken"),
        )
        return await self._call(
            callable=method_handle,
            aborted_type=getattr(
                Stream, method + 'Aborted'
            ),
            request_type=request_type,
            json_request=json_request,
        )

    async def _workflow(  # type: ignore[override]
        self,
        method: str,
        context: IMPORT_reboot_aio_contexts.WriterContext | IMPORT_reboot_aio_contexts.TransactionContext | IMPORT_reboot_aio_contexts.WorkflowContext | IMPORT_reboot_aio_external.ExternalContext,
        request_type: type[IMPORT_google_protobuf_message.Message],
        json_request: str,
        json_options: str,
    ) -> str:
        options = IMPORT_json.loads(json_options)

        idempotency: IMPORT_typing.Optional[IMPORT_reboot_aio_idempotency.Idempotency] = None

        if 'idempotency' in options:
            idempotency = IMPORT_reboot_aio_contexts.Context.idempotency(
                alias=options['idempotency'].get('alias'),
                key=options['idempotency'].get('key'),
                each_iteration=options['idempotency'].get('eachIteration'),
                generated=options['idempotency'].get('generated', False),
            )

        assert 'schedule' in options

        when = IMPORT_google_protobuf_timestamp_pb2.Timestamp()
        when.FromJsonString(options['schedule']['when'])

        return await self._schedule(
            method=method,
            context=context,
            schedule=IMPORT_reboot_time_DateTimeWithTimeZone.from_protobuf_timestamp(when),
            idempotency=idempotency,
            request_type=request_type,
            json_request=json_request,
        )

# yapf: enable
