diff --git a/nemoguardrails/colang/v2_x/runtime/runtime.py b/nemoguardrails/colang/v2_x/runtime/runtime.py index fe971e1d6..870a84830 100644 --- a/nemoguardrails/colang/v2_x/runtime/runtime.py +++ b/nemoguardrails/colang/v2_x/runtime/runtime.py @@ -489,6 +489,7 @@ async def process_events( # we continue the processing. events_counter = 0 while input_events or local_running_actions: + new_outgoing_events = [] for event in input_events: events_counter += 1 if events_counter > self.max_events: @@ -610,12 +611,13 @@ async def process_events( pending_local_async_action_counter, ) = await self._get_async_actions_finished_events(main_flow_uid) local_action_finished_events.extend(new_local_action_finished_events) + new_outgoing_events.extend(state.outgoing_events) input_events.clear() # If we have outgoing events we are also processing them as input events - if state.outgoing_events: - input_events.extend(state.outgoing_events) + if new_outgoing_events: + input_events.extend(new_outgoing_events) continue input_events.extend(local_action_finished_events) diff --git a/tests/v2_x/test_outgoing_events.py b/tests/v2_x/test_outgoing_events.py new file mode 100644 index 000000000..795166114 --- /dev/null +++ b/tests/v2_x/test_outgoing_events.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from nemoguardrails import RailsConfig +from tests.utils import TestChat + + +@pytest.fixture +def config_1(): + return RailsConfig.from_content( + colang_content=""" + flow user said $text + match UtteranceUserActionFinished(final_transcript=$text) + + flow bot say $text + await UtteranceBotAction(script=$text) + + flow wait + await SomeRandomAction() + + # --- + flow a + match EventA() + send EventC() + + flow b + match EventB() + send EventD() + + flow c + match EventD() + bot say "Hello" + + flow main + activate a + activate b + activate c + + user said "hi" + send EventA() + send EventB() + wait + """, + yaml_content=""" + colang_version: "2.x" + """, + ) + + +def test_outgoing_events(config_1): + chat = TestChat( + config_1, + llm_completions=[], + ) + + chat >> "hi" + chat << "Hello"