diff --git a/docs/colang-2/examples/test_csl.py b/docs/colang-2/examples/test_csl.py index 728364c8e..4eeaa6efa 100644 --- a/docs/colang-2/examples/test_csl.py +++ b/docs/colang-2/examples/test_csl.py @@ -484,6 +484,94 @@ async def test_wait_indefinitely(): await compare_interaction_with_test_script(test_script, colang_code) +# @pytest.mark.asyncio +# async def test_it_finished(): +# colang_code = """ +# # COLANG_START: test_it_finished +# import core + +# flow bot greet +# bot say "hello" + +# flow test0 +# user said "hi" +# await UtteranceBotAction(script="hello") as $ref +# await it finished $ref + +# flow test1 +# user said "hi" +# await bot greet as $ref +# await it finished $ref + +# flow test2 +# user said "hi" +# start bot greet as $ref +# send $ref.Stop() +# await it finished $ref + +# flow main +# await test0 +# bot say "test0 success" + +# start test1 as $ref +# match $ref.Finished() +# bot say "test1 success" + +# start test2 as $ref +# match $ref.Failed() +# bot say "test2 success" + +# # COLANG_END: test_it_finished +# """ + +# test_script = """ +# # USAGE_START: test_it_finished +# > hi +# hello +# test0 success +# > hi +# hello +# test1 success +# > hi +# hello +# Event: StopUtteranceBotAction +# test2 success +# # USAGE_END: test_it_finished +# """ + + +@pytest.mark.asyncio +async def test_it_finished(): + colang_code = """ +# COLANG_START: test_it_finished +import core + +flow bot greet + bot say "hello" + +flow main + user said "hi" + start bot greet as $ref + it finished $ref + bot say "finish" + it finished $ref + bot say "still finished" + +# COLANG_END: test_it_finished + """ + + test_script = """ +# USAGE_START: test_it_finished +> hi +hello +finish +still finished +# USAGE_END: test_it_finished + """ + + await compare_interaction_with_test_script(test_script, colang_code) + + ######################################################################################################################## # TIMING ######################################################################################################################## diff --git a/docs/colang-2/language-reference/csl/core.rst b/docs/colang-2/language-reference/csl/core.rst index 5355ef754..eb6796778 100644 --- a/docs/colang-2/language-reference/csl/core.rst +++ b/docs/colang-2/language-reference/csl/core.rst @@ -313,6 +313,31 @@ Utilities :dedent: +.. py:function:: it finished + + Wait until a flow or action has finished. This will also check the action's or flow's state and if it has + already finished, continue immediately. If the awaited flow has already failed instead of finished, this flow + will also fail. + + Note: Actions can never fail, even if stopped, but will always finish. If an action was stopped, the ActionFinished + event will have a ``was_stopped=True`` argument. + + Example: + + .. literalinclude:: ../../examples/test_csl.py + :language: colang + :start-after: # COLANG_START: test_it_finished + :end-before: # COLANG_END: test_it_finished + :dedent: + + + .. literalinclude:: ../../examples/test_csl.py + :language: text + :start-after: # USAGE_START: test_it_finished + :end-before: # USAGE_END: test_it_finished + :dedent: + + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ State Tracking Flows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/nemoguardrails/colang/v2_x/library/core.co b/nemoguardrails/colang/v2_x/library/core.co index 147d4f1d9..6d182473d 100644 --- a/nemoguardrails/colang/v2_x/library/core.co +++ b/nemoguardrails/colang/v2_x/library/core.co @@ -290,3 +290,32 @@ flow await_flow_by_name $flow_name $new_flow_instance_uid = None send StartFlow(flow_id=$flow_name, flow_instance_uid=$new_flow_instance_uid) match FlowStarted(flow_id=$flow_name, flow_instance_uid=$new_flow_instance_uid) as $event_ref match $event_ref.flow.Finished() + +flow it finished $ref -> $finished_event_ref + """Wait until a flow or action has finished.""" + + $type = type($ref) + if $type != "Action" and $type != "FlowState": + log "flow `it finished` expects a flow or action reference as parameter." + abort + + if $type == "FlowState" and $ref.status.value == "stopped": + # We abort this flow since it will never finish + abort + + if $ref.status.value != "finished": + match $ref.Finished() as $finished_event_ref + +flow flow_failed $flow_ref -> $failed_event_ref + """Wait until a flow has failed.""" + + if type($flow_ref) != "FlowState": + log "flow `flow_failed` expects a flow reference as parameter." + abort + + if $flow_ref.status.value == "finished": + # We abort this flow since it will never fail + abort + + if $flow_ref.status.value != "stopped": + match $flow_ref.Failed() as $failed_event_ref