def _process_envelopes( agent_name: str, identity_stub: Identity, inbox: InBox, outbox: OutBox, dialogues: DefaultDialogues, ) -> None: """ Process envelopes. :param agent_name: name of an agent. :param identity_stub: stub identity. :param inbox: an inbox object. :param outbox: an outbox object. :param dialogues: the dialogues object. :return: None. """ envelope = _try_construct_envelope(agent_name, identity_stub.name, dialogues) if envelope is None: if not inbox.empty(): envelope = inbox.get_nowait() assert envelope is not None, "Could not recover envelope from inbox." click.echo(_construct_message("received", envelope)) else: click.echo("Received no new envelope!") else: outbox.put(envelope) click.echo(_construct_message("sending", envelope))
def test_outbox_put(): """Tests that an envelope is putted into the queue.""" agent_address = "Agent0" receiver_address = "Agent1" msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.counterparty = receiver_address dummy_connection = _make_dummy_connection() multiplexer = Multiplexer([dummy_connection]) outbox = OutBox(multiplexer, agent_address) inbox = InBox(multiplexer) multiplexer.connect() envelope = Envelope( to=receiver_address, sender=agent_address, protocol_id=DefaultMessage.protocol_id, message=msg, ) outbox.put(envelope) time.sleep(0.5) assert not inbox.empty(), "Inbox must not be empty after putting an envelope" multiplexer.disconnect()
def test_outbox_put(): """Tests that an envelope is putted into the queue.""" agent_address = "Agent0" receiver_address = "Agent1" msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.to = receiver_address msg.sender = agent_address dummy_connection = _make_dummy_connection() multiplexer = Multiplexer([dummy_connection]) outbox = OutBox(multiplexer) inbox = InBox(multiplexer) multiplexer.connect() envelope = Envelope( to=receiver_address, sender=agent_address, message=msg, ) outbox.put(envelope) wait_for_condition(lambda: inbox.empty(), 15, "Inbox must not be empty after putting an envelope") multiplexer.disconnect()
def test_outbox_empty(): """Test thet the outbox queue is empty.""" dummy_connection = _make_dummy_connection() multiplexer = Multiplexer([dummy_connection]) multiplexer.connect() outbox = OutBox(multiplexer) assert outbox.empty(), "The outbox is not empty" multiplexer.disconnect()
def _run_interaction_channel(): # load agent configuration file loader = ConfigLoader.from_configuration_type(PackageType.AGENT) agent_configuration = loader.load(Path(DEFAULT_AEA_CONFIG_FILE).open()) agent_name = agent_configuration.name # load stub connection configuration = ConnectionConfig( input_file=DEFAULT_OUTPUT_FILE_NAME, output_file=DEFAULT_INPUT_FILE_NAME, connection_id=StubConnection.connection_id, ) identity_stub = Identity(agent_name + "_interact", "interact") stub_connection = StubConnection(configuration=configuration, identity=identity_stub) multiplexer = Multiplexer([stub_connection]) inbox = InBox(multiplexer) outbox = OutBox(multiplexer, default_address=identity_stub.address) dialogues = DefaultDialogues(identity_stub.name) try: multiplexer.connect() while True: # pragma: no cover _process_envelopes(agent_name, identity_stub, inbox, outbox, dialogues) except KeyboardInterrupt: click.echo("Interaction interrupted!") except BaseException as e: # pylint: disable=broad-except # pragma: no cover click.echo(e) finally: multiplexer.disconnect()
def setup(cls) -> None: """Set up the skill test case.""" identity = Identity("test_agent_name", "test_agent_address") cls._multiplexer = AsyncMultiplexer() cls._multiplexer._out_queue = ( # pylint: disable=protected-access asyncio.Queue() ) cls._outbox = OutBox(cast(Multiplexer, cls._multiplexer)) agent_context = AgentContext( identity=identity, connection_status=cls._multiplexer.connection_status, outbox=cls._outbox, decision_maker_message_queue=Queue(), decision_maker_handler_context=SimpleNamespace(), task_manager=TaskManager(), default_ledger_id=identity.default_address_key, currency_denominations=DEFAULT_CURRENCY_DENOMINATIONS, default_connection=None, default_routing={}, search_service_address="dummy_search_service_address", decision_maker_address="dummy_decision_maker_address", ) cls._skill = Skill.from_dir(str(cls.path_to_skill), agent_context)
def __init__( self, identity: Identity, connections: List[Connection], loop: Optional[AbstractEventLoop] = None, period: float = 1.0, loop_mode: Optional[str] = None, runtime_mode: Optional[str] = None, logger: Logger = _default_logger, ) -> None: """ Instantiate the agent. :param identity: the identity of the agent. :param connections: the list of connections of the agent. :param loop: the event loop to run the connections. :param period: period to call agent's act :param loop_mode: loop_mode to choose agent run loop. :param runtime_mode: runtime mode to up agent. :return: None """ WithLogger.__init__(self, logger=logger) self._connections = connections self._identity = identity self._period = period self._tick = 0 self._runtime_mode = runtime_mode or self.DEFAULT_RUNTIME runtime_cls = self._get_runtime_class() self._runtime: BaseRuntime = runtime_cls(agent=self, loop_mode=loop_mode, loop=loop) self._inbox = InBox(self.runtime.multiplexer) self._outbox = OutBox(self.runtime.multiplexer)
def _run_interaction_channel(): loader = ConfigLoader.from_configuration_type(PackageType.AGENT) agent_configuration = loader.load(Path(DEFAULT_AEA_CONFIG_FILE).open()) agent_name = agent_configuration.name identity_stub = Identity(agent_name + "_interact", "interact") _load_packages(identity_stub) # load agent configuration file from packages.fetchai.connections.stub.connection import ( # noqa: F811 # pylint: disable=import-outside-toplevel DEFAULT_INPUT_FILE_NAME, DEFAULT_OUTPUT_FILE_NAME, StubConnection, ) from packages.fetchai.protocols.default.dialogues import ( # noqa: F811 # pylint: disable=import-outside-toplevel DefaultDialogue, DefaultDialogues, ) from packages.fetchai.protocols.default.message import ( # noqa: F811 # pylint: disable=import-outside-toplevel DefaultMessage, ) # load stub connection configuration = ConnectionConfig( input_file=DEFAULT_OUTPUT_FILE_NAME, output_file=DEFAULT_INPUT_FILE_NAME, connection_id=StubConnection.connection_id, ) stub_connection = StubConnection( configuration=configuration, identity=identity_stub ) multiplexer = Multiplexer([stub_connection]) inbox = InBox(multiplexer) outbox = OutBox(multiplexer) def role_from_first_message( # pylint: disable=unused-argument message: Message, receiver_address: Address ) -> BaseDialogue.Role: """Infer the role of the agent from an incoming/outgoing first message :param message: an incoming/outgoing first message :param receiver_address: the address of the receiving agent :return: The role of the agent """ return DefaultDialogue.Role.AGENT dialogues = DefaultDialogues(identity_stub.name, role_from_first_message) try: multiplexer.connect() while True: # pragma: no cover _process_envelopes(agent_name, inbox, outbox, dialogues, DefaultMessage) except KeyboardInterrupt: click.echo("Interaction interrupted!") except BaseException as e: # pylint: disable=broad-except # pragma: no cover click.echo(e) finally: multiplexer.disconnect()
def test_outbox_put_message(): """Tests that an envelope is created from the message is in the queue.""" agent_address = "Agent0" receiver_address = "Agent1" msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.counterparty = receiver_address dummy_connection = _make_dummy_connection() multiplexer = Multiplexer([dummy_connection]) outbox = OutBox(multiplexer, agent_address) inbox = InBox(multiplexer) multiplexer.connect() outbox.put_message(msg) time.sleep(0.5) assert not inbox.empty(), "Inbox will not be empty after putting a message." multiplexer.disconnect()
def _process_envelopes( agent_name: str, inbox: InBox, outbox: OutBox, dialogues: Dialogues, message_class: Type[Message], ) -> None: """ Process envelopes. :param agent_name: name of an agent. :param inbox: an inbox object. :param outbox: an outbox object. :param dialogues: the dialogues object. :param message_class: the message class. :return: None. """ envelope = _try_construct_envelope(agent_name, dialogues, message_class) if envelope is None: _check_for_incoming_envelope(inbox, message_class) else: outbox.put(envelope) click.echo(_construct_message("sending", envelope, message_class))
def _set_runtime_and_mail_boxes( self, runtime_class: Type[BaseRuntime], multiplexer_options: Dict, loop_mode: Optional[str] = None, loop: Optional[AbstractEventLoop] = None, ) -> None: """Set the runtime and inbox and outbox.""" self._runtime = runtime_class( agent=self, loop_mode=loop_mode, loop=loop, multiplexer_options=multiplexer_options, ) self._inbox = InBox(self.runtime.multiplexer) self._outbox = OutBox(self.runtime.multiplexer)
def setup(cls, **kwargs: Any) -> None: """Set up the skill test case.""" identity = Identity("test_agent_name", "test_agent_address") cls._multiplexer = AsyncMultiplexer() cls._multiplexer._out_queue = ( # pylint: disable=protected-access asyncio.Queue() ) cls._outbox = OutBox(cast(Multiplexer, cls._multiplexer)) _shared_state = cast(Dict[str, Any], kwargs.pop("shared_state", dict())) _skill_config_overrides = cast( Dict[str, Any], kwargs.pop("config_overrides", dict()) ) agent_context = AgentContext( identity=identity, connection_status=cls._multiplexer.connection_status, outbox=cls._outbox, decision_maker_message_queue=Queue(), decision_maker_handler_context=SimpleNamespace(), task_manager=TaskManager(), default_ledger_id=identity.default_address_key, currency_denominations=DEFAULT_CURRENCY_DENOMINATIONS, default_connection=None, default_routing={}, search_service_address="dummy_search_service_address", decision_maker_address="dummy_decision_maker_address", data_dir=os.getcwd(), ) # This enables pre-populating the 'shared_state' prior to loading the skill if _shared_state != dict(): for key, value in _shared_state.items(): agent_context.shared_state[key] = value skill_configuration_file_path: Path = Path(cls.path_to_skill, "skill.yaml") loader = ConfigLoaders.from_package_type(PackageType.SKILL) with open_file(skill_configuration_file_path) as fp: skill_config: SkillConfig = loader.load(fp) # This enables overriding the skill's config prior to loading if _skill_config_overrides != {}: skill_config.update(_skill_config_overrides) skill_config.directory = cls.path_to_skill cls._skill = Skill.from_config(skill_config, agent_context)
async def test_threaded_mode(): """Test InBox OutBox objects in threaded mode.""" connection_1 = _make_dummy_connection() connections = [connection_1] multiplexer = AsyncMultiplexer(connections, threaded=True) msg = DefaultMessage( performative=DefaultMessage.Performative.BYTES, content=b"", ) msg.to = "to" msg.sender = "sender" context = EnvelopeContext(connection_id=connection_1.connection_id) envelope = Envelope( to="to", sender="sender", message=msg, context=context, ) try: await multiplexer.connect() await asyncio.sleep(0.5) inbox = InBox(multiplexer) outbox = OutBox(multiplexer) assert inbox.empty() assert outbox.empty() outbox.put(envelope) received = await inbox.async_get() assert received == envelope assert inbox.empty() assert outbox.empty() outbox.put_message(msg, context=context) await inbox.async_wait() received = inbox.get_nowait() assert received == envelope finally: await multiplexer.disconnect()
async def test_inbox_outbox(): """Test InBox OutBox objects.""" connection_1 = _make_dummy_connection() connections = [connection_1] multiplexer = AsyncMultiplexer(connections, loop=asyncio.get_event_loop()) msg = DefaultMessage(performative=DefaultMessage.Performative.BYTES, content=b"",) msg.counterparty = "to" msg.sender = "sender" context = EnvelopeContext(connection_id=connection_1.connection_id) envelope = Envelope( to="to", sender="sender", protocol_id=msg.protocol_id, message=msg, context=context, ) try: await multiplexer.connect() inbox = InBox(multiplexer) outbox = OutBox(multiplexer, "default_address") assert inbox.empty() assert outbox.empty() outbox.put(envelope) received = await inbox.async_get() assert received == envelope assert inbox.empty() assert outbox.empty() outbox.put_message(msg, context=context) await inbox.async_wait() received = inbox.get_nowait() assert received == envelope finally: await multiplexer.disconnect()
def __init__( self, identity: Identity, connections: List[Connection], loop: Optional[AbstractEventLoop] = None, timeout: float = 1.0, loop_mode: Optional[str] = None, runtime_mode: Optional[str] = None, ) -> None: """ Instantiate the agent. :param identity: the identity of the agent. :param connections: the list of connections of the agent. :param loop: the event loop to run the connections. :param timeout: the time in (fractions of) seconds to time out an agent between act and react :param loop_mode: loop_mode to choose agent run loop. :param runtime_mode: runtime mode to up agent. :return: None """ self._identity = identity self._connections = connections self._multiplexer = Multiplexer(self._connections, loop=loop) self._inbox = InBox(self._multiplexer) self._outbox = OutBox(self._multiplexer, identity.address) self._liveness = Liveness() self._timeout = timeout self._tick = 0 self._loop_mode = loop_mode or self.DEFAULT_RUN_LOOP loop_cls = self._get_main_loop_class() self._main_loop: BaseAgentLoop = loop_cls(self) self._runtime_mode = runtime_mode or self.DEFAULT_RUNTIME runtime_cls = self._get_runtime_class() self._runtime: BaseRuntime = runtime_cls(agent=self, loop=loop)
async def test_outbox_negative(): """Test InBox OutBox objects.""" connection_1 = _make_dummy_connection() connections = [connection_1] multiplexer = AsyncMultiplexer(connections, loop=asyncio.get_event_loop()) msg = DefaultMessage( performative=DefaultMessage.Performative.BYTES, content=b"", ) context = EnvelopeContext(connection_id=connection_1.connection_id) envelope = Envelope( to="to", sender="sender", protocol_specification_id=msg.protocol_specification_id, message=b"", context=context, ) try: await multiplexer.connect() outbox = OutBox(multiplexer) assert outbox.empty() with pytest.raises(ValueError) as execinfo: outbox.put(envelope) assert ( str(execinfo.value) == "Only Message type allowed in envelope message field when putting into outbox." ) assert outbox.empty() with pytest.raises(ValueError) as execinfo: outbox.put_message("") assert str(execinfo.value) == "Provided message not of type Message." assert outbox.empty() with pytest.raises(ValueError) as execinfo: outbox.put_message(msg) assert str( execinfo.value) == "Provided message has message.to not set." assert outbox.empty() msg.to = "to" with pytest.raises(ValueError) as execinfo: outbox.put_message(msg) assert str( execinfo.value) == "Provided message has message.sender not set." finally: await multiplexer.disconnect()