first commit
This commit is contained in:
16
agent_dhal/agentdhal_extensions/runtimes/grpc/__init__.py
Normal file
16
agent_dhal/agentdhal_extensions/runtimes/grpc/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from ._worker_runtime import GrpcWorkerAgentRuntime
|
||||
from ._worker_runtime_host import GrpcWorkerAgentRuntimeHost
|
||||
from ._worker_runtime_host_servicer import GrpcWorkerAgentRuntimeHostServicer
|
||||
|
||||
try:
|
||||
import grpc # type: ignore
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
"To use the GRPC runtime the grpc extra must be installed. Run `pip install autogen-ext[grpc]`"
|
||||
) from e
|
||||
|
||||
__all__ = [
|
||||
"GrpcWorkerAgentRuntime",
|
||||
"GrpcWorkerAgentRuntimeHost",
|
||||
"GrpcWorkerAgentRuntimeHostServicer",
|
||||
]
|
||||
13
agent_dhal/agentdhal_extensions/runtimes/grpc/_constants.py
Normal file
13
agent_dhal/agentdhal_extensions/runtimes/grpc/_constants.py
Normal file
@@ -0,0 +1,13 @@
|
||||
GRPC_IMPORT_ERROR_STR = (
|
||||
"Distributed runtime features require additional dependencies. Install them with: pip install autogen-core[grpc]"
|
||||
)
|
||||
|
||||
DATA_CONTENT_TYPE_ATTR = "datacontenttype"
|
||||
DATA_SCHEMA_ATTR = "dataschema"
|
||||
AGENT_SENDER_TYPE_ATTR = "agagentsendertype"
|
||||
AGENT_SENDER_KEY_ATTR = "agagentsenderkey"
|
||||
MESSAGE_KIND_ATTR = "agmsgkind"
|
||||
MESSAGE_KIND_VALUE_PUBLISH = "publish"
|
||||
MESSAGE_KIND_VALUE_RPC_REQUEST = "rpc_request"
|
||||
MESSAGE_KIND_VALUE_RPC_RESPONSE = "rpc_response"
|
||||
MESSAGE_KIND_VALUE_RPC_ERROR = "error"
|
||||
@@ -0,0 +1,4 @@
|
||||
from typing import Any, Sequence, Tuple
|
||||
|
||||
# Had to redefine this from grpc.aio._typing as using that one was causing mypy errors
|
||||
ChannelArgumentType = Sequence[Tuple[str, Any]]
|
||||
45
agent_dhal/agentdhal_extensions/runtimes/grpc/_utils.py
Normal file
45
agent_dhal/agentdhal_extensions/runtimes/grpc/_utils.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from agentdhal_core._subscription import Subscription
|
||||
from agentdhal_core._type_prefix_subscription import TypePrefixSubscription
|
||||
from agentdhal_core._type_subscription import TypeSubscription
|
||||
|
||||
from .protos import agent_worker_pb2
|
||||
|
||||
|
||||
def subscription_to_proto(subscription: Subscription) -> agent_worker_pb2.Subscription:
|
||||
match subscription:
|
||||
case TypeSubscription(topic_type=topic_type, agent_type=agent_type, id=id):
|
||||
return agent_worker_pb2.Subscription(
|
||||
id=id,
|
||||
typeSubscription=agent_worker_pb2.TypeSubscription(topic_type=topic_type, agent_type=agent_type),
|
||||
)
|
||||
case TypePrefixSubscription(topic_type_prefix=topic_type_prefix, agent_type=agent_type, id=id):
|
||||
return agent_worker_pb2.Subscription(
|
||||
id=id,
|
||||
typePrefixSubscription=agent_worker_pb2.TypePrefixSubscription(
|
||||
topic_type_prefix=topic_type_prefix, agent_type=agent_type
|
||||
),
|
||||
)
|
||||
case _:
|
||||
raise ValueError("Unsupported subscription type.")
|
||||
|
||||
|
||||
def subscription_from_proto(subscription: agent_worker_pb2.Subscription) -> Subscription:
|
||||
oneofcase = subscription.WhichOneof("subscription")
|
||||
match oneofcase:
|
||||
case "typeSubscription":
|
||||
type_subscription_msg: agent_worker_pb2.TypeSubscription = subscription.typeSubscription
|
||||
return TypeSubscription(
|
||||
topic_type=type_subscription_msg.topic_type,
|
||||
agent_type=type_subscription_msg.agent_type,
|
||||
id=subscription.id,
|
||||
)
|
||||
|
||||
case "typePrefixSubscription":
|
||||
type_prefix_subscription_msg: agent_worker_pb2.TypePrefixSubscription = subscription.typePrefixSubscription
|
||||
return TypePrefixSubscription(
|
||||
topic_type_prefix=type_prefix_subscription_msg.topic_type_prefix,
|
||||
agent_type=type_prefix_subscription_msg.agent_type,
|
||||
id=subscription.id,
|
||||
)
|
||||
case None:
|
||||
raise ValueError("Invalid subscription message.")
|
||||
856
agent_dhal/agentdhal_extensions/runtimes/grpc/_worker_runtime.py
Normal file
856
agent_dhal/agentdhal_extensions/runtimes/grpc/_worker_runtime.py
Normal file
@@ -0,0 +1,856 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import signal
|
||||
import uuid
|
||||
import warnings
|
||||
from asyncio import Future, Task
|
||||
from collections import defaultdict
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
AsyncIterable,
|
||||
AsyncIterator,
|
||||
Awaitable,
|
||||
Callable,
|
||||
ClassVar,
|
||||
DefaultDict,
|
||||
Dict,
|
||||
List,
|
||||
Literal,
|
||||
Mapping,
|
||||
ParamSpec,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
cast,
|
||||
)
|
||||
|
||||
from agentdhal_core import (
|
||||
JSON_DATA_CONTENT_TYPE,
|
||||
PROTOBUF_DATA_CONTENT_TYPE,
|
||||
Agent,
|
||||
AgentId,
|
||||
AgentInstantiationContext,
|
||||
AgentMetadata,
|
||||
AgentRuntime,
|
||||
AgentType,
|
||||
CancellationToken,
|
||||
MessageContext,
|
||||
MessageHandlerContext,
|
||||
MessageSerializer,
|
||||
Subscription,
|
||||
TopicId,
|
||||
)
|
||||
from agentdhal_core._runtime_impl_helpers import SubscriptionManager, get_impl
|
||||
from agentdhal_core._serialization import (
|
||||
SerializationRegistry,
|
||||
)
|
||||
from agentdhal_core._telemetry import MessageRuntimeTracingConfig, TraceHelper, get_telemetry_grpc_metadata
|
||||
from google.protobuf import any_pb2
|
||||
from opentelemetry.trace import TracerProvider
|
||||
from typing_extensions import Self
|
||||
|
||||
from agentdhal_extensions.runtimes.grpc._utils import subscription_to_proto
|
||||
|
||||
from . import _constants
|
||||
from ._constants import GRPC_IMPORT_ERROR_STR
|
||||
from ._type_helpers import ChannelArgumentType
|
||||
from .protos import agent_worker_pb2, agent_worker_pb2_grpc, cloudevent_pb2
|
||||
|
||||
try:
|
||||
import grpc.aio
|
||||
except ImportError as e:
|
||||
raise ImportError(GRPC_IMPORT_ERROR_STR) from e
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .protos.agent_worker_pb2_grpc import AgentRpcAsyncStub
|
||||
|
||||
logger = logging.getLogger("agentdhal_core")
|
||||
event_logger = logging.getLogger("agentdhal_core.events")
|
||||
|
||||
P = ParamSpec("P")
|
||||
T = TypeVar("T", bound=Agent)
|
||||
|
||||
|
||||
type_func_alias = type
|
||||
|
||||
|
||||
class QueueAsyncIterable(AsyncIterator[Any], AsyncIterable[Any]):
|
||||
def __init__(self, queue: asyncio.Queue[Any]) -> None:
|
||||
self._queue = queue
|
||||
|
||||
async def __anext__(self) -> Any:
|
||||
return await self._queue.get()
|
||||
|
||||
def __aiter__(self) -> AsyncIterator[Any]:
|
||||
return self
|
||||
|
||||
|
||||
class HostConnection:
|
||||
DEFAULT_GRPC_CONFIG: ClassVar[ChannelArgumentType] = [
|
||||
(
|
||||
"grpc.service_config",
|
||||
json.dumps(
|
||||
{
|
||||
"methodConfig": [
|
||||
{
|
||||
"name": [{}],
|
||||
"retryPolicy": {
|
||||
"maxAttempts": 3,
|
||||
"initialBackoff": "0.01s",
|
||||
"maxBackoff": "5s",
|
||||
"backoffMultiplier": 2,
|
||||
"retryableStatusCodes": ["UNAVAILABLE"],
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
def __init__(self, channel: grpc.aio.Channel, stub: Any) -> None: # type: ignore
|
||||
self._channel = channel
|
||||
self._send_queue = asyncio.Queue[agent_worker_pb2.Message]()
|
||||
self._recv_queue = asyncio.Queue[agent_worker_pb2.Message]()
|
||||
self._connection_task: Task[None] | None = None
|
||||
self._stub: AgentRpcAsyncStub = stub
|
||||
self._client_id = str(uuid.uuid4())
|
||||
|
||||
@property
|
||||
def stub(self) -> Any:
|
||||
return self._stub
|
||||
|
||||
@property
|
||||
def metadata(self) -> Sequence[Tuple[str, str]]:
|
||||
return [("client-id", self._client_id)]
|
||||
|
||||
@classmethod
|
||||
async def from_host_address(
|
||||
cls, host_address: str, extra_grpc_config: ChannelArgumentType = DEFAULT_GRPC_CONFIG
|
||||
) -> Self:
|
||||
logger.info("Connecting to %s", host_address)
|
||||
# Always use DEFAULT_GRPC_CONFIG and override it with provided grpc_config
|
||||
merged_options = [
|
||||
(k, v) for k, v in {**dict(HostConnection.DEFAULT_GRPC_CONFIG), **dict(extra_grpc_config)}.items()
|
||||
]
|
||||
|
||||
channel = grpc.aio.insecure_channel(
|
||||
host_address,
|
||||
options=merged_options,
|
||||
)
|
||||
stub: AgentRpcAsyncStub = agent_worker_pb2_grpc.AgentRpcStub(channel) # type: ignore
|
||||
instance = cls(channel, stub)
|
||||
|
||||
instance._connection_task = await instance._connect(
|
||||
stub, instance._send_queue, instance._recv_queue, instance._client_id
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
async def close(self) -> None:
|
||||
if self._connection_task is None:
|
||||
raise RuntimeError("Connection is not open.")
|
||||
await self._channel.close()
|
||||
await self._connection_task
|
||||
|
||||
@staticmethod
|
||||
async def _connect(
|
||||
stub: Any, # AgentRpcAsyncStub
|
||||
send_queue: asyncio.Queue[agent_worker_pb2.Message],
|
||||
receive_queue: asyncio.Queue[agent_worker_pb2.Message],
|
||||
client_id: str,
|
||||
) -> Task[None]:
|
||||
from grpc.aio import StreamStreamCall
|
||||
|
||||
# TODO: where do exceptions from reading the iterable go? How do we recover from those?
|
||||
stream: StreamStreamCall[agent_worker_pb2.Message, agent_worker_pb2.Message] = stub.OpenChannel( # type: ignore
|
||||
QueueAsyncIterable(send_queue), metadata=[("client-id", client_id)]
|
||||
)
|
||||
|
||||
await stream.wait_for_connection()
|
||||
|
||||
async def read_loop() -> None:
|
||||
while True:
|
||||
logger.info("Waiting for message from host")
|
||||
message = cast(agent_worker_pb2.Message, await stream.read()) # type: ignore
|
||||
if message == grpc.aio.EOF: # type: ignore
|
||||
logger.info("EOF")
|
||||
break
|
||||
logger.info(f"Received a message from host: {message}")
|
||||
await receive_queue.put(message)
|
||||
logger.info("Put message in receive queue")
|
||||
|
||||
return asyncio.create_task(read_loop())
|
||||
|
||||
async def send(self, message: agent_worker_pb2.Message) -> None:
|
||||
logger.info(f"Send message to host: {message}")
|
||||
await self._send_queue.put(message)
|
||||
logger.info("Put message in send queue")
|
||||
|
||||
async def recv(self) -> agent_worker_pb2.Message:
|
||||
logger.info("Getting message from queue")
|
||||
return await self._recv_queue.get()
|
||||
|
||||
|
||||
# TODO: Lots of types need to have protobuf equivalents:
|
||||
# Core:
|
||||
# - FunctionCall, CodeResult, possibly CodeBlock
|
||||
# - All the types in https://github.com/microsoft/autogen/blob/main/python/packages/autogen-core/src/agentdhal_core/models/_types.py
|
||||
#
|
||||
# Agentchat:
|
||||
# - All the types in https://github.com/microsoft/autogen/blob/main/python/packages/autogen-agentchat/src/agentdhal_agentchat/messages.py to protobufs.
|
||||
#
|
||||
# Ext --
|
||||
# CodeExecutor:
|
||||
# - CommandLineCodeResult
|
||||
|
||||
|
||||
class GrpcWorkerAgentRuntime(AgentRuntime):
|
||||
"""An agent runtime for running remote or cross-language agents.
|
||||
|
||||
Agent messaging uses protobufs from `agent_worker.proto`_ and ``CloudEvent`` from `cloudevent.proto`_.
|
||||
|
||||
Cross-language agents will additionally require all agents use shared protobuf schemas for any message types that are sent between agents.
|
||||
|
||||
.. _agent_worker.proto: https://github.com/microsoft/autogen/blob/main/protos/agent_worker.proto
|
||||
|
||||
.. _cloudevent.proto: https://github.com/microsoft/autogen/blob/main/protos/cloudevent.proto
|
||||
|
||||
"""
|
||||
|
||||
# TODO: Needs to handle agent close() call
|
||||
def __init__(
|
||||
self,
|
||||
host_address: str,
|
||||
tracer_provider: TracerProvider | None = None,
|
||||
extra_grpc_config: ChannelArgumentType | None = None,
|
||||
payload_serialization_format: str = JSON_DATA_CONTENT_TYPE,
|
||||
) -> None:
|
||||
self._host_address = host_address
|
||||
self._trace_helper = TraceHelper(tracer_provider, MessageRuntimeTracingConfig("Worker Runtime"))
|
||||
self._per_type_subscribers: DefaultDict[tuple[str, str], Set[AgentId]] = defaultdict(set)
|
||||
self._agent_factories: Dict[
|
||||
str, Callable[[], Agent | Awaitable[Agent]] | Callable[[AgentRuntime, AgentId], Agent | Awaitable[Agent]]
|
||||
] = {}
|
||||
self._instantiated_agents: Dict[AgentId, Agent] = {}
|
||||
self._known_namespaces: set[str] = set()
|
||||
self._read_task: None | Task[None] = None
|
||||
self._running = False
|
||||
self._pending_requests: Dict[str, Future[Any]] = {}
|
||||
self._pending_requests_lock = asyncio.Lock()
|
||||
self._next_request_id = 0
|
||||
self._host_connection: HostConnection | None = None
|
||||
self._background_tasks: Set[Task[Any]] = set()
|
||||
self._subscription_manager = SubscriptionManager()
|
||||
self._serialization_registry = SerializationRegistry()
|
||||
self._extra_grpc_config = extra_grpc_config or []
|
||||
self._agent_instance_types: Dict[str, Type[Agent]] = {}
|
||||
|
||||
if payload_serialization_format not in {JSON_DATA_CONTENT_TYPE, PROTOBUF_DATA_CONTENT_TYPE}:
|
||||
raise ValueError(f"Unsupported payload serialization format: {payload_serialization_format}")
|
||||
|
||||
self._payload_serialization_format = payload_serialization_format
|
||||
|
||||
async def start(self) -> None:
|
||||
"""Start the runtime in a background task."""
|
||||
if self._running:
|
||||
raise ValueError("Runtime is already running.")
|
||||
logger.info(f"Connecting to host: {self._host_address}")
|
||||
self._host_connection = await HostConnection.from_host_address(
|
||||
self._host_address, extra_grpc_config=self._extra_grpc_config
|
||||
)
|
||||
logger.info("Connection established")
|
||||
if self._read_task is None:
|
||||
self._read_task = asyncio.create_task(self._run_read_loop())
|
||||
self._running = True
|
||||
|
||||
def _raise_on_exception(self, task: Task[Any]) -> None:
|
||||
exception = task.exception()
|
||||
if exception is not None:
|
||||
raise exception
|
||||
|
||||
async def _run_read_loop(self) -> None:
|
||||
logger.info("Starting read loop")
|
||||
assert self._host_connection is not None
|
||||
# TODO: catch exceptions and reconnect
|
||||
while self._running:
|
||||
try:
|
||||
message = await self._host_connection.recv()
|
||||
oneofcase = agent_worker_pb2.Message.WhichOneof(message, "message")
|
||||
match oneofcase:
|
||||
case "request":
|
||||
task = asyncio.create_task(self._process_request(message.request))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case "response":
|
||||
task = asyncio.create_task(self._process_response(message.response))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case "cloudEvent":
|
||||
task = asyncio.create_task(self._process_event(message.cloudEvent))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case None:
|
||||
logger.warning("No message")
|
||||
except Exception as e:
|
||||
logger.error("Error in read loop", exc_info=e)
|
||||
|
||||
async def stop(self) -> None:
|
||||
"""Stop the runtime immediately."""
|
||||
if not self._running:
|
||||
raise RuntimeError("Runtime is not running.")
|
||||
self._running = False
|
||||
# Wait for all background tasks to finish.
|
||||
final_tasks_results = await asyncio.gather(*self._background_tasks, return_exceptions=True)
|
||||
for task_result in final_tasks_results:
|
||||
if isinstance(task_result, Exception):
|
||||
logger.error("Error in background task", exc_info=task_result)
|
||||
# Close the host connection.
|
||||
if self._host_connection is not None:
|
||||
try:
|
||||
await self._host_connection.close()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
# Cancel the read task.
|
||||
if self._read_task is not None:
|
||||
self._read_task.cancel()
|
||||
try:
|
||||
await self._read_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
async def stop_when_signal(self, signals: Sequence[signal.Signals] = (signal.SIGTERM, signal.SIGINT)) -> None:
|
||||
"""Stop the runtime when a signal is received."""
|
||||
loop = asyncio.get_running_loop()
|
||||
shutdown_event = asyncio.Event()
|
||||
|
||||
def signal_handler() -> None:
|
||||
logger.info("Received exit signal, shutting down gracefully...")
|
||||
shutdown_event.set()
|
||||
|
||||
for sig in signals:
|
||||
loop.add_signal_handler(sig, signal_handler)
|
||||
|
||||
# Wait for the signal to trigger the shutdown event.
|
||||
await shutdown_event.wait()
|
||||
|
||||
# Stop the runtime.
|
||||
await self.stop()
|
||||
|
||||
@property
|
||||
def _known_agent_names(self) -> Set[str]:
|
||||
return set(self._agent_factories.keys())
|
||||
|
||||
async def _send_message(
|
||||
self,
|
||||
runtime_message: agent_worker_pb2.Message,
|
||||
send_type: Literal["send", "publish"],
|
||||
recipient: AgentId | TopicId,
|
||||
telemetry_metadata: Mapping[str, str],
|
||||
) -> None:
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
with self._trace_helper.trace_block(send_type, recipient, parent=telemetry_metadata):
|
||||
await self._host_connection.send(runtime_message)
|
||||
|
||||
async def send_message(
|
||||
self,
|
||||
message: Any,
|
||||
recipient: AgentId,
|
||||
*,
|
||||
sender: AgentId | None = None,
|
||||
cancellation_token: CancellationToken | None = None,
|
||||
message_id: str | None = None,
|
||||
) -> Any:
|
||||
# TODO: use message_id
|
||||
if not self._running:
|
||||
raise ValueError("Runtime must be running when sending message.")
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
data_type = self._serialization_registry.type_name(message)
|
||||
with self._trace_helper.trace_block(
|
||||
"create", recipient, parent=None, extraAttributes={"message_type": data_type}
|
||||
):
|
||||
# create a new future for the result
|
||||
future = asyncio.get_event_loop().create_future()
|
||||
request_id = await self._get_new_request_id()
|
||||
self._pending_requests[request_id] = future
|
||||
serialized_message = self._serialization_registry.serialize(
|
||||
message, type_name=data_type, data_content_type=JSON_DATA_CONTENT_TYPE
|
||||
)
|
||||
telemetry_metadata = get_telemetry_grpc_metadata()
|
||||
runtime_message = agent_worker_pb2.Message(
|
||||
request=agent_worker_pb2.RpcRequest(
|
||||
request_id=request_id,
|
||||
target=agent_worker_pb2.AgentId(type=recipient.type, key=recipient.key),
|
||||
source=agent_worker_pb2.AgentId(type=sender.type, key=sender.key) if sender is not None else None,
|
||||
metadata=telemetry_metadata,
|
||||
payload=agent_worker_pb2.Payload(
|
||||
data_type=data_type,
|
||||
data=serialized_message,
|
||||
data_content_type=JSON_DATA_CONTENT_TYPE,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
# TODO: Find a way to handle timeouts/errors
|
||||
task = asyncio.create_task(self._send_message(runtime_message, "send", recipient, telemetry_metadata))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
return await future
|
||||
|
||||
async def publish_message(
|
||||
self,
|
||||
message: Any,
|
||||
topic_id: TopicId,
|
||||
*,
|
||||
sender: AgentId | None = None,
|
||||
cancellation_token: CancellationToken | None = None,
|
||||
message_id: str | None = None,
|
||||
) -> None:
|
||||
if not self._running:
|
||||
raise ValueError("Runtime must be running when publishing message.")
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
if message_id is None:
|
||||
message_id = str(uuid.uuid4())
|
||||
|
||||
message_type = self._serialization_registry.type_name(message)
|
||||
with self._trace_helper.trace_block(
|
||||
"create", topic_id, parent=None, extraAttributes={"message_type": message_type}
|
||||
):
|
||||
serialized_message = self._serialization_registry.serialize(
|
||||
message, type_name=message_type, data_content_type=self._payload_serialization_format
|
||||
)
|
||||
|
||||
sender_id = sender or AgentId("unknown", "unknown")
|
||||
attributes = {
|
||||
_constants.DATA_CONTENT_TYPE_ATTR: cloudevent_pb2.CloudEvent.CloudEventAttributeValue(
|
||||
ce_string=self._payload_serialization_format
|
||||
),
|
||||
_constants.DATA_SCHEMA_ATTR: cloudevent_pb2.CloudEvent.CloudEventAttributeValue(ce_string=message_type),
|
||||
_constants.AGENT_SENDER_TYPE_ATTR: cloudevent_pb2.CloudEvent.CloudEventAttributeValue(
|
||||
ce_string=sender_id.type
|
||||
),
|
||||
_constants.AGENT_SENDER_KEY_ATTR: cloudevent_pb2.CloudEvent.CloudEventAttributeValue(
|
||||
ce_string=sender_id.key
|
||||
),
|
||||
_constants.MESSAGE_KIND_ATTR: cloudevent_pb2.CloudEvent.CloudEventAttributeValue(
|
||||
ce_string=_constants.MESSAGE_KIND_VALUE_PUBLISH
|
||||
),
|
||||
}
|
||||
|
||||
# If sending JSON we fill text_data with the serialized message
|
||||
# If sending Protobuf we fill proto_data with the serialized message
|
||||
# TODO: add an encoding field for serializer
|
||||
|
||||
if self._payload_serialization_format == JSON_DATA_CONTENT_TYPE:
|
||||
runtime_message = agent_worker_pb2.Message(
|
||||
cloudEvent=cloudevent_pb2.CloudEvent(
|
||||
id=message_id,
|
||||
spec_version="1.0",
|
||||
type=topic_id.type,
|
||||
source=topic_id.source,
|
||||
attributes=attributes,
|
||||
# TODO: use text, or proto fields appropriately
|
||||
binary_data=serialized_message,
|
||||
)
|
||||
)
|
||||
else:
|
||||
# We need to unpack the serialized proto back into an Any
|
||||
# TODO: find a way to prevent the roundtrip serialization
|
||||
any_proto = any_pb2.Any()
|
||||
any_proto.ParseFromString(serialized_message)
|
||||
runtime_message = agent_worker_pb2.Message(
|
||||
cloudEvent=cloudevent_pb2.CloudEvent(
|
||||
id=message_id,
|
||||
spec_version="1.0",
|
||||
type=topic_id.type,
|
||||
source=topic_id.source,
|
||||
attributes=attributes,
|
||||
proto_data=any_proto,
|
||||
)
|
||||
)
|
||||
|
||||
telemetry_metadata = get_telemetry_grpc_metadata()
|
||||
task = asyncio.create_task(self._send_message(runtime_message, "publish", topic_id, telemetry_metadata))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
|
||||
async def save_state(self) -> Mapping[str, Any]:
|
||||
raise NotImplementedError("Saving state is not yet implemented.")
|
||||
|
||||
async def load_state(self, state: Mapping[str, Any]) -> None:
|
||||
raise NotImplementedError("Loading state is not yet implemented.")
|
||||
|
||||
async def agent_metadata(self, agent: AgentId) -> AgentMetadata:
|
||||
raise NotImplementedError("Agent metadata is not yet implemented.")
|
||||
|
||||
async def agent_save_state(self, agent: AgentId) -> Mapping[str, Any]:
|
||||
raise NotImplementedError("Agent save_state is not yet implemented.")
|
||||
|
||||
async def agent_load_state(self, agent: AgentId, state: Mapping[str, Any]) -> None:
|
||||
raise NotImplementedError("Agent load_state is not yet implemented.")
|
||||
|
||||
async def _get_new_request_id(self) -> str:
|
||||
async with self._pending_requests_lock:
|
||||
self._next_request_id += 1
|
||||
return str(self._next_request_id)
|
||||
|
||||
async def _process_request(self, request: agent_worker_pb2.RpcRequest) -> None:
|
||||
assert self._host_connection is not None
|
||||
recipient = AgentId(request.target.type, request.target.key)
|
||||
sender: AgentId | None = None
|
||||
if request.HasField("source"):
|
||||
sender = AgentId(request.source.type, request.source.key)
|
||||
logging.info(f"Processing request from {sender} to {recipient}")
|
||||
else:
|
||||
logging.info(f"Processing request from unknown source to {recipient}")
|
||||
|
||||
# Deserialize the message.
|
||||
message = self._serialization_registry.deserialize(
|
||||
request.payload.data,
|
||||
type_name=request.payload.data_type,
|
||||
data_content_type=request.payload.data_content_type,
|
||||
)
|
||||
|
||||
# Get the receiving agent and prepare the message context.
|
||||
rec_agent = await self._get_agent(recipient)
|
||||
message_context = MessageContext(
|
||||
sender=sender,
|
||||
topic_id=None,
|
||||
is_rpc=True,
|
||||
cancellation_token=CancellationToken(),
|
||||
message_id=request.request_id,
|
||||
)
|
||||
|
||||
# Call the receiving agent.
|
||||
try:
|
||||
with MessageHandlerContext.populate_context(rec_agent.id):
|
||||
with self._trace_helper.trace_block(
|
||||
"process",
|
||||
rec_agent.id,
|
||||
parent=request.metadata,
|
||||
attributes={"request_id": request.request_id},
|
||||
extraAttributes={"message_type": request.payload.data_type},
|
||||
):
|
||||
result = await rec_agent.on_message(message, ctx=message_context)
|
||||
except BaseException as e:
|
||||
response_message = agent_worker_pb2.Message(
|
||||
response=agent_worker_pb2.RpcResponse(
|
||||
request_id=request.request_id,
|
||||
error=str(e),
|
||||
metadata=get_telemetry_grpc_metadata(),
|
||||
),
|
||||
)
|
||||
# Send the error response.
|
||||
await self._host_connection.send(response_message)
|
||||
return
|
||||
|
||||
# Serialize the result.
|
||||
result_type = self._serialization_registry.type_name(result)
|
||||
serialized_result = self._serialization_registry.serialize(
|
||||
result, type_name=result_type, data_content_type=JSON_DATA_CONTENT_TYPE
|
||||
)
|
||||
|
||||
# Create the response message.
|
||||
response_message = agent_worker_pb2.Message(
|
||||
response=agent_worker_pb2.RpcResponse(
|
||||
request_id=request.request_id,
|
||||
payload=agent_worker_pb2.Payload(
|
||||
data_type=result_type,
|
||||
data=serialized_result,
|
||||
data_content_type=JSON_DATA_CONTENT_TYPE,
|
||||
),
|
||||
metadata=get_telemetry_grpc_metadata(),
|
||||
)
|
||||
)
|
||||
|
||||
# Send the response.
|
||||
await self._host_connection.send(response_message)
|
||||
|
||||
async def _process_response(self, response: agent_worker_pb2.RpcResponse) -> None:
|
||||
with self._trace_helper.trace_block(
|
||||
"ack",
|
||||
None,
|
||||
parent=response.metadata,
|
||||
attributes={"request_id": response.request_id},
|
||||
extraAttributes={"message_type": response.payload.data_type},
|
||||
):
|
||||
# Deserialize the result.
|
||||
result = self._serialization_registry.deserialize(
|
||||
response.payload.data,
|
||||
type_name=response.payload.data_type,
|
||||
data_content_type=response.payload.data_content_type,
|
||||
)
|
||||
# Get the future and set the result.
|
||||
future = self._pending_requests.pop(response.request_id)
|
||||
if len(response.error) > 0:
|
||||
future.set_exception(Exception(response.error))
|
||||
else:
|
||||
future.set_result(result)
|
||||
|
||||
async def _process_event(self, event: cloudevent_pb2.CloudEvent) -> None:
|
||||
event_attributes = event.attributes
|
||||
sender: AgentId | None = None
|
||||
if (
|
||||
_constants.AGENT_SENDER_TYPE_ATTR in event_attributes
|
||||
and _constants.AGENT_SENDER_KEY_ATTR in event_attributes
|
||||
):
|
||||
sender = AgentId(
|
||||
event_attributes[_constants.AGENT_SENDER_TYPE_ATTR].ce_string,
|
||||
event_attributes[_constants.AGENT_SENDER_KEY_ATTR].ce_string,
|
||||
)
|
||||
topic_id = TopicId(event.type, event.source)
|
||||
# Get the recipients for the topic.
|
||||
recipients = await self._subscription_manager.get_subscribed_recipients(topic_id)
|
||||
|
||||
message_content_type = event_attributes[_constants.DATA_CONTENT_TYPE_ATTR].ce_string
|
||||
message_type = event_attributes[_constants.DATA_SCHEMA_ATTR].ce_string
|
||||
|
||||
if message_content_type == JSON_DATA_CONTENT_TYPE:
|
||||
message = self._serialization_registry.deserialize(
|
||||
event.binary_data, type_name=message_type, data_content_type=message_content_type
|
||||
)
|
||||
elif message_content_type == PROTOBUF_DATA_CONTENT_TYPE:
|
||||
# TODO: find a way to prevent the roundtrip serialization
|
||||
proto_binary_data = event.proto_data.SerializeToString()
|
||||
message = self._serialization_registry.deserialize(
|
||||
proto_binary_data, type_name=message_type, data_content_type=message_content_type
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unsupported message content type: {message_content_type}")
|
||||
|
||||
# TODO: dont read these values in the runtime
|
||||
topic_type_suffix = topic_id.type.split(":", maxsplit=1)[1] if ":" in topic_id.type else ""
|
||||
is_rpc = topic_type_suffix == _constants.MESSAGE_KIND_VALUE_RPC_REQUEST
|
||||
is_marked_rpc_type = (
|
||||
_constants.MESSAGE_KIND_ATTR in event_attributes
|
||||
and event_attributes[_constants.MESSAGE_KIND_ATTR].ce_string == _constants.MESSAGE_KIND_VALUE_RPC_REQUEST
|
||||
)
|
||||
if is_rpc and not is_marked_rpc_type:
|
||||
warnings.warn("Received RPC request with topic type suffix but not marked as RPC request.", stacklevel=2)
|
||||
|
||||
# Send the message to each recipient.
|
||||
responses: List[Awaitable[Any]] = []
|
||||
for agent_id in recipients:
|
||||
if agent_id == sender:
|
||||
continue
|
||||
message_context = MessageContext(
|
||||
sender=sender,
|
||||
topic_id=topic_id,
|
||||
is_rpc=is_rpc,
|
||||
cancellation_token=CancellationToken(),
|
||||
message_id=event.id,
|
||||
)
|
||||
agent = await self._get_agent(agent_id)
|
||||
with MessageHandlerContext.populate_context(agent.id):
|
||||
|
||||
def stringify_attributes(
|
||||
attributes: Mapping[str, cloudevent_pb2.CloudEvent.CloudEventAttributeValue],
|
||||
) -> Mapping[str, str]:
|
||||
result: Dict[str, str] = {}
|
||||
for key, value in attributes.items():
|
||||
item = None
|
||||
match value.WhichOneof("attr"):
|
||||
case "ce_boolean":
|
||||
item = str(value.ce_boolean)
|
||||
case "ce_integer":
|
||||
item = str(value.ce_integer)
|
||||
case "ce_string":
|
||||
item = value.ce_string
|
||||
case "ce_bytes":
|
||||
item = str(value.ce_bytes)
|
||||
case "ce_uri":
|
||||
item = value.ce_uri
|
||||
case "ce_uri_ref":
|
||||
item = value.ce_uri_ref
|
||||
case "ce_timestamp":
|
||||
item = str(value.ce_timestamp)
|
||||
case _:
|
||||
raise ValueError("Unknown attribute kind")
|
||||
result[key] = item
|
||||
|
||||
return result
|
||||
|
||||
async def send_message(agent: Agent, message_context: MessageContext) -> Any:
|
||||
with self._trace_helper.trace_block(
|
||||
"process",
|
||||
agent.id,
|
||||
parent=stringify_attributes(event.attributes),
|
||||
extraAttributes={"message_type": message_type},
|
||||
):
|
||||
await agent.on_message(message, ctx=message_context)
|
||||
|
||||
future = send_message(agent, message_context)
|
||||
responses.append(future)
|
||||
# Wait for all responses.
|
||||
try:
|
||||
await asyncio.gather(*responses)
|
||||
except BaseException as e:
|
||||
logger.error("Error handling event", exc_info=e)
|
||||
|
||||
async def _register_agent_type(self, agent_type: str) -> None:
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
message = agent_worker_pb2.RegisterAgentTypeRequest(type=agent_type)
|
||||
_response: agent_worker_pb2.RegisterAgentTypeResponse = await self._host_connection.stub.RegisterAgent(
|
||||
message, metadata=self._host_connection.metadata
|
||||
)
|
||||
|
||||
async def register_factory(
|
||||
self,
|
||||
type: str | AgentType,
|
||||
agent_factory: Callable[[], T | Awaitable[T]],
|
||||
*,
|
||||
expected_class: type[T] | None = None,
|
||||
) -> AgentType:
|
||||
if isinstance(type, str):
|
||||
type = AgentType(type)
|
||||
|
||||
if type.type in self._agent_factories:
|
||||
raise ValueError(f"Agent with type {type} already exists.")
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
|
||||
async def factory_wrapper() -> T:
|
||||
maybe_agent_instance = agent_factory()
|
||||
if inspect.isawaitable(maybe_agent_instance):
|
||||
agent_instance = await maybe_agent_instance
|
||||
else:
|
||||
agent_instance = maybe_agent_instance
|
||||
|
||||
if expected_class is not None and type_func_alias(agent_instance) != expected_class:
|
||||
raise ValueError("Factory registered using the wrong type.")
|
||||
|
||||
return agent_instance
|
||||
|
||||
self._agent_factories[type.type] = factory_wrapper
|
||||
# Send the registration request message to the host.
|
||||
await self._register_agent_type(type.type)
|
||||
|
||||
return type
|
||||
|
||||
async def register_agent_instance(
|
||||
self,
|
||||
agent_instance: Agent,
|
||||
agent_id: AgentId,
|
||||
) -> AgentId:
|
||||
def agent_factory() -> Agent:
|
||||
raise RuntimeError(
|
||||
"Agent factory was invoked for an agent instance that was not registered. This is likely due to the agent type being incorrectly subscribed to a topic. If this exception occurs when publishing a message to the DefaultTopicId, then it is likely that `skip_class_subscriptions` needs to be turned off when registering the agent."
|
||||
)
|
||||
|
||||
if agent_id in self._instantiated_agents:
|
||||
raise ValueError(f"Agent with id {agent_id} already exists.")
|
||||
|
||||
if agent_id.type not in self._agent_factories:
|
||||
self._agent_factories[agent_id.type] = agent_factory
|
||||
await self._register_agent_type(agent_id.type)
|
||||
self._agent_instance_types[agent_id.type] = type_func_alias(agent_instance)
|
||||
else:
|
||||
if self._agent_factories[agent_id.type].__code__ != agent_factory.__code__:
|
||||
raise ValueError("Agent factories and agent instances cannot be registered to the same type.")
|
||||
if self._agent_instance_types[agent_id.type] != type_func_alias(agent_instance):
|
||||
raise ValueError("Agent instances must be the same object type.")
|
||||
|
||||
await agent_instance.bind_id_and_runtime(id=agent_id, runtime=self)
|
||||
self._instantiated_agents[agent_id] = agent_instance
|
||||
return agent_id
|
||||
|
||||
async def _invoke_agent_factory(
|
||||
self,
|
||||
agent_factory: Callable[[], T | Awaitable[T]] | Callable[[AgentRuntime, AgentId], T | Awaitable[T]],
|
||||
agent_id: AgentId,
|
||||
) -> T:
|
||||
with AgentInstantiationContext.populate_context((self, agent_id)):
|
||||
if len(inspect.signature(agent_factory).parameters) == 0:
|
||||
factory_one = cast(Callable[[], T], agent_factory)
|
||||
agent = factory_one()
|
||||
elif len(inspect.signature(agent_factory).parameters) == 2:
|
||||
warnings.warn(
|
||||
"Agent factories that take two arguments are deprecated. Use AgentInstantiationContext instead. Two arg factories will be removed in a future version.",
|
||||
stacklevel=2,
|
||||
)
|
||||
factory_two = cast(Callable[[AgentRuntime, AgentId], T], agent_factory)
|
||||
agent = factory_two(self, agent_id)
|
||||
else:
|
||||
raise ValueError("Agent factory must take 0 or 2 arguments.")
|
||||
|
||||
if inspect.isawaitable(agent):
|
||||
agent = cast(T, await agent)
|
||||
|
||||
return agent
|
||||
|
||||
async def _get_agent(self, agent_id: AgentId) -> Agent:
|
||||
if agent_id in self._instantiated_agents:
|
||||
return self._instantiated_agents[agent_id]
|
||||
|
||||
if agent_id.type not in self._agent_factories:
|
||||
raise ValueError(f"Agent with name {agent_id.type} not found.")
|
||||
|
||||
agent_factory = self._agent_factories[agent_id.type]
|
||||
agent = await self._invoke_agent_factory(agent_factory, agent_id)
|
||||
self._instantiated_agents[agent_id] = agent
|
||||
return agent
|
||||
|
||||
# TODO: uncomment out the following type ignore when this is fixed in mypy: https://github.com/python/mypy/issues/3737
|
||||
async def try_get_underlying_agent_instance(self, id: AgentId, type: Type[T] = Agent) -> T: # type: ignore[assignment]
|
||||
if id.type not in self._agent_factories:
|
||||
raise LookupError(f"Agent with name {id.type} not found.")
|
||||
|
||||
# TODO: check if remote
|
||||
agent_instance = await self._get_agent(id)
|
||||
|
||||
if not isinstance(agent_instance, type):
|
||||
raise TypeError(f"Agent with name {id.type} is not of type {type.__name__}")
|
||||
|
||||
return agent_instance
|
||||
|
||||
async def add_subscription(self, subscription: Subscription) -> None:
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
|
||||
message = agent_worker_pb2.AddSubscriptionRequest(subscription=subscription_to_proto(subscription))
|
||||
_response: agent_worker_pb2.AddSubscriptionResponse = await self._host_connection.stub.AddSubscription(
|
||||
message, metadata=self._host_connection.metadata
|
||||
)
|
||||
|
||||
# Add to local subscription manager.
|
||||
await self._subscription_manager.add_subscription(subscription)
|
||||
|
||||
async def remove_subscription(self, id: str) -> None:
|
||||
if self._host_connection is None:
|
||||
raise RuntimeError("Host connection is not set.")
|
||||
|
||||
message = agent_worker_pb2.RemoveSubscriptionRequest(id=id)
|
||||
_response: agent_worker_pb2.RemoveSubscriptionResponse = await self._host_connection.stub.RemoveSubscription(
|
||||
message, metadata=self._host_connection.metadata
|
||||
)
|
||||
|
||||
await self._subscription_manager.remove_subscription(id)
|
||||
|
||||
async def get(
|
||||
self, id_or_type: AgentId | AgentType | str, /, key: str = "default", *, lazy: bool = True
|
||||
) -> AgentId:
|
||||
return await get_impl(
|
||||
id_or_type=id_or_type,
|
||||
key=key,
|
||||
lazy=lazy,
|
||||
instance_getter=self._get_agent,
|
||||
)
|
||||
|
||||
def add_message_serializer(self, serializer: MessageSerializer[Any] | Sequence[MessageSerializer[Any]]) -> None:
|
||||
self._serialization_registry.add_serializer(serializer)
|
||||
@@ -0,0 +1,73 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import signal
|
||||
from typing import Optional, Sequence
|
||||
|
||||
from ._constants import GRPC_IMPORT_ERROR_STR
|
||||
from ._type_helpers import ChannelArgumentType
|
||||
from ._worker_runtime_host_servicer import GrpcWorkerAgentRuntimeHostServicer
|
||||
|
||||
try:
|
||||
import grpc
|
||||
except ImportError as e:
|
||||
raise ImportError(GRPC_IMPORT_ERROR_STR) from e
|
||||
from .protos import agent_worker_pb2_grpc
|
||||
|
||||
logger = logging.getLogger("agentdhal_core")
|
||||
|
||||
|
||||
class GrpcWorkerAgentRuntimeHost:
|
||||
def __init__(self, address: str, extra_grpc_config: Optional[ChannelArgumentType] = None) -> None:
|
||||
self._server = grpc.aio.server(options=extra_grpc_config)
|
||||
self._servicer = GrpcWorkerAgentRuntimeHostServicer()
|
||||
agent_worker_pb2_grpc.add_AgentRpcServicer_to_server(self._servicer, self._server)
|
||||
self._server.add_insecure_port(address)
|
||||
self._address = address
|
||||
self._serve_task: asyncio.Task[None] | None = None
|
||||
|
||||
async def _serve(self) -> None:
|
||||
await self._server.start()
|
||||
logger.info(f"Server started at {self._address}.")
|
||||
await self._server.wait_for_termination()
|
||||
|
||||
def start(self) -> None:
|
||||
"""Start the server in a background task."""
|
||||
if self._serve_task is not None:
|
||||
raise RuntimeError("Host runtime is already started.")
|
||||
self._serve_task = asyncio.create_task(self._serve())
|
||||
|
||||
async def stop(self, grace: int = 5) -> None:
|
||||
"""Stop the server."""
|
||||
if self._serve_task is None:
|
||||
raise RuntimeError("Host runtime is not started.")
|
||||
await self._server.stop(grace=grace)
|
||||
self._serve_task.cancel()
|
||||
try:
|
||||
await self._serve_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
logger.info("Server stopped.")
|
||||
self._serve_task = None
|
||||
|
||||
async def stop_when_signal(
|
||||
self, grace: int = 5, signals: Sequence[signal.Signals] = (signal.SIGTERM, signal.SIGINT)
|
||||
) -> None:
|
||||
"""Stop the server when a signal is received."""
|
||||
if self._serve_task is None:
|
||||
raise RuntimeError("Host runtime is not started.")
|
||||
# Set up signal handling for graceful shutdown.
|
||||
loop = asyncio.get_running_loop()
|
||||
shutdown_event = asyncio.Event()
|
||||
|
||||
def signal_handler() -> None:
|
||||
logger.info("Received exit signal, shutting down gracefully...")
|
||||
shutdown_event.set()
|
||||
|
||||
for sig in signals:
|
||||
loop.add_signal_handler(sig, signal_handler)
|
||||
|
||||
# Wait for the signal to trigger the shutdown event.
|
||||
await shutdown_event.wait()
|
||||
|
||||
# Shutdown the server.
|
||||
await self.stop(grace=grace)
|
||||
@@ -0,0 +1,364 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from asyncio import Future, Task
|
||||
from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Generic, Sequence, Set, Tuple, TypeVar
|
||||
|
||||
from agentdhal_core import TopicId
|
||||
from agentdhal_core._agent_id import AgentId
|
||||
from agentdhal_core._runtime_impl_helpers import SubscriptionManager
|
||||
|
||||
from ._constants import GRPC_IMPORT_ERROR_STR
|
||||
from ._utils import subscription_from_proto, subscription_to_proto
|
||||
|
||||
try:
|
||||
import grpc
|
||||
except ImportError as e:
|
||||
raise ImportError(GRPC_IMPORT_ERROR_STR) from e
|
||||
|
||||
from .protos import agent_worker_pb2, agent_worker_pb2_grpc, cloudevent_pb2
|
||||
|
||||
logger = logging.getLogger("agentdhal_core")
|
||||
event_logger = logging.getLogger("agentdhal_core.events")
|
||||
|
||||
ClientConnectionId = str
|
||||
|
||||
|
||||
def metadata_to_dict(metadata: Sequence[Tuple[str, str]] | None) -> Dict[str, str]:
|
||||
if metadata is None:
|
||||
return {}
|
||||
return {key: value for key, value in metadata}
|
||||
|
||||
|
||||
async def get_client_id_or_abort(context: grpc.aio.ServicerContext[Any, Any]) -> str: # type: ignore
|
||||
# The type hint on context.invocation_metadata() is incorrect.
|
||||
metadata = metadata_to_dict(context.invocation_metadata()) # type: ignore
|
||||
if (client_id := metadata.get("client-id")) is None:
|
||||
await context.abort(grpc.StatusCode.INVALID_ARGUMENT, "client-id metadata not found.")
|
||||
|
||||
return client_id # type: ignore
|
||||
|
||||
|
||||
SendT = TypeVar("SendT")
|
||||
ReceiveT = TypeVar("ReceiveT")
|
||||
|
||||
|
||||
class ChannelConnection(ABC, Generic[SendT, ReceiveT]):
|
||||
def __init__(self, request_iterator: AsyncIterator[ReceiveT], client_id: str) -> None:
|
||||
self._request_iterator = request_iterator
|
||||
self._client_id = client_id
|
||||
self._send_queue: asyncio.Queue[SendT] = asyncio.Queue()
|
||||
self._receiving_task = asyncio.create_task(self._receive_messages(client_id, request_iterator))
|
||||
|
||||
async def _receive_messages(self, client_id: ClientConnectionId, request_iterator: AsyncIterator[ReceiveT]) -> None:
|
||||
# Receive messages from the client and process them.
|
||||
async for message in request_iterator:
|
||||
logger.info(f"Received message from client {client_id}: {message}")
|
||||
await self._handle_message(message)
|
||||
|
||||
def __aiter__(self) -> AsyncIterator[SendT]:
|
||||
return self
|
||||
|
||||
async def __anext__(self) -> SendT:
|
||||
try:
|
||||
return await self._send_queue.get()
|
||||
except StopAsyncIteration:
|
||||
await self._receiving_task
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get message from send queue: {e}", exc_info=True)
|
||||
await self._receiving_task
|
||||
raise
|
||||
|
||||
@abstractmethod
|
||||
async def _handle_message(self, message: ReceiveT) -> None:
|
||||
pass
|
||||
|
||||
async def send(self, message: SendT) -> None:
|
||||
await self._send_queue.put(message)
|
||||
|
||||
|
||||
class CallbackChannelConnection(ChannelConnection[SendT, ReceiveT]):
|
||||
def __init__(
|
||||
self,
|
||||
request_iterator: AsyncIterator[ReceiveT],
|
||||
client_id: str,
|
||||
handle_callback: Callable[[ReceiveT], Awaitable[None]],
|
||||
) -> None:
|
||||
self._handle_callback = handle_callback
|
||||
super().__init__(request_iterator, client_id)
|
||||
|
||||
async def _handle_message(self, message: ReceiveT) -> None:
|
||||
await self._handle_callback(message)
|
||||
|
||||
|
||||
class GrpcWorkerAgentRuntimeHostServicer(agent_worker_pb2_grpc.AgentRpcServicer):
|
||||
"""A gRPC servicer that hosts message delivery service for agents."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._data_connections: Dict[
|
||||
ClientConnectionId, ChannelConnection[agent_worker_pb2.Message, agent_worker_pb2.Message]
|
||||
] = {}
|
||||
self._control_connections: Dict[
|
||||
ClientConnectionId, ChannelConnection[agent_worker_pb2.ControlMessage, agent_worker_pb2.ControlMessage]
|
||||
] = {}
|
||||
self._agent_type_to_client_id_lock = asyncio.Lock()
|
||||
self._agent_type_to_client_id: Dict[str, ClientConnectionId] = {}
|
||||
self._pending_responses: Dict[ClientConnectionId, Dict[str, Future[Any]]] = {}
|
||||
self._background_tasks: Set[Task[Any]] = set()
|
||||
self._subscription_manager = SubscriptionManager()
|
||||
self._client_id_to_subscription_id_mapping: Dict[ClientConnectionId, set[str]] = {}
|
||||
|
||||
async def OpenChannel( # type: ignore
|
||||
self,
|
||||
request_iterator: AsyncIterator[agent_worker_pb2.Message],
|
||||
context: grpc.aio.ServicerContext[agent_worker_pb2.Message, agent_worker_pb2.Message],
|
||||
) -> AsyncIterator[agent_worker_pb2.Message]:
|
||||
client_id = await get_client_id_or_abort(context)
|
||||
|
||||
async def handle_callback(message: agent_worker_pb2.Message) -> None:
|
||||
await self._receive_message(client_id, message)
|
||||
|
||||
connection = CallbackChannelConnection[agent_worker_pb2.Message, agent_worker_pb2.Message](
|
||||
request_iterator, client_id, handle_callback=handle_callback
|
||||
)
|
||||
self._data_connections[client_id] = connection
|
||||
logger.info(f"Client {client_id} connected.")
|
||||
|
||||
try:
|
||||
async for message in connection:
|
||||
yield message
|
||||
finally:
|
||||
# Clean up the client connection.
|
||||
del self._data_connections[client_id]
|
||||
# Cancel pending requests sent to this client.
|
||||
for future in self._pending_responses.pop(client_id, {}).values():
|
||||
future.cancel()
|
||||
# Remove the client id from the agent type to client id mapping.
|
||||
await self._on_client_disconnect(client_id)
|
||||
|
||||
async def OpenControlChannel( # type: ignore
|
||||
self,
|
||||
request_iterator: AsyncIterator[agent_worker_pb2.ControlMessage],
|
||||
context: grpc.aio.ServicerContext[agent_worker_pb2.ControlMessage, agent_worker_pb2.ControlMessage],
|
||||
) -> AsyncIterator[agent_worker_pb2.ControlMessage]:
|
||||
client_id = await get_client_id_or_abort(context)
|
||||
|
||||
async def handle_callback(message: agent_worker_pb2.ControlMessage) -> None:
|
||||
await self._receive_control_message(client_id, message)
|
||||
|
||||
connection = CallbackChannelConnection[agent_worker_pb2.ControlMessage, agent_worker_pb2.ControlMessage](
|
||||
request_iterator, client_id, handle_callback=handle_callback
|
||||
)
|
||||
self._control_connections[client_id] = connection
|
||||
logger.info(f"Client {client_id} connected.")
|
||||
|
||||
try:
|
||||
async for message in connection:
|
||||
yield message
|
||||
finally:
|
||||
# Clean up the client connection.
|
||||
del self._control_connections[client_id]
|
||||
|
||||
async def _on_client_disconnect(self, client_id: ClientConnectionId) -> None:
|
||||
async with self._agent_type_to_client_id_lock:
|
||||
agent_types = [agent_type for agent_type, id_ in self._agent_type_to_client_id.items() if id_ == client_id]
|
||||
for agent_type in agent_types:
|
||||
logger.info(f"Removing agent type {agent_type} from agent type to client id mapping")
|
||||
del self._agent_type_to_client_id[agent_type]
|
||||
for sub_id in self._client_id_to_subscription_id_mapping.get(client_id, set()):
|
||||
logger.info(f"Client id {client_id} disconnected. Removing corresponding subscription with id {id}")
|
||||
try:
|
||||
await self._subscription_manager.remove_subscription(sub_id)
|
||||
# Catch and ignore if the subscription does not exist.
|
||||
except ValueError:
|
||||
continue
|
||||
logger.info(f"Client {client_id} disconnected successfully")
|
||||
|
||||
def _raise_on_exception(self, task: Task[Any]) -> None:
|
||||
exception = task.exception()
|
||||
if exception is not None:
|
||||
raise exception
|
||||
|
||||
async def _receive_message(self, client_id: ClientConnectionId, message: agent_worker_pb2.Message) -> None:
|
||||
logger.info(f"Received message from client {client_id}: {message}")
|
||||
oneofcase = message.WhichOneof("message")
|
||||
match oneofcase:
|
||||
case "request":
|
||||
request: agent_worker_pb2.RpcRequest = message.request
|
||||
task = asyncio.create_task(self._process_request(request, client_id))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case "response":
|
||||
response: agent_worker_pb2.RpcResponse = message.response
|
||||
task = asyncio.create_task(self._process_response(response, client_id))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case "cloudEvent":
|
||||
task = asyncio.create_task(self._process_event(message.cloudEvent))
|
||||
self._background_tasks.add(task)
|
||||
task.add_done_callback(self._raise_on_exception)
|
||||
task.add_done_callback(self._background_tasks.discard)
|
||||
case None:
|
||||
logger.warning("Received empty message")
|
||||
|
||||
async def _receive_control_message(
|
||||
self, client_id: ClientConnectionId, message: agent_worker_pb2.ControlMessage
|
||||
) -> None:
|
||||
logger.info(f"Received message from client {client_id}: {message}")
|
||||
destination = message.destination
|
||||
if destination.startswith("agentid="):
|
||||
agent_id = AgentId.from_str(destination[len("agentid=") :])
|
||||
target_client_id = self._agent_type_to_client_id.get(agent_id.type)
|
||||
if target_client_id is None:
|
||||
logger.error(f"Agent client id not found for agent type {agent_id.type}.")
|
||||
return
|
||||
elif destination.startswith("clientid="):
|
||||
target_client_id = destination[len("clientid=") :]
|
||||
else:
|
||||
logger.error(f"Invalid destination {destination}")
|
||||
return
|
||||
|
||||
target_send_queue = self._control_connections.get(target_client_id)
|
||||
if target_send_queue is None:
|
||||
logger.error(f"Client {target_client_id} not found, failed to deliver message.")
|
||||
return
|
||||
await target_send_queue.send(message)
|
||||
|
||||
async def _process_request(self, request: agent_worker_pb2.RpcRequest, client_id: ClientConnectionId) -> None:
|
||||
# Deliver the message to a client given the target agent type.
|
||||
async with self._agent_type_to_client_id_lock:
|
||||
target_client_id = self._agent_type_to_client_id.get(request.target.type)
|
||||
if target_client_id is None:
|
||||
logger.error(f"Agent {request.target.type} not found, failed to deliver message.")
|
||||
return
|
||||
target_send_queue = self._data_connections.get(target_client_id)
|
||||
if target_send_queue is None:
|
||||
logger.error(f"Client {target_client_id} not found, failed to deliver message.")
|
||||
return
|
||||
await target_send_queue.send(agent_worker_pb2.Message(request=request))
|
||||
|
||||
# Create a future to wait for the response from the target.
|
||||
future = asyncio.get_event_loop().create_future()
|
||||
self._pending_responses.setdefault(target_client_id, {})[request.request_id] = future
|
||||
|
||||
# Create a task to wait for the response and send it back to the client.
|
||||
send_response_task = asyncio.create_task(self._wait_and_send_response(future, client_id))
|
||||
self._background_tasks.add(send_response_task)
|
||||
send_response_task.add_done_callback(self._raise_on_exception)
|
||||
send_response_task.add_done_callback(self._background_tasks.discard)
|
||||
|
||||
async def _wait_and_send_response(
|
||||
self, future: Future[agent_worker_pb2.RpcResponse], client_id: ClientConnectionId
|
||||
) -> None:
|
||||
response = await future
|
||||
message = agent_worker_pb2.Message(response=response)
|
||||
send_queue = self._data_connections.get(client_id)
|
||||
if send_queue is None:
|
||||
logger.error(f"Client {client_id} not found, failed to send response message.")
|
||||
return
|
||||
await send_queue.send(message)
|
||||
|
||||
async def _process_response(self, response: agent_worker_pb2.RpcResponse, client_id: ClientConnectionId) -> None:
|
||||
# Setting the result of the future will send the response back to the original sender.
|
||||
future = self._pending_responses[client_id].pop(response.request_id)
|
||||
future.set_result(response)
|
||||
|
||||
async def _process_event(self, event: cloudevent_pb2.CloudEvent) -> None:
|
||||
topic_id = TopicId(type=event.type, source=event.source)
|
||||
recipients = await self._subscription_manager.get_subscribed_recipients(topic_id)
|
||||
# Get the client ids of the recipients.
|
||||
async with self._agent_type_to_client_id_lock:
|
||||
client_ids: Set[ClientConnectionId] = set()
|
||||
for recipient in recipients:
|
||||
client_id = self._agent_type_to_client_id.get(recipient.type)
|
||||
if client_id is not None:
|
||||
client_ids.add(client_id)
|
||||
else:
|
||||
logger.error(f"Agent {recipient.type} and its client not found for topic {topic_id}.")
|
||||
# Deliver the event to clients.
|
||||
for client_id in client_ids:
|
||||
await self._data_connections[client_id].send(agent_worker_pb2.Message(cloudEvent=event))
|
||||
|
||||
async def RegisterAgent( # type: ignore
|
||||
self,
|
||||
request: agent_worker_pb2.RegisterAgentTypeRequest,
|
||||
context: grpc.aio.ServicerContext[
|
||||
agent_worker_pb2.RegisterAgentTypeRequest, agent_worker_pb2.RegisterAgentTypeResponse
|
||||
],
|
||||
) -> agent_worker_pb2.RegisterAgentTypeResponse:
|
||||
client_id = await get_client_id_or_abort(context)
|
||||
|
||||
async with self._agent_type_to_client_id_lock:
|
||||
if request.type in self._agent_type_to_client_id:
|
||||
existing_client_id = self._agent_type_to_client_id[request.type]
|
||||
await context.abort(
|
||||
grpc.StatusCode.INVALID_ARGUMENT,
|
||||
f"Agent type {request.type} already registered with client {existing_client_id}.",
|
||||
)
|
||||
else:
|
||||
self._agent_type_to_client_id[request.type] = client_id
|
||||
|
||||
return agent_worker_pb2.RegisterAgentTypeResponse()
|
||||
|
||||
async def AddSubscription( # type: ignore
|
||||
self,
|
||||
request: agent_worker_pb2.AddSubscriptionRequest,
|
||||
context: grpc.aio.ServicerContext[
|
||||
agent_worker_pb2.AddSubscriptionRequest, agent_worker_pb2.AddSubscriptionResponse
|
||||
],
|
||||
) -> agent_worker_pb2.AddSubscriptionResponse:
|
||||
client_id = await get_client_id_or_abort(context)
|
||||
|
||||
subscription = subscription_from_proto(request.subscription)
|
||||
try:
|
||||
await self._subscription_manager.add_subscription(subscription)
|
||||
subscription_ids = self._client_id_to_subscription_id_mapping.setdefault(client_id, set())
|
||||
subscription_ids.add(subscription.id)
|
||||
except ValueError as e:
|
||||
await context.abort(grpc.StatusCode.INVALID_ARGUMENT, str(e))
|
||||
return agent_worker_pb2.AddSubscriptionResponse()
|
||||
|
||||
async def RemoveSubscription( # type: ignore
|
||||
self,
|
||||
request: agent_worker_pb2.RemoveSubscriptionRequest,
|
||||
context: grpc.aio.ServicerContext[
|
||||
agent_worker_pb2.RemoveSubscriptionRequest, agent_worker_pb2.RemoveSubscriptionResponse
|
||||
],
|
||||
) -> agent_worker_pb2.RemoveSubscriptionResponse:
|
||||
_client_id = await get_client_id_or_abort(context)
|
||||
await self._subscription_manager.remove_subscription(request.id)
|
||||
return agent_worker_pb2.RemoveSubscriptionResponse()
|
||||
|
||||
async def GetSubscriptions( # type: ignore
|
||||
self,
|
||||
request: agent_worker_pb2.GetSubscriptionsRequest,
|
||||
context: grpc.aio.ServicerContext[
|
||||
agent_worker_pb2.GetSubscriptionsRequest, agent_worker_pb2.GetSubscriptionsResponse
|
||||
],
|
||||
) -> agent_worker_pb2.GetSubscriptionsResponse:
|
||||
_client_id = await get_client_id_or_abort(context)
|
||||
subscriptions = self._subscription_manager.subscriptions
|
||||
return agent_worker_pb2.GetSubscriptionsResponse(
|
||||
subscriptions=[subscription_to_proto(sub) for sub in subscriptions]
|
||||
)
|
||||
|
||||
# async def GetState( # type: ignore
|
||||
# self,
|
||||
# request: agent_worker_pb2.AgentId,
|
||||
# context: grpc.aio.ServicerContext[agent_worker_pb2.AgentId, agent_worker_pb2.GetStateResponse],
|
||||
# ) -> agent_worker_pb2.GetStateResponse:
|
||||
# _client_id = await get_client_id_or_abort(context)
|
||||
# raise NotImplementedError("Method not implemented!")
|
||||
|
||||
# async def SaveState( # type: ignore
|
||||
# self,
|
||||
# request: agent_worker_pb2.AgentState,
|
||||
# context: grpc.aio.ServicerContext[agent_worker_pb2.AgentId, agent_worker_pb2.SaveStateResponse],
|
||||
# ) -> agent_worker_pb2.SaveStateResponse:
|
||||
# _client_id = await get_client_id_or_abort(context)
|
||||
# raise NotImplementedError("Method not implemented!")
|
||||
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
The :mod:`agentdhal_extensions.runtimes.grpc.protos` module provides Google Protobuf classes for agent-worker communication
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# NO CHECKED-IN PROTOBUF GENCODE
|
||||
# source: agent_worker.proto
|
||||
# Protobuf Python Version: 5.29.0
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import runtime_version as _runtime_version
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
_runtime_version.ValidateProtobufRuntimeVersion(
|
||||
_runtime_version.Domain.PUBLIC,
|
||||
5,
|
||||
29,
|
||||
0,
|
||||
'',
|
||||
'agent_worker.proto'
|
||||
)
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from . import cloudevent_pb2 as cloudevent__pb2
|
||||
from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x61gent_worker.proto\x12\x06\x61gents\x1a\x10\x63loudevent.proto\x1a\x19google/protobuf/any.proto\"$\n\x07\x41gentId\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\"E\n\x07Payload\x12\x11\n\tdata_type\x18\x01 \x01(\t\x12\x19\n\x11\x64\x61ta_content_type\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\"\x89\x02\n\nRpcRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12$\n\x06source\x18\x02 \x01(\x0b\x32\x0f.agents.AgentIdH\x00\x88\x01\x01\x12\x1f\n\x06target\x18\x03 \x01(\x0b\x32\x0f.agents.AgentId\x12\x0e\n\x06method\x18\x04 \x01(\t\x12 \n\x07payload\x18\x05 \x01(\x0b\x32\x0f.agents.Payload\x12\x32\n\x08metadata\x18\x06 \x03(\x0b\x32 .agents.RpcRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07_source\"\xb8\x01\n\x0bRpcResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12 \n\x07payload\x18\x02 \x01(\x0b\x32\x0f.agents.Payload\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12\x33\n\x08metadata\x18\x04 \x03(\x0b\x32!.agents.RpcResponse.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"(\n\x18RegisterAgentTypeRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\"\x1b\n\x19RegisterAgentTypeResponse\":\n\x10TypeSubscription\x12\x12\n\ntopic_type\x18\x01 \x01(\t\x12\x12\n\nagent_type\x18\x02 \x01(\t\"G\n\x16TypePrefixSubscription\x12\x19\n\x11topic_type_prefix\x18\x01 \x01(\t\x12\x12\n\nagent_type\x18\x02 \x01(\t\"\xa2\x01\n\x0cSubscription\x12\n\n\x02id\x18\x01 \x01(\t\x12\x34\n\x10typeSubscription\x18\x02 \x01(\x0b\x32\x18.agents.TypeSubscriptionH\x00\x12@\n\x16typePrefixSubscription\x18\x03 \x01(\x0b\x32\x1e.agents.TypePrefixSubscriptionH\x00\x42\x0e\n\x0csubscription\"D\n\x16\x41\x64\x64SubscriptionRequest\x12*\n\x0csubscription\x18\x01 \x01(\x0b\x32\x14.agents.Subscription\"\x19\n\x17\x41\x64\x64SubscriptionResponse\"\'\n\x19RemoveSubscriptionRequest\x12\n\n\x02id\x18\x01 \x01(\t\"\x1c\n\x1aRemoveSubscriptionResponse\"\x19\n\x17GetSubscriptionsRequest\"G\n\x18GetSubscriptionsResponse\x12+\n\rsubscriptions\x18\x01 \x03(\x0b\x32\x14.agents.Subscription\"\x99\x01\n\x07Message\x12%\n\x07request\x18\x01 \x01(\x0b\x32\x12.agents.RpcRequestH\x00\x12\'\n\x08response\x18\x02 \x01(\x0b\x32\x13.agents.RpcResponseH\x00\x12\x33\n\ncloudEvent\x18\x03 \x01(\x0b\x32\x1d.io.cloudevents.v1.CloudEventH\x00\x42\t\n\x07message\"4\n\x10SaveStateRequest\x12 \n\x07\x61gentId\x18\x01 \x01(\x0b\x32\x0f.agents.AgentId\"@\n\x11SaveStateResponse\x12\r\n\x05state\x18\x01 \x01(\t\x12\x12\n\x05\x65rror\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"C\n\x10LoadStateRequest\x12 \n\x07\x61gentId\x18\x01 \x01(\x0b\x32\x0f.agents.AgentId\x12\r\n\x05state\x18\x02 \x01(\t\"1\n\x11LoadStateResponse\x12\x12\n\x05\x65rror\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"\x87\x01\n\x0e\x43ontrolMessage\x12\x0e\n\x06rpc_id\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65stination\x18\x02 \x01(\t\x12\x17\n\nrespond_to\x18\x03 \x01(\tH\x00\x88\x01\x01\x12(\n\nrpcMessage\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyB\r\n\x0b_respond_to2\xe7\x03\n\x08\x41gentRpc\x12\x33\n\x0bOpenChannel\x12\x0f.agents.Message\x1a\x0f.agents.Message(\x01\x30\x01\x12H\n\x12OpenControlChannel\x12\x16.agents.ControlMessage\x1a\x16.agents.ControlMessage(\x01\x30\x01\x12T\n\rRegisterAgent\x12 .agents.RegisterAgentTypeRequest\x1a!.agents.RegisterAgentTypeResponse\x12R\n\x0f\x41\x64\x64Subscription\x12\x1e.agents.AddSubscriptionRequest\x1a\x1f.agents.AddSubscriptionResponse\x12[\n\x12RemoveSubscription\x12!.agents.RemoveSubscriptionRequest\x1a\".agents.RemoveSubscriptionResponse\x12U\n\x10GetSubscriptions\x12\x1f.agents.GetSubscriptionsRequest\x1a .agents.GetSubscriptionsResponseB\x1d\xaa\x02\x1aMicrosoft.AutoGen.Protobufb\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'agent_worker_pb2', _globals)
|
||||
if not _descriptor._USE_C_DESCRIPTORS:
|
||||
_globals['DESCRIPTOR']._loaded_options = None
|
||||
_globals['DESCRIPTOR']._serialized_options = b'\252\002\032Microsoft.AutoGen.Protobuf'
|
||||
_globals['_RPCREQUEST_METADATAENTRY']._loaded_options = None
|
||||
_globals['_RPCREQUEST_METADATAENTRY']._serialized_options = b'8\001'
|
||||
_globals['_RPCRESPONSE_METADATAENTRY']._loaded_options = None
|
||||
_globals['_RPCRESPONSE_METADATAENTRY']._serialized_options = b'8\001'
|
||||
_globals['_AGENTID']._serialized_start=75
|
||||
_globals['_AGENTID']._serialized_end=111
|
||||
_globals['_PAYLOAD']._serialized_start=113
|
||||
_globals['_PAYLOAD']._serialized_end=182
|
||||
_globals['_RPCREQUEST']._serialized_start=185
|
||||
_globals['_RPCREQUEST']._serialized_end=450
|
||||
_globals['_RPCREQUEST_METADATAENTRY']._serialized_start=392
|
||||
_globals['_RPCREQUEST_METADATAENTRY']._serialized_end=439
|
||||
_globals['_RPCRESPONSE']._serialized_start=453
|
||||
_globals['_RPCRESPONSE']._serialized_end=637
|
||||
_globals['_RPCRESPONSE_METADATAENTRY']._serialized_start=392
|
||||
_globals['_RPCRESPONSE_METADATAENTRY']._serialized_end=439
|
||||
_globals['_REGISTERAGENTTYPEREQUEST']._serialized_start=639
|
||||
_globals['_REGISTERAGENTTYPEREQUEST']._serialized_end=679
|
||||
_globals['_REGISTERAGENTTYPERESPONSE']._serialized_start=681
|
||||
_globals['_REGISTERAGENTTYPERESPONSE']._serialized_end=708
|
||||
_globals['_TYPESUBSCRIPTION']._serialized_start=710
|
||||
_globals['_TYPESUBSCRIPTION']._serialized_end=768
|
||||
_globals['_TYPEPREFIXSUBSCRIPTION']._serialized_start=770
|
||||
_globals['_TYPEPREFIXSUBSCRIPTION']._serialized_end=841
|
||||
_globals['_SUBSCRIPTION']._serialized_start=844
|
||||
_globals['_SUBSCRIPTION']._serialized_end=1006
|
||||
_globals['_ADDSUBSCRIPTIONREQUEST']._serialized_start=1008
|
||||
_globals['_ADDSUBSCRIPTIONREQUEST']._serialized_end=1076
|
||||
_globals['_ADDSUBSCRIPTIONRESPONSE']._serialized_start=1078
|
||||
_globals['_ADDSUBSCRIPTIONRESPONSE']._serialized_end=1103
|
||||
_globals['_REMOVESUBSCRIPTIONREQUEST']._serialized_start=1105
|
||||
_globals['_REMOVESUBSCRIPTIONREQUEST']._serialized_end=1144
|
||||
_globals['_REMOVESUBSCRIPTIONRESPONSE']._serialized_start=1146
|
||||
_globals['_REMOVESUBSCRIPTIONRESPONSE']._serialized_end=1174
|
||||
_globals['_GETSUBSCRIPTIONSREQUEST']._serialized_start=1176
|
||||
_globals['_GETSUBSCRIPTIONSREQUEST']._serialized_end=1201
|
||||
_globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_start=1203
|
||||
_globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_end=1274
|
||||
_globals['_MESSAGE']._serialized_start=1277
|
||||
_globals['_MESSAGE']._serialized_end=1430
|
||||
_globals['_SAVESTATEREQUEST']._serialized_start=1432
|
||||
_globals['_SAVESTATEREQUEST']._serialized_end=1484
|
||||
_globals['_SAVESTATERESPONSE']._serialized_start=1486
|
||||
_globals['_SAVESTATERESPONSE']._serialized_end=1550
|
||||
_globals['_LOADSTATEREQUEST']._serialized_start=1552
|
||||
_globals['_LOADSTATEREQUEST']._serialized_end=1619
|
||||
_globals['_LOADSTATERESPONSE']._serialized_start=1621
|
||||
_globals['_LOADSTATERESPONSE']._serialized_end=1670
|
||||
_globals['_CONTROLMESSAGE']._serialized_start=1673
|
||||
_globals['_CONTROLMESSAGE']._serialized_end=1808
|
||||
_globals['_AGENTRPC']._serialized_start=1811
|
||||
_globals['_AGENTRPC']._serialized_end=2298
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
@@ -0,0 +1,457 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
"""
|
||||
|
||||
import builtins
|
||||
from . import cloudevent_pb2
|
||||
import collections.abc
|
||||
import google.protobuf.any_pb2
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.containers
|
||||
import google.protobuf.message
|
||||
import typing
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
@typing.final
|
||||
class AgentId(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
TYPE_FIELD_NUMBER: builtins.int
|
||||
KEY_FIELD_NUMBER: builtins.int
|
||||
type: builtins.str
|
||||
key: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
type: builtins.str = ...,
|
||||
key: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["key", b"key", "type", b"type"]) -> None: ...
|
||||
|
||||
global___AgentId = AgentId
|
||||
|
||||
@typing.final
|
||||
class Payload(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
DATA_TYPE_FIELD_NUMBER: builtins.int
|
||||
DATA_CONTENT_TYPE_FIELD_NUMBER: builtins.int
|
||||
DATA_FIELD_NUMBER: builtins.int
|
||||
data_type: builtins.str
|
||||
data_content_type: builtins.str
|
||||
data: builtins.bytes
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
data_type: builtins.str = ...,
|
||||
data_content_type: builtins.str = ...,
|
||||
data: builtins.bytes = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["data", b"data", "data_content_type", b"data_content_type", "data_type", b"data_type"]) -> None: ...
|
||||
|
||||
global___Payload = Payload
|
||||
|
||||
@typing.final
|
||||
class RpcRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
@typing.final
|
||||
class MetadataEntry(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
KEY_FIELD_NUMBER: builtins.int
|
||||
VALUE_FIELD_NUMBER: builtins.int
|
||||
key: builtins.str
|
||||
value: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
key: builtins.str = ...,
|
||||
value: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ...
|
||||
|
||||
REQUEST_ID_FIELD_NUMBER: builtins.int
|
||||
SOURCE_FIELD_NUMBER: builtins.int
|
||||
TARGET_FIELD_NUMBER: builtins.int
|
||||
METHOD_FIELD_NUMBER: builtins.int
|
||||
PAYLOAD_FIELD_NUMBER: builtins.int
|
||||
METADATA_FIELD_NUMBER: builtins.int
|
||||
request_id: builtins.str
|
||||
method: builtins.str
|
||||
@property
|
||||
def source(self) -> global___AgentId: ...
|
||||
@property
|
||||
def target(self) -> global___AgentId: ...
|
||||
@property
|
||||
def payload(self) -> global___Payload: ...
|
||||
@property
|
||||
def metadata(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
request_id: builtins.str = ...,
|
||||
source: global___AgentId | None = ...,
|
||||
target: global___AgentId | None = ...,
|
||||
method: builtins.str = ...,
|
||||
payload: global___Payload | None = ...,
|
||||
metadata: collections.abc.Mapping[builtins.str, builtins.str] | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_source", b"_source", "payload", b"payload", "source", b"source", "target", b"target"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_source", b"_source", "metadata", b"metadata", "method", b"method", "payload", b"payload", "request_id", b"request_id", "source", b"source", "target", b"target"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_source", b"_source"]) -> typing.Literal["source"] | None: ...
|
||||
|
||||
global___RpcRequest = RpcRequest
|
||||
|
||||
@typing.final
|
||||
class RpcResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
@typing.final
|
||||
class MetadataEntry(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
KEY_FIELD_NUMBER: builtins.int
|
||||
VALUE_FIELD_NUMBER: builtins.int
|
||||
key: builtins.str
|
||||
value: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
key: builtins.str = ...,
|
||||
value: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ...
|
||||
|
||||
REQUEST_ID_FIELD_NUMBER: builtins.int
|
||||
PAYLOAD_FIELD_NUMBER: builtins.int
|
||||
ERROR_FIELD_NUMBER: builtins.int
|
||||
METADATA_FIELD_NUMBER: builtins.int
|
||||
request_id: builtins.str
|
||||
error: builtins.str
|
||||
@property
|
||||
def payload(self) -> global___Payload: ...
|
||||
@property
|
||||
def metadata(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
request_id: builtins.str = ...,
|
||||
payload: global___Payload | None = ...,
|
||||
error: builtins.str = ...,
|
||||
metadata: collections.abc.Mapping[builtins.str, builtins.str] | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["payload", b"payload"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["error", b"error", "metadata", b"metadata", "payload", b"payload", "request_id", b"request_id"]) -> None: ...
|
||||
|
||||
global___RpcResponse = RpcResponse
|
||||
|
||||
@typing.final
|
||||
class RegisterAgentTypeRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
TYPE_FIELD_NUMBER: builtins.int
|
||||
type: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
type: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["type", b"type"]) -> None: ...
|
||||
|
||||
global___RegisterAgentTypeRequest = RegisterAgentTypeRequest
|
||||
|
||||
@typing.final
|
||||
class RegisterAgentTypeResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
global___RegisterAgentTypeResponse = RegisterAgentTypeResponse
|
||||
|
||||
@typing.final
|
||||
class TypeSubscription(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
TOPIC_TYPE_FIELD_NUMBER: builtins.int
|
||||
AGENT_TYPE_FIELD_NUMBER: builtins.int
|
||||
topic_type: builtins.str
|
||||
agent_type: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
topic_type: builtins.str = ...,
|
||||
agent_type: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["agent_type", b"agent_type", "topic_type", b"topic_type"]) -> None: ...
|
||||
|
||||
global___TypeSubscription = TypeSubscription
|
||||
|
||||
@typing.final
|
||||
class TypePrefixSubscription(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
TOPIC_TYPE_PREFIX_FIELD_NUMBER: builtins.int
|
||||
AGENT_TYPE_FIELD_NUMBER: builtins.int
|
||||
topic_type_prefix: builtins.str
|
||||
agent_type: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
topic_type_prefix: builtins.str = ...,
|
||||
agent_type: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["agent_type", b"agent_type", "topic_type_prefix", b"topic_type_prefix"]) -> None: ...
|
||||
|
||||
global___TypePrefixSubscription = TypePrefixSubscription
|
||||
|
||||
@typing.final
|
||||
class Subscription(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
ID_FIELD_NUMBER: builtins.int
|
||||
TYPESUBSCRIPTION_FIELD_NUMBER: builtins.int
|
||||
TYPEPREFIXSUBSCRIPTION_FIELD_NUMBER: builtins.int
|
||||
id: builtins.str
|
||||
@property
|
||||
def typeSubscription(self) -> global___TypeSubscription: ...
|
||||
@property
|
||||
def typePrefixSubscription(self) -> global___TypePrefixSubscription: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
id: builtins.str = ...,
|
||||
typeSubscription: global___TypeSubscription | None = ...,
|
||||
typePrefixSubscription: global___TypePrefixSubscription | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["subscription", b"subscription", "typePrefixSubscription", b"typePrefixSubscription", "typeSubscription", b"typeSubscription"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["id", b"id", "subscription", b"subscription", "typePrefixSubscription", b"typePrefixSubscription", "typeSubscription", b"typeSubscription"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["subscription", b"subscription"]) -> typing.Literal["typeSubscription", "typePrefixSubscription"] | None: ...
|
||||
|
||||
global___Subscription = Subscription
|
||||
|
||||
@typing.final
|
||||
class AddSubscriptionRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
SUBSCRIPTION_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def subscription(self) -> global___Subscription: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
subscription: global___Subscription | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["subscription", b"subscription"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["subscription", b"subscription"]) -> None: ...
|
||||
|
||||
global___AddSubscriptionRequest = AddSubscriptionRequest
|
||||
|
||||
@typing.final
|
||||
class AddSubscriptionResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
global___AddSubscriptionResponse = AddSubscriptionResponse
|
||||
|
||||
@typing.final
|
||||
class RemoveSubscriptionRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
ID_FIELD_NUMBER: builtins.int
|
||||
id: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
id: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["id", b"id"]) -> None: ...
|
||||
|
||||
global___RemoveSubscriptionRequest = RemoveSubscriptionRequest
|
||||
|
||||
@typing.final
|
||||
class RemoveSubscriptionResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
global___RemoveSubscriptionResponse = RemoveSubscriptionResponse
|
||||
|
||||
@typing.final
|
||||
class GetSubscriptionsRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
global___GetSubscriptionsRequest = GetSubscriptionsRequest
|
||||
|
||||
@typing.final
|
||||
class GetSubscriptionsResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
SUBSCRIPTIONS_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def subscriptions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Subscription]: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
subscriptions: collections.abc.Iterable[global___Subscription] | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["subscriptions", b"subscriptions"]) -> None: ...
|
||||
|
||||
global___GetSubscriptionsResponse = GetSubscriptionsResponse
|
||||
|
||||
@typing.final
|
||||
class Message(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
REQUEST_FIELD_NUMBER: builtins.int
|
||||
RESPONSE_FIELD_NUMBER: builtins.int
|
||||
CLOUDEVENT_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def request(self) -> global___RpcRequest: ...
|
||||
@property
|
||||
def response(self) -> global___RpcResponse: ...
|
||||
@property
|
||||
def cloudEvent(self) -> cloudevent_pb2.CloudEvent: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
request: global___RpcRequest | None = ...,
|
||||
response: global___RpcResponse | None = ...,
|
||||
cloudEvent: cloudevent_pb2.CloudEvent | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["cloudEvent", b"cloudEvent", "message", b"message", "request", b"request", "response", b"response"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["cloudEvent", b"cloudEvent", "message", b"message", "request", b"request", "response", b"response"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["request", "response", "cloudEvent"] | None: ...
|
||||
|
||||
global___Message = Message
|
||||
|
||||
@typing.final
|
||||
class SaveStateRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
AGENTID_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def agentId(self) -> global___AgentId: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
agentId: global___AgentId | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["agentId", b"agentId"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["agentId", b"agentId"]) -> None: ...
|
||||
|
||||
global___SaveStateRequest = SaveStateRequest
|
||||
|
||||
@typing.final
|
||||
class SaveStateResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
STATE_FIELD_NUMBER: builtins.int
|
||||
ERROR_FIELD_NUMBER: builtins.int
|
||||
state: builtins.str
|
||||
error: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
state: builtins.str = ...,
|
||||
error: builtins.str | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_error", b"_error", "error", b"error"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_error", b"_error", "error", b"error", "state", b"state"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_error", b"_error"]) -> typing.Literal["error"] | None: ...
|
||||
|
||||
global___SaveStateResponse = SaveStateResponse
|
||||
|
||||
@typing.final
|
||||
class LoadStateRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
AGENTID_FIELD_NUMBER: builtins.int
|
||||
STATE_FIELD_NUMBER: builtins.int
|
||||
state: builtins.str
|
||||
@property
|
||||
def agentId(self) -> global___AgentId: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
agentId: global___AgentId | None = ...,
|
||||
state: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["agentId", b"agentId"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["agentId", b"agentId", "state", b"state"]) -> None: ...
|
||||
|
||||
global___LoadStateRequest = LoadStateRequest
|
||||
|
||||
@typing.final
|
||||
class LoadStateResponse(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
ERROR_FIELD_NUMBER: builtins.int
|
||||
error: builtins.str
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
error: builtins.str | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_error", b"_error", "error", b"error"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_error", b"_error", "error", b"error"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_error", b"_error"]) -> typing.Literal["error"] | None: ...
|
||||
|
||||
global___LoadStateResponse = LoadStateResponse
|
||||
|
||||
@typing.final
|
||||
class ControlMessage(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
RPC_ID_FIELD_NUMBER: builtins.int
|
||||
DESTINATION_FIELD_NUMBER: builtins.int
|
||||
RESPOND_TO_FIELD_NUMBER: builtins.int
|
||||
RPCMESSAGE_FIELD_NUMBER: builtins.int
|
||||
rpc_id: builtins.str
|
||||
"""A response message should have the same id as the request message"""
|
||||
destination: builtins.str
|
||||
"""This is either:
|
||||
agentid=AGENT_ID
|
||||
clientid=CLIENT_ID
|
||||
"""
|
||||
respond_to: builtins.str
|
||||
"""This is either:
|
||||
agentid=AGENT_ID
|
||||
clientid=CLIENT_ID
|
||||
Empty string means the message is a response
|
||||
"""
|
||||
@property
|
||||
def rpcMessage(self) -> google.protobuf.any_pb2.Any:
|
||||
"""One of:
|
||||
SaveStateRequest saveStateRequest = 2;
|
||||
SaveStateResponse saveStateResponse = 3;
|
||||
LoadStateRequest loadStateRequest = 4;
|
||||
LoadStateResponse loadStateResponse = 5;
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
rpc_id: builtins.str = ...,
|
||||
destination: builtins.str = ...,
|
||||
respond_to: builtins.str | None = ...,
|
||||
rpcMessage: google.protobuf.any_pb2.Any | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_respond_to", b"_respond_to", "respond_to", b"respond_to", "rpcMessage", b"rpcMessage"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_respond_to", b"_respond_to", "destination", b"destination", "respond_to", b"respond_to", "rpcMessage", b"rpcMessage", "rpc_id", b"rpc_id"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_respond_to", b"_respond_to"]) -> typing.Literal["respond_to"] | None: ...
|
||||
|
||||
global___ControlMessage = ControlMessage
|
||||
@@ -0,0 +1,312 @@
|
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
import warnings
|
||||
|
||||
from . import agent_worker_pb2 as agent__worker__pb2
|
||||
|
||||
GRPC_GENERATED_VERSION = '1.70.0'
|
||||
GRPC_VERSION = grpc.__version__
|
||||
_version_not_supported = False
|
||||
|
||||
try:
|
||||
from grpc._utilities import first_version_is_lower
|
||||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
||||
except ImportError:
|
||||
_version_not_supported = True
|
||||
|
||||
if _version_not_supported:
|
||||
raise RuntimeError(
|
||||
f'The grpc package installed is at version {GRPC_VERSION},'
|
||||
+ f' but the generated code in agent_worker_pb2_grpc.py depends on'
|
||||
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
||||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
||||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
||||
)
|
||||
|
||||
|
||||
class AgentRpcStub(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.OpenChannel = channel.stream_stream(
|
||||
'/agents.AgentRpc/OpenChannel',
|
||||
request_serializer=agent__worker__pb2.Message.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.Message.FromString,
|
||||
_registered_method=True)
|
||||
self.OpenControlChannel = channel.stream_stream(
|
||||
'/agents.AgentRpc/OpenControlChannel',
|
||||
request_serializer=agent__worker__pb2.ControlMessage.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.ControlMessage.FromString,
|
||||
_registered_method=True)
|
||||
self.RegisterAgent = channel.unary_unary(
|
||||
'/agents.AgentRpc/RegisterAgent',
|
||||
request_serializer=agent__worker__pb2.RegisterAgentTypeRequest.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.RegisterAgentTypeResponse.FromString,
|
||||
_registered_method=True)
|
||||
self.AddSubscription = channel.unary_unary(
|
||||
'/agents.AgentRpc/AddSubscription',
|
||||
request_serializer=agent__worker__pb2.AddSubscriptionRequest.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.AddSubscriptionResponse.FromString,
|
||||
_registered_method=True)
|
||||
self.RemoveSubscription = channel.unary_unary(
|
||||
'/agents.AgentRpc/RemoveSubscription',
|
||||
request_serializer=agent__worker__pb2.RemoveSubscriptionRequest.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.RemoveSubscriptionResponse.FromString,
|
||||
_registered_method=True)
|
||||
self.GetSubscriptions = channel.unary_unary(
|
||||
'/agents.AgentRpc/GetSubscriptions',
|
||||
request_serializer=agent__worker__pb2.GetSubscriptionsRequest.SerializeToString,
|
||||
response_deserializer=agent__worker__pb2.GetSubscriptionsResponse.FromString,
|
||||
_registered_method=True)
|
||||
|
||||
|
||||
class AgentRpcServicer(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def OpenChannel(self, request_iterator, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def OpenControlChannel(self, request_iterator, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def RegisterAgent(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def AddSubscription(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def RemoveSubscription(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetSubscriptions(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_AgentRpcServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'OpenChannel': grpc.stream_stream_rpc_method_handler(
|
||||
servicer.OpenChannel,
|
||||
request_deserializer=agent__worker__pb2.Message.FromString,
|
||||
response_serializer=agent__worker__pb2.Message.SerializeToString,
|
||||
),
|
||||
'OpenControlChannel': grpc.stream_stream_rpc_method_handler(
|
||||
servicer.OpenControlChannel,
|
||||
request_deserializer=agent__worker__pb2.ControlMessage.FromString,
|
||||
response_serializer=agent__worker__pb2.ControlMessage.SerializeToString,
|
||||
),
|
||||
'RegisterAgent': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.RegisterAgent,
|
||||
request_deserializer=agent__worker__pb2.RegisterAgentTypeRequest.FromString,
|
||||
response_serializer=agent__worker__pb2.RegisterAgentTypeResponse.SerializeToString,
|
||||
),
|
||||
'AddSubscription': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.AddSubscription,
|
||||
request_deserializer=agent__worker__pb2.AddSubscriptionRequest.FromString,
|
||||
response_serializer=agent__worker__pb2.AddSubscriptionResponse.SerializeToString,
|
||||
),
|
||||
'RemoveSubscription': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.RemoveSubscription,
|
||||
request_deserializer=agent__worker__pb2.RemoveSubscriptionRequest.FromString,
|
||||
response_serializer=agent__worker__pb2.RemoveSubscriptionResponse.SerializeToString,
|
||||
),
|
||||
'GetSubscriptions': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetSubscriptions,
|
||||
request_deserializer=agent__worker__pb2.GetSubscriptionsRequest.FromString,
|
||||
response_serializer=agent__worker__pb2.GetSubscriptionsResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'agents.AgentRpc', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
server.add_registered_method_handlers('agents.AgentRpc', rpc_method_handlers)
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class AgentRpc(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
@staticmethod
|
||||
def OpenChannel(request_iterator,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.stream_stream(
|
||||
request_iterator,
|
||||
target,
|
||||
'/agents.AgentRpc/OpenChannel',
|
||||
agent__worker__pb2.Message.SerializeToString,
|
||||
agent__worker__pb2.Message.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
||||
@staticmethod
|
||||
def OpenControlChannel(request_iterator,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.stream_stream(
|
||||
request_iterator,
|
||||
target,
|
||||
'/agents.AgentRpc/OpenControlChannel',
|
||||
agent__worker__pb2.ControlMessage.SerializeToString,
|
||||
agent__worker__pb2.ControlMessage.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
||||
@staticmethod
|
||||
def RegisterAgent(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/agents.AgentRpc/RegisterAgent',
|
||||
agent__worker__pb2.RegisterAgentTypeRequest.SerializeToString,
|
||||
agent__worker__pb2.RegisterAgentTypeResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
||||
@staticmethod
|
||||
def AddSubscription(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/agents.AgentRpc/AddSubscription',
|
||||
agent__worker__pb2.AddSubscriptionRequest.SerializeToString,
|
||||
agent__worker__pb2.AddSubscriptionResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
||||
@staticmethod
|
||||
def RemoveSubscription(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/agents.AgentRpc/RemoveSubscription',
|
||||
agent__worker__pb2.RemoveSubscriptionRequest.SerializeToString,
|
||||
agent__worker__pb2.RemoveSubscriptionResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
|
||||
@staticmethod
|
||||
def GetSubscriptions(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
'/agents.AgentRpc/GetSubscriptions',
|
||||
agent__worker__pb2.GetSubscriptionsRequest.SerializeToString,
|
||||
agent__worker__pb2.GetSubscriptionsResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
insecure,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
_registered_method=True)
|
||||
@@ -0,0 +1,126 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
"""
|
||||
|
||||
import abc
|
||||
from . import agent_worker_pb2
|
||||
import collections.abc
|
||||
import grpc
|
||||
import grpc.aio
|
||||
import typing
|
||||
|
||||
_T = typing.TypeVar("_T")
|
||||
|
||||
class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ...
|
||||
|
||||
class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg]
|
||||
...
|
||||
|
||||
class AgentRpcStub:
|
||||
def __init__(self, channel: typing.Union[grpc.Channel, grpc.aio.Channel]) -> None: ...
|
||||
OpenChannel: grpc.StreamStreamMultiCallable[
|
||||
agent_worker_pb2.Message,
|
||||
agent_worker_pb2.Message,
|
||||
]
|
||||
|
||||
OpenControlChannel: grpc.StreamStreamMultiCallable[
|
||||
agent_worker_pb2.ControlMessage,
|
||||
agent_worker_pb2.ControlMessage,
|
||||
]
|
||||
|
||||
RegisterAgent: grpc.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.RegisterAgentTypeRequest,
|
||||
agent_worker_pb2.RegisterAgentTypeResponse,
|
||||
]
|
||||
|
||||
AddSubscription: grpc.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.AddSubscriptionRequest,
|
||||
agent_worker_pb2.AddSubscriptionResponse,
|
||||
]
|
||||
|
||||
RemoveSubscription: grpc.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.RemoveSubscriptionRequest,
|
||||
agent_worker_pb2.RemoveSubscriptionResponse,
|
||||
]
|
||||
|
||||
GetSubscriptions: grpc.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.GetSubscriptionsRequest,
|
||||
agent_worker_pb2.GetSubscriptionsResponse,
|
||||
]
|
||||
|
||||
class AgentRpcAsyncStub:
|
||||
OpenChannel: grpc.aio.StreamStreamMultiCallable[
|
||||
agent_worker_pb2.Message,
|
||||
agent_worker_pb2.Message,
|
||||
]
|
||||
|
||||
OpenControlChannel: grpc.aio.StreamStreamMultiCallable[
|
||||
agent_worker_pb2.ControlMessage,
|
||||
agent_worker_pb2.ControlMessage,
|
||||
]
|
||||
|
||||
RegisterAgent: grpc.aio.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.RegisterAgentTypeRequest,
|
||||
agent_worker_pb2.RegisterAgentTypeResponse,
|
||||
]
|
||||
|
||||
AddSubscription: grpc.aio.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.AddSubscriptionRequest,
|
||||
agent_worker_pb2.AddSubscriptionResponse,
|
||||
]
|
||||
|
||||
RemoveSubscription: grpc.aio.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.RemoveSubscriptionRequest,
|
||||
agent_worker_pb2.RemoveSubscriptionResponse,
|
||||
]
|
||||
|
||||
GetSubscriptions: grpc.aio.UnaryUnaryMultiCallable[
|
||||
agent_worker_pb2.GetSubscriptionsRequest,
|
||||
agent_worker_pb2.GetSubscriptionsResponse,
|
||||
]
|
||||
|
||||
class AgentRpcServicer(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def OpenChannel(
|
||||
self,
|
||||
request_iterator: _MaybeAsyncIterator[agent_worker_pb2.Message],
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[collections.abc.Iterator[agent_worker_pb2.Message], collections.abc.AsyncIterator[agent_worker_pb2.Message]]: ...
|
||||
|
||||
@abc.abstractmethod
|
||||
def OpenControlChannel(
|
||||
self,
|
||||
request_iterator: _MaybeAsyncIterator[agent_worker_pb2.ControlMessage],
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[collections.abc.Iterator[agent_worker_pb2.ControlMessage], collections.abc.AsyncIterator[agent_worker_pb2.ControlMessage]]: ...
|
||||
|
||||
@abc.abstractmethod
|
||||
def RegisterAgent(
|
||||
self,
|
||||
request: agent_worker_pb2.RegisterAgentTypeRequest,
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[agent_worker_pb2.RegisterAgentTypeResponse, collections.abc.Awaitable[agent_worker_pb2.RegisterAgentTypeResponse]]: ...
|
||||
|
||||
@abc.abstractmethod
|
||||
def AddSubscription(
|
||||
self,
|
||||
request: agent_worker_pb2.AddSubscriptionRequest,
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[agent_worker_pb2.AddSubscriptionResponse, collections.abc.Awaitable[agent_worker_pb2.AddSubscriptionResponse]]: ...
|
||||
|
||||
@abc.abstractmethod
|
||||
def RemoveSubscription(
|
||||
self,
|
||||
request: agent_worker_pb2.RemoveSubscriptionRequest,
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[agent_worker_pb2.RemoveSubscriptionResponse, collections.abc.Awaitable[agent_worker_pb2.RemoveSubscriptionResponse]]: ...
|
||||
|
||||
@abc.abstractmethod
|
||||
def GetSubscriptions(
|
||||
self,
|
||||
request: agent_worker_pb2.GetSubscriptionsRequest,
|
||||
context: _ServicerContext,
|
||||
) -> typing.Union[agent_worker_pb2.GetSubscriptionsResponse, collections.abc.Awaitable[agent_worker_pb2.GetSubscriptionsResponse]]: ...
|
||||
|
||||
def add_AgentRpcServicer_to_server(servicer: AgentRpcServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ...
|
||||
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# NO CHECKED-IN PROTOBUF GENCODE
|
||||
# source: cloudevent.proto
|
||||
# Protobuf Python Version: 5.29.0
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import runtime_version as _runtime_version
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
_runtime_version.ValidateProtobufRuntimeVersion(
|
||||
_runtime_version.Domain.PUBLIC,
|
||||
5,
|
||||
29,
|
||||
0,
|
||||
'',
|
||||
'cloudevent.proto'
|
||||
)
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
|
||||
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x63loudevent.proto\x12\x11io.cloudevents.v1\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb0\x04\n\nCloudEvent\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06source\x18\x02 \x01(\t\x12\x14\n\x0cspec_version\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\x41\n\nattributes\x18\x05 \x03(\x0b\x32-.io.cloudevents.v1.CloudEvent.AttributesEntry\x12\x15\n\x0b\x62inary_data\x18\x06 \x01(\x0cH\x00\x12\x13\n\ttext_data\x18\x07 \x01(\tH\x00\x12*\n\nproto_data\x18\x08 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x1ai\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x45\n\x05value\x18\x02 \x01(\x0b\x32\x36.io.cloudevents.v1.CloudEvent.CloudEventAttributeValue:\x02\x38\x01\x1a\xd3\x01\n\x18\x43loudEventAttributeValue\x12\x14\n\nce_boolean\x18\x01 \x01(\x08H\x00\x12\x14\n\nce_integer\x18\x02 \x01(\x05H\x00\x12\x13\n\tce_string\x18\x03 \x01(\tH\x00\x12\x12\n\x08\x63\x65_bytes\x18\x04 \x01(\x0cH\x00\x12\x10\n\x06\x63\x65_uri\x18\x05 \x01(\tH\x00\x12\x14\n\nce_uri_ref\x18\x06 \x01(\tH\x00\x12\x32\n\x0c\x63\x65_timestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x42\x06\n\x04\x61ttrB\x06\n\x04\x64\x61taB\x1e\xaa\x02\x1bMicrosoft.AutoGen.Contractsb\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cloudevent_pb2', _globals)
|
||||
if not _descriptor._USE_C_DESCRIPTORS:
|
||||
_globals['DESCRIPTOR']._loaded_options = None
|
||||
_globals['DESCRIPTOR']._serialized_options = b'\252\002\033Microsoft.AutoGen.Contracts'
|
||||
_globals['_CLOUDEVENT_ATTRIBUTESENTRY']._loaded_options = None
|
||||
_globals['_CLOUDEVENT_ATTRIBUTESENTRY']._serialized_options = b'8\001'
|
||||
_globals['_CLOUDEVENT']._serialized_start=100
|
||||
_globals['_CLOUDEVENT']._serialized_end=660
|
||||
_globals['_CLOUDEVENT_ATTRIBUTESENTRY']._serialized_start=333
|
||||
_globals['_CLOUDEVENT_ATTRIBUTESENTRY']._serialized_end=438
|
||||
_globals['_CLOUDEVENT_CLOUDEVENTATTRIBUTEVALUE']._serialized_start=441
|
||||
_globals['_CLOUDEVENT_CLOUDEVENTATTRIBUTEVALUE']._serialized_end=652
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
@@ -0,0 +1,125 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
*
|
||||
CloudEvent Protobuf Format
|
||||
|
||||
- Required context attributes are explicitly represented.
|
||||
- Optional and Extension context attributes are carried in a map structure.
|
||||
- Data may be represented as binary, text, or protobuf messages.
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import collections.abc
|
||||
import google.protobuf.any_pb2
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.containers
|
||||
import google.protobuf.message
|
||||
import google.protobuf.timestamp_pb2
|
||||
import typing
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
@typing.final
|
||||
class CloudEvent(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
@typing.final
|
||||
class AttributesEntry(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
KEY_FIELD_NUMBER: builtins.int
|
||||
VALUE_FIELD_NUMBER: builtins.int
|
||||
key: builtins.str
|
||||
@property
|
||||
def value(self) -> global___CloudEvent.CloudEventAttributeValue: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
key: builtins.str = ...,
|
||||
value: global___CloudEvent.CloudEventAttributeValue | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["value", b"value"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class CloudEventAttributeValue(google.protobuf.message.Message):
|
||||
"""*
|
||||
The CloudEvent specification defines
|
||||
seven attribute value types...
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
CE_BOOLEAN_FIELD_NUMBER: builtins.int
|
||||
CE_INTEGER_FIELD_NUMBER: builtins.int
|
||||
CE_STRING_FIELD_NUMBER: builtins.int
|
||||
CE_BYTES_FIELD_NUMBER: builtins.int
|
||||
CE_URI_FIELD_NUMBER: builtins.int
|
||||
CE_URI_REF_FIELD_NUMBER: builtins.int
|
||||
CE_TIMESTAMP_FIELD_NUMBER: builtins.int
|
||||
ce_boolean: builtins.bool
|
||||
ce_integer: builtins.int
|
||||
ce_string: builtins.str
|
||||
ce_bytes: builtins.bytes
|
||||
ce_uri: builtins.str
|
||||
ce_uri_ref: builtins.str
|
||||
@property
|
||||
def ce_timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
ce_boolean: builtins.bool = ...,
|
||||
ce_integer: builtins.int = ...,
|
||||
ce_string: builtins.str = ...,
|
||||
ce_bytes: builtins.bytes = ...,
|
||||
ce_uri: builtins.str = ...,
|
||||
ce_uri_ref: builtins.str = ...,
|
||||
ce_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["attr", b"attr", "ce_boolean", b"ce_boolean", "ce_bytes", b"ce_bytes", "ce_integer", b"ce_integer", "ce_string", b"ce_string", "ce_timestamp", b"ce_timestamp", "ce_uri", b"ce_uri", "ce_uri_ref", b"ce_uri_ref"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["attr", b"attr", "ce_boolean", b"ce_boolean", "ce_bytes", b"ce_bytes", "ce_integer", b"ce_integer", "ce_string", b"ce_string", "ce_timestamp", b"ce_timestamp", "ce_uri", b"ce_uri", "ce_uri_ref", b"ce_uri_ref"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["attr", b"attr"]) -> typing.Literal["ce_boolean", "ce_integer", "ce_string", "ce_bytes", "ce_uri", "ce_uri_ref", "ce_timestamp"] | None: ...
|
||||
|
||||
ID_FIELD_NUMBER: builtins.int
|
||||
SOURCE_FIELD_NUMBER: builtins.int
|
||||
SPEC_VERSION_FIELD_NUMBER: builtins.int
|
||||
TYPE_FIELD_NUMBER: builtins.int
|
||||
ATTRIBUTES_FIELD_NUMBER: builtins.int
|
||||
BINARY_DATA_FIELD_NUMBER: builtins.int
|
||||
TEXT_DATA_FIELD_NUMBER: builtins.int
|
||||
PROTO_DATA_FIELD_NUMBER: builtins.int
|
||||
id: builtins.str
|
||||
"""-- CloudEvent Context Attributes
|
||||
|
||||
Required Attributes
|
||||
"""
|
||||
source: builtins.str
|
||||
"""URI-reference"""
|
||||
spec_version: builtins.str
|
||||
type: builtins.str
|
||||
binary_data: builtins.bytes
|
||||
text_data: builtins.str
|
||||
@property
|
||||
def attributes(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, global___CloudEvent.CloudEventAttributeValue]:
|
||||
"""Optional & Extension Attributes"""
|
||||
|
||||
@property
|
||||
def proto_data(self) -> google.protobuf.any_pb2.Any: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
id: builtins.str = ...,
|
||||
source: builtins.str = ...,
|
||||
spec_version: builtins.str = ...,
|
||||
type: builtins.str = ...,
|
||||
attributes: collections.abc.Mapping[builtins.str, global___CloudEvent.CloudEventAttributeValue] | None = ...,
|
||||
binary_data: builtins.bytes = ...,
|
||||
text_data: builtins.str = ...,
|
||||
proto_data: google.protobuf.any_pb2.Any | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["binary_data", b"binary_data", "data", b"data", "proto_data", b"proto_data", "text_data", b"text_data"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["attributes", b"attributes", "binary_data", b"binary_data", "data", b"data", "id", b"id", "proto_data", b"proto_data", "source", b"source", "spec_version", b"spec_version", "text_data", b"text_data", "type", b"type"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["binary_data", "text_data", "proto_data"] | None: ...
|
||||
|
||||
global___CloudEvent = CloudEvent
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
import warnings
|
||||
|
||||
|
||||
GRPC_GENERATED_VERSION = '1.70.0'
|
||||
GRPC_VERSION = grpc.__version__
|
||||
_version_not_supported = False
|
||||
|
||||
try:
|
||||
from grpc._utilities import first_version_is_lower
|
||||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
||||
except ImportError:
|
||||
_version_not_supported = True
|
||||
|
||||
if _version_not_supported:
|
||||
raise RuntimeError(
|
||||
f'The grpc package installed is at version {GRPC_VERSION},'
|
||||
+ f' but the generated code in cloudevent_pb2_grpc.py depends on'
|
||||
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
||||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
||||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
*
|
||||
CloudEvent Protobuf Format
|
||||
|
||||
- Required context attributes are explicitly represented.
|
||||
- Optional and Extension context attributes are carried in a map structure.
|
||||
- Data may be represented as binary, text, or protobuf messages.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import collections.abc
|
||||
import grpc
|
||||
import grpc.aio
|
||||
import typing
|
||||
|
||||
_T = typing.TypeVar("_T")
|
||||
|
||||
class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ...
|
||||
|
||||
class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg]
|
||||
...
|
||||
Reference in New Issue
Block a user