rasa-pro 3.13.6__py3-none-any.whl → 3.14.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/agents/__init__.py +0 -0
- rasa/agents/agent_factory.py +122 -0
- rasa/agents/agent_manager.py +162 -0
- rasa/agents/constants.py +31 -0
- rasa/agents/core/__init__.py +0 -0
- rasa/agents/core/agent_protocol.py +108 -0
- rasa/agents/core/types.py +70 -0
- rasa/agents/exceptions.py +8 -0
- rasa/agents/protocol/__init__.py +5 -0
- rasa/agents/protocol/a2a/__init__.py +0 -0
- rasa/agents/protocol/a2a/a2a_agent.py +51 -0
- rasa/agents/protocol/mcp/__init__.py +0 -0
- rasa/agents/protocol/mcp/mcp_base_agent.py +697 -0
- rasa/agents/protocol/mcp/mcp_open_agent.py +275 -0
- rasa/agents/protocol/mcp/mcp_task_agent.py +447 -0
- rasa/agents/schemas/__init__.py +6 -0
- rasa/agents/schemas/agent_input.py +24 -0
- rasa/agents/schemas/agent_output.py +26 -0
- rasa/agents/schemas/agent_tool_result.py +51 -0
- rasa/agents/schemas/agent_tool_schema.py +112 -0
- rasa/agents/templates/__init__.py +0 -0
- rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +15 -0
- rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +13 -0
- rasa/agents/utils.py +72 -0
- rasa/api.py +5 -0
- rasa/cli/arguments/default_arguments.py +12 -0
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/dialogue_understanding_test.py +4 -0
- rasa/cli/e2e_test.py +4 -0
- rasa/cli/inspect.py +3 -0
- rasa/cli/llm_fine_tuning.py +5 -0
- rasa/cli/run.py +4 -0
- rasa/cli/shell.py +3 -0
- rasa/cli/train.py +2 -2
- rasa/constants.py +6 -0
- rasa/core/actions/action.py +69 -39
- rasa/core/actions/action_run_slot_rejections.py +1 -1
- rasa/core/agent.py +16 -0
- rasa/core/available_agents.py +196 -0
- rasa/core/available_endpoints.py +30 -0
- rasa/core/channels/development_inspector.py +47 -14
- rasa/core/channels/inspector/dist/assets/{arc-0b11fe30.js → arc-2e78c586.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-9eef30a7.js → blockDiagram-38ab4fdb-806b712e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-03e94f28.js → c4Diagram-3d4e48cf-0745efa9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-c436ca7c.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-95c09eba.js → classDiagram-70f12bd4-7bd1082b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-38e8446c.js → classDiagram-v2-f2320105-d937ba49.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-50dd656b.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-57dc3038.js → createText-2e5e7dd3-a2a564ca.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-4bac0545.js → edges-e0da2a9e-b5256940.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-81795c90.js → erDiagram-9861fffd-e6883ad2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-89489ae6.js → flowDb-956e92f1-e576fc02.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-cd152627.js → flowDiagram-66a62f08-2e298d01.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b2aeaf8.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-3da369bc.js → flowchart-elk-definition-4a651766-dd7b150a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-85ec16f8.js → ganttDiagram-c361ad54-5b79575c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-495bc140.js → gitGraphDiagram-72cf32ee-3016f40a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-1ec4d266.js → graph-3e19170f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-1bd9135e.js +1353 -0
- rasa/core/channels/inspector/dist/assets/{index-3862675e-0a0e97c9.js → index-3862675e-eb9c86de.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-4d54bcde.js → infoDiagram-f8f76790-b4280e4d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-dc097114.js → journeyDiagram-49397b02-556091f8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-1a08981e.js → layout-08436411.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-95f7f1d3.js → line-683c4f3b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-97e69543.js → linear-cee6d791.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-8c71ff03.js → mindmap-definition-fc14e90a-a0bf0b1a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-f14c71c7.js → pieDiagram-8a3498a8-3730d5c4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-f1d3c9ff.js → quadrantDiagram-120e2f19-12a20fed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-bfa2412f.js → requirementDiagram-deff3bca-b9732102.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-53f2c97b.js → sankeyDiagram-04a897e0-a2e72776.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-319d7c0e.js → sequenceDiagram-704730f1-8b7a76bb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-76a09418.js → stateDiagram-587899a1-e65853ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-a67f15d4.js → stateDiagram-v2-d93cdb3a-6f58a44b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0654e7c3.js → styles-6aaf32cf-df25b934.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1394bb9d.js → styles-9a916d00-88357141.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-e4c5bdae.js → styles-c10674c1-d600174d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-50957104.js → svgDrawCommon-08f97a94-4adc3e0b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-b0885a6a.js → timeline-definition-85554ec2-42816fa1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-79e6541a.js → xychartDiagram-e933f94c-621eb66a.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +2 -2
- rasa/core/channels/inspector/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +53 -7
- rasa/core/channels/inspector/src/components/Chat.tsx +3 -2
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +7 -5
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +268 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +8 -3
- rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
- rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
- rasa/core/channels/inspector/src/types.ts +12 -0
- rasa/core/channels/studio_chat.py +125 -34
- rasa/core/channels/voice_ready/twilio_voice.py +1 -1
- rasa/core/channels/voice_stream/audiocodes.py +9 -6
- rasa/core/channels/voice_stream/browser_audio.py +39 -4
- rasa/core/channels/voice_stream/call_state.py +13 -2
- rasa/core/channels/voice_stream/genesys.py +16 -13
- rasa/core/channels/voice_stream/jambonz.py +13 -11
- rasa/core/channels/voice_stream/twilio_media_streams.py +14 -13
- rasa/core/channels/voice_stream/util.py +11 -1
- rasa/core/channels/voice_stream/voice_channel.py +101 -29
- rasa/core/constants.py +4 -0
- rasa/core/nlg/contextual_response_rephraser.py +11 -7
- rasa/core/nlg/generator.py +21 -5
- rasa/core/nlg/response.py +43 -6
- rasa/core/nlg/translate.py +8 -0
- rasa/core/policies/enterprise_search_policy.py +4 -2
- rasa/core/policies/flow_policy.py +2 -2
- rasa/core/policies/flows/flow_executor.py +374 -35
- rasa/core/policies/flows/mcp_tool_executor.py +240 -0
- rasa/core/processor.py +6 -1
- rasa/core/run.py +8 -1
- rasa/core/utils.py +21 -1
- rasa/dialogue_understanding/commands/__init__.py +8 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +97 -4
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +11 -0
- rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +11 -0
- rasa/dialogue_understanding/commands/restart_agent_command.py +146 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +129 -8
- rasa/dialogue_understanding/commands/utils.py +6 -2
- rasa/dialogue_understanding/generator/command_parser.py +4 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +61 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +61 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +81 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +81 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +7 -6
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +7 -6
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +41 -2
- rasa/dialogue_understanding/patterns/continue_interrupted.py +163 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +51 -7
- rasa/dialogue_understanding/processor/command_processor.py +27 -11
- rasa/dialogue_understanding/stack/dialogue_stack.py +123 -2
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
- rasa/dialogue_understanding/stack/utils.py +3 -2
- rasa/dialogue_understanding_test/du_test_runner.py +7 -2
- rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
- rasa/e2e_test/e2e_test_runner.py +5 -0
- rasa/e2e_test/e2e_test_schema.yml +3 -3
- rasa/model_manager/model_api.py +1 -1
- rasa/model_manager/socket_bridge.py +8 -2
- rasa/server.py +10 -0
- rasa/shared/agents/__init__.py +0 -0
- rasa/shared/agents/utils.py +35 -0
- rasa/shared/constants.py +5 -0
- rasa/shared/core/constants.py +12 -1
- rasa/shared/core/domain.py +5 -5
- rasa/shared/core/events.py +319 -0
- rasa/shared/core/flows/flows_list.py +2 -2
- rasa/shared/core/flows/flows_yaml_schema.json +101 -186
- rasa/shared/core/flows/steps/call.py +51 -5
- rasa/shared/core/flows/validation.py +45 -7
- rasa/shared/core/flows/yaml_flows_io.py +3 -3
- rasa/shared/providers/llm/_base_litellm_client.py +39 -7
- rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
- rasa/shared/providers/llm/llm_client.py +7 -3
- rasa/shared/providers/llm/llm_response.py +49 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
- rasa/shared/utils/common.py +2 -1
- rasa/shared/utils/llm.py +28 -5
- rasa/shared/utils/mcp/__init__.py +0 -0
- rasa/shared/utils/mcp/server_connection.py +157 -0
- rasa/shared/utils/schemas/events.py +42 -0
- rasa/tracing/instrumentation/instrumentation.py +4 -2
- rasa/utils/common.py +53 -0
- rasa/utils/licensing.py +21 -10
- rasa/utils/plotting.py +1 -1
- rasa/version.py +1 -1
- {rasa_pro-3.13.6.dist-info → rasa_pro-3.14.0.dev1.dist-info}/METADATA +16 -15
- {rasa_pro-3.13.6.dist-info → rasa_pro-3.14.0.dev1.dist-info}/RECORD +174 -137
- rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-c804b295.js +0 -1335
- {rasa_pro-3.13.6.dist-info → rasa_pro-3.14.0.dev1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.6.dist-info → rasa_pro-3.14.0.dev1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.6.dist-info → rasa_pro-3.14.0.dev1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
import structlog
|
|
5
|
+
from mcp.types import CallToolResult
|
|
6
|
+
|
|
7
|
+
from rasa.core.available_endpoints import AvailableEndpoints
|
|
8
|
+
from rasa.core.policies.flows.flow_step_result import (
|
|
9
|
+
ContinueFlowWithNextStep,
|
|
10
|
+
FlowStepResult,
|
|
11
|
+
)
|
|
12
|
+
from rasa.dialogue_understanding.patterns.internal_error import (
|
|
13
|
+
InternalErrorPatternFlowStackFrame,
|
|
14
|
+
)
|
|
15
|
+
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
16
|
+
from rasa.shared.core.events import Event, SlotSet
|
|
17
|
+
from rasa.shared.core.flows.steps import CallFlowStep
|
|
18
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
19
|
+
from rasa.shared.utils.mcp.server_connection import MCPServerConnection
|
|
20
|
+
|
|
21
|
+
structlogger = structlog.get_logger()
|
|
22
|
+
|
|
23
|
+
SEPARATOR = "\n###\n"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def call_mcp_tool(
|
|
27
|
+
initial_events: List[Event],
|
|
28
|
+
stack: DialogueStack,
|
|
29
|
+
step: CallFlowStep,
|
|
30
|
+
tracker: DialogueStateTracker,
|
|
31
|
+
) -> FlowStepResult:
|
|
32
|
+
"""Run an MCP tool call step."""
|
|
33
|
+
structlogger.debug(
|
|
34
|
+
"flow.step.call_mcp_tool",
|
|
35
|
+
tool_id=step.call,
|
|
36
|
+
mcp_server=step.mcp_server,
|
|
37
|
+
mapping=step.mapping,
|
|
38
|
+
step_id=step.id,
|
|
39
|
+
flow_id=step.flow_id,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
return await _execute_mcp_tool_call(initial_events, stack, step, tracker)
|
|
44
|
+
except Exception as e:
|
|
45
|
+
return _handle_mcp_tool_error(
|
|
46
|
+
stack,
|
|
47
|
+
initial_events,
|
|
48
|
+
error_message=f"Failed to execute MCP tool call: {e}.",
|
|
49
|
+
tool_name=step.call,
|
|
50
|
+
mcp_server=step.mcp_server,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def _execute_mcp_tool_call(
|
|
55
|
+
initial_events: List[Event],
|
|
56
|
+
stack: DialogueStack,
|
|
57
|
+
step: CallFlowStep,
|
|
58
|
+
tracker: DialogueStateTracker,
|
|
59
|
+
) -> FlowStepResult:
|
|
60
|
+
"""Execute the MCP tool call with proper error handling."""
|
|
61
|
+
mcp_server_connection = None
|
|
62
|
+
try:
|
|
63
|
+
# Connect to the MCP server
|
|
64
|
+
mcp_server_connection = await _connect_to_mcp_server(step.mcp_server)
|
|
65
|
+
|
|
66
|
+
if not mcp_server_connection:
|
|
67
|
+
return _handle_mcp_tool_error(
|
|
68
|
+
stack,
|
|
69
|
+
initial_events,
|
|
70
|
+
f"Cannot connect to MCP server '{step.mcp_server}'.",
|
|
71
|
+
tool_name=step.call,
|
|
72
|
+
mcp_server=step.mcp_server,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Validate tool availability
|
|
76
|
+
if not await _is_tool_available(mcp_server_connection, step.call):
|
|
77
|
+
return _handle_mcp_tool_error(
|
|
78
|
+
stack,
|
|
79
|
+
initial_events,
|
|
80
|
+
f"Tool '{step.call}' is not available on MCP server "
|
|
81
|
+
f"'{step.mcp_server}'.",
|
|
82
|
+
tool_name=step.call,
|
|
83
|
+
mcp_server=step.mcp_server,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# This should not happen, but we need to check for type checking to pass
|
|
87
|
+
if not step.mapping:
|
|
88
|
+
return _handle_mcp_tool_error(
|
|
89
|
+
stack,
|
|
90
|
+
initial_events,
|
|
91
|
+
f"No mapping found for tool '{step.call}'.",
|
|
92
|
+
tool_name=step.call,
|
|
93
|
+
mcp_server=step.mcp_server,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Prepare arguments for the tool call
|
|
97
|
+
arguments = _prepare_tool_arguments(step.mapping["input"], tracker)
|
|
98
|
+
|
|
99
|
+
# Call the tool with parameters
|
|
100
|
+
mcp_server = await mcp_server_connection.ensure_active_session()
|
|
101
|
+
result = await mcp_server.call_tool(step.call, arguments)
|
|
102
|
+
|
|
103
|
+
# Handle tool execution result
|
|
104
|
+
if result.isError:
|
|
105
|
+
return _handle_mcp_tool_error(
|
|
106
|
+
stack,
|
|
107
|
+
initial_events,
|
|
108
|
+
f"Tool '{step.call}' execution failed: {result.content}.",
|
|
109
|
+
tool_name=step.call,
|
|
110
|
+
mcp_server=step.mcp_server,
|
|
111
|
+
)
|
|
112
|
+
elif not result.content:
|
|
113
|
+
structlogger.warning(
|
|
114
|
+
"call_mcp_tool.empty_tool_result",
|
|
115
|
+
tool_name=step.call,
|
|
116
|
+
mcp_server=step.mcp_server,
|
|
117
|
+
)
|
|
118
|
+
else:
|
|
119
|
+
structlogger.debug(
|
|
120
|
+
"call_mcp_tool.tool_execution_success",
|
|
121
|
+
tool_name=step.call,
|
|
122
|
+
mcp_server=step.mcp_server,
|
|
123
|
+
result_content=result.content,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Process successful result
|
|
127
|
+
set_slot_event = _process_tool_result(result, step.mapping["output"])
|
|
128
|
+
if set_slot_event:
|
|
129
|
+
initial_events.append(set_slot_event)
|
|
130
|
+
|
|
131
|
+
return ContinueFlowWithNextStep(events=initial_events)
|
|
132
|
+
|
|
133
|
+
finally:
|
|
134
|
+
# Always clean up the connection to prevent resource leaks
|
|
135
|
+
if mcp_server_connection:
|
|
136
|
+
try:
|
|
137
|
+
await mcp_server_connection.close()
|
|
138
|
+
except Exception as e:
|
|
139
|
+
structlogger.warning(
|
|
140
|
+
"call_mcp_tool.connection_cleanup_failed",
|
|
141
|
+
tool_name=step.call,
|
|
142
|
+
mcp_server=step.mcp_server,
|
|
143
|
+
error=str(e),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async def _is_tool_available(
|
|
148
|
+
mcp_server_connection: MCPServerConnection, tool_name: str
|
|
149
|
+
) -> bool:
|
|
150
|
+
"""Check if the specified tool is available on the MCP server."""
|
|
151
|
+
try:
|
|
152
|
+
# Get the active session from the connection
|
|
153
|
+
mcp_server = await mcp_server_connection.ensure_active_session()
|
|
154
|
+
available_tools = await mcp_server.list_tools()
|
|
155
|
+
tool_names = [tool.name for tool in available_tools.tools]
|
|
156
|
+
return tool_name in tool_names
|
|
157
|
+
except Exception as e:
|
|
158
|
+
structlogger.warning(
|
|
159
|
+
"call_mcp_tool.tool_availability_check_failed",
|
|
160
|
+
tool_name=tool_name,
|
|
161
|
+
error=str(e),
|
|
162
|
+
)
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
async def _connect_to_mcp_server(
|
|
167
|
+
mcp_server_name: Optional[str],
|
|
168
|
+
) -> Optional[MCPServerConnection]:
|
|
169
|
+
"""Connect to the MCP server."""
|
|
170
|
+
if not mcp_server_name:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
# get the MCP server config from the available endpoints
|
|
174
|
+
endpoints = AvailableEndpoints.get_instance()
|
|
175
|
+
mcp_servers = endpoints.mcp_servers
|
|
176
|
+
if not mcp_servers:
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
mcp_server_configs = [
|
|
180
|
+
mcp_server for mcp_server in mcp_servers if mcp_server.name == mcp_server_name
|
|
181
|
+
]
|
|
182
|
+
if not mcp_server_configs or len(mcp_server_configs) != 1:
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
mcp_server_config = mcp_server_configs[0]
|
|
186
|
+
mcp_server_connection = MCPServerConnection(
|
|
187
|
+
mcp_server_config.name, mcp_server_config.url, mcp_server_config.type
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Ensure the connection is established and return the connection object
|
|
191
|
+
await mcp_server_connection.ensure_active_session()
|
|
192
|
+
return mcp_server_connection
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _prepare_tool_arguments(
|
|
196
|
+
input_mapping: List[Dict[str, str]], tracker: DialogueStateTracker
|
|
197
|
+
) -> Dict[str, Any]:
|
|
198
|
+
"""Prepare arguments for the tool call from slot values."""
|
|
199
|
+
arguments = {}
|
|
200
|
+
for argument in input_mapping:
|
|
201
|
+
slot_value = tracker.get_slot(argument["slot"])
|
|
202
|
+
arguments[argument["param"]] = slot_value
|
|
203
|
+
return arguments
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _process_tool_result(
|
|
207
|
+
result: CallToolResult,
|
|
208
|
+
output_mapping: str,
|
|
209
|
+
) -> Optional[SlotSet]:
|
|
210
|
+
"""Create a SetSlot event for the tool result."""
|
|
211
|
+
try:
|
|
212
|
+
content_as_string = [
|
|
213
|
+
json.dumps(content_part.model_dump()) for content_part in result.content
|
|
214
|
+
]
|
|
215
|
+
return SlotSet(key=output_mapping, value=SEPARATOR.join(content_as_string))
|
|
216
|
+
except Exception as e:
|
|
217
|
+
structlogger.error(
|
|
218
|
+
"call_mcp_tool.result_processing_failed",
|
|
219
|
+
error=str(e),
|
|
220
|
+
result=result,
|
|
221
|
+
)
|
|
222
|
+
return None
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _handle_mcp_tool_error(
|
|
226
|
+
stack: DialogueStack,
|
|
227
|
+
events: List[Event],
|
|
228
|
+
error_message: str,
|
|
229
|
+
tool_name: str,
|
|
230
|
+
mcp_server: Optional[str],
|
|
231
|
+
) -> FlowStepResult:
|
|
232
|
+
"""Handle MCP tool errors consistently."""
|
|
233
|
+
structlogger.error(
|
|
234
|
+
"call_mcp_tool.error",
|
|
235
|
+
error_message=error_message,
|
|
236
|
+
tool_name=tool_name,
|
|
237
|
+
mcp_server=mcp_server,
|
|
238
|
+
)
|
|
239
|
+
stack.push(InternalErrorPatternFlowStackFrame())
|
|
240
|
+
return ContinueFlowWithNextStep(events=events)
|
rasa/core/processor.py
CHANGED
|
@@ -69,6 +69,7 @@ from rasa.shared.constants import (
|
|
|
69
69
|
UTTER_PREFIX,
|
|
70
70
|
)
|
|
71
71
|
from rasa.shared.core.constants import (
|
|
72
|
+
ACTION_AGENT_REQUEST_USER_INPUT_NAME,
|
|
72
73
|
ACTION_CORRECT_FLOW_SLOT,
|
|
73
74
|
ACTION_EXTRACT_SLOTS,
|
|
74
75
|
ACTION_LISTEN_NAME,
|
|
@@ -1194,7 +1195,11 @@ class MessageProcessor:
|
|
|
1194
1195
|
`False` if `action_name` is `ACTION_LISTEN_NAME` or
|
|
1195
1196
|
`ACTION_SESSION_START_NAME`, otherwise `True`.
|
|
1196
1197
|
"""
|
|
1197
|
-
return action_name not in (
|
|
1198
|
+
return action_name not in (
|
|
1199
|
+
ACTION_LISTEN_NAME,
|
|
1200
|
+
ACTION_SESSION_START_NAME,
|
|
1201
|
+
ACTION_AGENT_REQUEST_USER_INPUT_NAME,
|
|
1202
|
+
)
|
|
1198
1203
|
|
|
1199
1204
|
async def execute_side_effects(
|
|
1200
1205
|
self,
|
rasa/core/run.py
CHANGED
|
@@ -30,6 +30,7 @@ from rasa import server, telemetry
|
|
|
30
30
|
from rasa.constants import ENV_SANIC_BACKLOG
|
|
31
31
|
from rasa.core import agent, channels, constants
|
|
32
32
|
from rasa.core.agent import Agent
|
|
33
|
+
from rasa.core.available_agents import AvailableAgents
|
|
33
34
|
from rasa.core.available_endpoints import AvailableEndpoints
|
|
34
35
|
from rasa.core.channels import console
|
|
35
36
|
from rasa.core.channels.channel import InputChannel
|
|
@@ -141,6 +142,7 @@ def configure_app(
|
|
|
141
142
|
route: Optional[Text] = "/webhooks/",
|
|
142
143
|
port: int = constants.DEFAULT_SERVER_PORT,
|
|
143
144
|
endpoints: Optional[AvailableEndpoints] = None,
|
|
145
|
+
sub_agents: Optional[AvailableAgents] = None,
|
|
144
146
|
log_file: Optional[Text] = None,
|
|
145
147
|
conversation_id: Optional[Text] = uuid.uuid4().hex,
|
|
146
148
|
use_syslog: bool = False,
|
|
@@ -169,6 +171,7 @@ def configure_app(
|
|
|
169
171
|
jwt_private_key=jwt_private_key,
|
|
170
172
|
jwt_method=jwt_method,
|
|
171
173
|
endpoints=endpoints,
|
|
174
|
+
sub_agents=sub_agents,
|
|
172
175
|
is_inspector_enabled=is_inspector_enabled,
|
|
173
176
|
)
|
|
174
177
|
)
|
|
@@ -233,6 +236,7 @@ def serve_application(
|
|
|
233
236
|
jwt_private_key: Optional[Text] = None,
|
|
234
237
|
jwt_method: Optional[Text] = None,
|
|
235
238
|
endpoints: Optional[AvailableEndpoints] = None,
|
|
239
|
+
sub_agents: Optional[AvailableAgents] = None,
|
|
236
240
|
remote_storage: Optional[StorageType] = None,
|
|
237
241
|
log_file: Optional[Text] = None,
|
|
238
242
|
ssl_certificate: Optional[Text] = None,
|
|
@@ -273,6 +277,7 @@ def serve_application(
|
|
|
273
277
|
jwt_method,
|
|
274
278
|
port=port,
|
|
275
279
|
endpoints=endpoints,
|
|
280
|
+
sub_agents=sub_agents,
|
|
276
281
|
log_file=log_file,
|
|
277
282
|
conversation_id=conversation_id,
|
|
278
283
|
use_syslog=use_syslog,
|
|
@@ -292,7 +297,7 @@ def serve_application(
|
|
|
292
297
|
logger.info(f"Starting Rasa server on {protocol}://{interface}:{port}")
|
|
293
298
|
|
|
294
299
|
app.register_listener(
|
|
295
|
-
partial(load_agent_on_start, model_path, endpoints, remote_storage),
|
|
300
|
+
partial(load_agent_on_start, model_path, endpoints, remote_storage, sub_agents),
|
|
296
301
|
"before_server_start",
|
|
297
302
|
)
|
|
298
303
|
|
|
@@ -330,6 +335,7 @@ async def load_agent_on_start(
|
|
|
330
335
|
model_path: Text,
|
|
331
336
|
endpoints: AvailableEndpoints,
|
|
332
337
|
remote_storage: Optional[StorageType],
|
|
338
|
+
sub_agents: Optional[AvailableAgents],
|
|
333
339
|
app: Sanic,
|
|
334
340
|
loop: AbstractEventLoop,
|
|
335
341
|
) -> Agent:
|
|
@@ -342,6 +348,7 @@ async def load_agent_on_start(
|
|
|
342
348
|
model_path=model_path,
|
|
343
349
|
remote_storage=remote_storage,
|
|
344
350
|
endpoints=endpoints,
|
|
351
|
+
sub_agents=sub_agents,
|
|
345
352
|
loop=loop,
|
|
346
353
|
)
|
|
347
354
|
|
rasa/core/utils.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from socket import SOCK_DGRAM, SOCK_STREAM
|
|
5
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Text, Tuple, Union
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Text, Tuple, Union
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
8
9
|
import structlog
|
|
@@ -359,3 +360,22 @@ def should_force_slot_filling(
|
|
|
359
360
|
return True, slot_name
|
|
360
361
|
|
|
361
362
|
return False, None
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def get_slot_names_from_exit_conditions(exit_conditions: List[str]) -> List[str]:
|
|
366
|
+
"""Extract slot names from exit conditions.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
exit_conditions: The exit conditions to extract slot names from.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
A list of slot names.
|
|
373
|
+
"""
|
|
374
|
+
# Find all unique names matching "slots.<name>"
|
|
375
|
+
return list(
|
|
376
|
+
{
|
|
377
|
+
name
|
|
378
|
+
for condition in exit_conditions
|
|
379
|
+
for name in re.findall(r"\bslots\.(\w+)", condition)
|
|
380
|
+
}
|
|
381
|
+
)
|
|
@@ -8,6 +8,9 @@ from rasa.dialogue_understanding.commands.chit_chat_answer_command import (
|
|
|
8
8
|
)
|
|
9
9
|
from rasa.dialogue_understanding.commands.clarify_command import ClarifyCommand
|
|
10
10
|
from rasa.dialogue_understanding.commands.command import Command
|
|
11
|
+
from rasa.dialogue_understanding.commands.continue_agent_command import (
|
|
12
|
+
ContinueAgentCommand,
|
|
13
|
+
)
|
|
11
14
|
from rasa.dialogue_understanding.commands.correct_slots_command import (
|
|
12
15
|
CorrectedSlot,
|
|
13
16
|
CorrectSlotsCommand,
|
|
@@ -29,6 +32,9 @@ from rasa.dialogue_understanding.commands.noop_command import NoopCommand
|
|
|
29
32
|
from rasa.dialogue_understanding.commands.repeat_bot_messages_command import (
|
|
30
33
|
RepeatBotMessagesCommand,
|
|
31
34
|
)
|
|
35
|
+
from rasa.dialogue_understanding.commands.restart_agent_command import (
|
|
36
|
+
RestartAgentCommand,
|
|
37
|
+
)
|
|
32
38
|
from rasa.dialogue_understanding.commands.restart_command import RestartCommand
|
|
33
39
|
from rasa.dialogue_understanding.commands.session_end_command import SessionEndCommand
|
|
34
40
|
from rasa.dialogue_understanding.commands.session_start_command import (
|
|
@@ -62,4 +68,6 @@ __all__ = [
|
|
|
62
68
|
"SessionEndCommand",
|
|
63
69
|
"RepeatBotMessagesCommand",
|
|
64
70
|
"RestartCommand",
|
|
71
|
+
"ContinueAgentCommand",
|
|
72
|
+
"RestartAgentCommand",
|
|
65
73
|
]
|
|
@@ -2,10 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import Any, Dict, List
|
|
5
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
6
6
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
9
|
+
from rasa.core.policies.flows.flow_executor import (
|
|
10
|
+
remove_agent_stack_frame,
|
|
11
|
+
)
|
|
9
12
|
from rasa.dialogue_understanding.commands.command import Command
|
|
10
13
|
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
11
14
|
CommandSyntaxManager,
|
|
@@ -13,12 +16,13 @@ from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
|
13
16
|
)
|
|
14
17
|
from rasa.dialogue_understanding.patterns.cancel import CancelPatternFlowStackFrame
|
|
15
18
|
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
19
|
+
from rasa.dialogue_understanding.stack.frames import DialogueStackFrame
|
|
16
20
|
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
|
|
17
21
|
FlowStackFrameType,
|
|
18
22
|
UserFlowStackFrame,
|
|
19
23
|
)
|
|
20
24
|
from rasa.dialogue_understanding.stack.utils import top_user_flow_frame
|
|
21
|
-
from rasa.shared.core.events import Event, FlowCancelled
|
|
25
|
+
from rasa.shared.core.events import AgentCancelled, Event, FlowCancelled
|
|
22
26
|
from rasa.shared.core.flows import FlowsList
|
|
23
27
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
24
28
|
|
|
@@ -48,8 +52,7 @@ class CancelFlowCommand(Command):
|
|
|
48
52
|
"""Selects the frames that were canceled.
|
|
49
53
|
|
|
50
54
|
Args:
|
|
51
|
-
|
|
52
|
-
current_flow: The current flow.
|
|
55
|
+
stack: The dialogue stack.
|
|
53
56
|
|
|
54
57
|
Returns:
|
|
55
58
|
The frames that were canceled.
|
|
@@ -106,6 +109,19 @@ class CancelFlowCommand(Command):
|
|
|
106
109
|
)
|
|
107
110
|
return []
|
|
108
111
|
|
|
112
|
+
if agent_frame := original_tracker.stack.find_active_agent_stack_frame_for_flow(
|
|
113
|
+
current_flow.id
|
|
114
|
+
):
|
|
115
|
+
structlogger.debug(
|
|
116
|
+
"cancel_command.remove_agent_stack_frame",
|
|
117
|
+
command=self,
|
|
118
|
+
frame=agent_frame,
|
|
119
|
+
)
|
|
120
|
+
remove_agent_stack_frame(stack, agent_frame.agent_id)
|
|
121
|
+
applied_events.append(
|
|
122
|
+
AgentCancelled(agent_id=agent_frame.agent_id, flow_id=current_flow.id)
|
|
123
|
+
)
|
|
124
|
+
|
|
109
125
|
# we pass in the original dialogue stack (before any of the currently
|
|
110
126
|
# predicted commands were applied) to make sure we don't cancel any
|
|
111
127
|
# frames that were added by the currently predicted commands.
|
|
@@ -159,3 +175,80 @@ class CancelFlowCommand(Command):
|
|
|
159
175
|
CommandSyntaxManager.get_syntax_version(),
|
|
160
176
|
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
161
177
|
)
|
|
178
|
+
|
|
179
|
+
def cancel_flow(
|
|
180
|
+
self,
|
|
181
|
+
tracker: DialogueStateTracker,
|
|
182
|
+
stack: DialogueStack,
|
|
183
|
+
flow_id: str,
|
|
184
|
+
) -> List[Event]:
|
|
185
|
+
"""Cancels a flow by flow id."""
|
|
186
|
+
applied_events: List[Event] = []
|
|
187
|
+
|
|
188
|
+
frames_to_cancel, user_frame_to_cancel = self._collect_frames_to_cancel(
|
|
189
|
+
stack, flow_id
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# if the flow is not on the stack, do nothing
|
|
193
|
+
if user_frame_to_cancel is None:
|
|
194
|
+
structlogger.error(
|
|
195
|
+
"cancel_flow_command.cancel_flow.no_user_frame_to_cancel",
|
|
196
|
+
command=self,
|
|
197
|
+
)
|
|
198
|
+
return []
|
|
199
|
+
|
|
200
|
+
frames_ids_to_cancel = [frame.frame_id for frame in frames_to_cancel]
|
|
201
|
+
|
|
202
|
+
stack.push(
|
|
203
|
+
CancelPatternFlowStackFrame(
|
|
204
|
+
canceled_name=flow_id,
|
|
205
|
+
canceled_frames=frames_ids_to_cancel,
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# create flow cancelled event
|
|
210
|
+
applied_events.extend(
|
|
211
|
+
[
|
|
212
|
+
FlowCancelled(
|
|
213
|
+
user_frame_to_cancel.flow_id, user_frame_to_cancel.step_id
|
|
214
|
+
),
|
|
215
|
+
]
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
update_stack_events = tracker.create_stack_updated_events(stack)
|
|
219
|
+
|
|
220
|
+
return applied_events + update_stack_events
|
|
221
|
+
|
|
222
|
+
def _collect_frames_to_cancel(
|
|
223
|
+
self, stack: DialogueStack, target_flow_id: str
|
|
224
|
+
) -> Tuple[List[DialogueStackFrame], Optional[UserFlowStackFrame]]:
|
|
225
|
+
"""Collect frames that need to be cancelled.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
stack: The stack to collect frames from.
|
|
229
|
+
target_flow_id: The ID of the flow to cancel.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
A tuple containing (frames_to_cancel, frame_to_cancel).
|
|
233
|
+
"""
|
|
234
|
+
frames_to_cancel: List[DialogueStackFrame] = []
|
|
235
|
+
frame_found = False
|
|
236
|
+
frame_to_cancel = None
|
|
237
|
+
|
|
238
|
+
for frame in stack.frames:
|
|
239
|
+
if isinstance(frame, UserFlowStackFrame) and (
|
|
240
|
+
frame.frame_type == FlowStackFrameType.REGULAR
|
|
241
|
+
or frame.frame_type == FlowStackFrameType.INTERRUPT
|
|
242
|
+
):
|
|
243
|
+
if frame.flow_id == target_flow_id:
|
|
244
|
+
frames_to_cancel.append(frame)
|
|
245
|
+
frame_to_cancel = frame
|
|
246
|
+
frame_found = True
|
|
247
|
+
continue
|
|
248
|
+
elif frame_found:
|
|
249
|
+
break
|
|
250
|
+
|
|
251
|
+
if frame_found:
|
|
252
|
+
frames_to_cancel.append(frame)
|
|
253
|
+
|
|
254
|
+
return list(frames_to_cancel), frame_to_cancel
|
|
@@ -12,6 +12,10 @@ from rasa.dialogue_understanding.commands.free_form_answer_command import (
|
|
|
12
12
|
FreeFormAnswerCommand,
|
|
13
13
|
)
|
|
14
14
|
from rasa.dialogue_understanding.patterns.chitchat import ChitchatPatternFlowStackFrame
|
|
15
|
+
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
|
|
16
|
+
AgentStackFrame,
|
|
17
|
+
AgentState,
|
|
18
|
+
)
|
|
15
19
|
from rasa.shared.core.events import Event
|
|
16
20
|
from rasa.shared.core.flows import FlowsList
|
|
17
21
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -52,6 +56,13 @@ class ChitChatAnswerCommand(FreeFormAnswerCommand):
|
|
|
52
56
|
The events to apply to the tracker.
|
|
53
57
|
"""
|
|
54
58
|
stack = tracker.stack
|
|
59
|
+
|
|
60
|
+
# if the top stack frame is an agent stack frame, we need to
|
|
61
|
+
# update the state to INTERRUPTED
|
|
62
|
+
if top_stack_frame := stack.top():
|
|
63
|
+
if isinstance(top_stack_frame, AgentStackFrame):
|
|
64
|
+
top_stack_frame.state = AgentState.INTERRUPTED
|
|
65
|
+
|
|
55
66
|
stack.push(ChitchatPatternFlowStackFrame())
|
|
56
67
|
return tracker.create_stack_updated_events(stack)
|
|
57
68
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Dict, List
|
|
6
|
+
|
|
7
|
+
import structlog
|
|
8
|
+
|
|
9
|
+
from rasa.dialogue_understanding.commands.command import Command
|
|
10
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
11
|
+
CommandSyntaxManager,
|
|
12
|
+
CommandSyntaxVersion,
|
|
13
|
+
)
|
|
14
|
+
from rasa.shared.core.events import Event
|
|
15
|
+
from rasa.shared.core.flows import FlowsList
|
|
16
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
17
|
+
|
|
18
|
+
structlogger = structlog.get_logger()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ContinueAgentCommand(Command):
|
|
23
|
+
"""A command to continue the currently active agent's execution."""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def command(cls) -> str:
|
|
27
|
+
"""Returns the command type."""
|
|
28
|
+
return "continue agent"
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def from_dict(cls, data: Dict[str, Any]) -> ContinueAgentCommand:
|
|
32
|
+
"""Converts the dictionary to a command.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The converted dictionary.
|
|
36
|
+
"""
|
|
37
|
+
return ContinueAgentCommand()
|
|
38
|
+
|
|
39
|
+
def run_command_on_tracker(
|
|
40
|
+
self,
|
|
41
|
+
tracker: DialogueStateTracker,
|
|
42
|
+
all_flows: FlowsList,
|
|
43
|
+
original_tracker: DialogueStateTracker,
|
|
44
|
+
) -> List[Event]:
|
|
45
|
+
"""Runs the command on the tracker.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
tracker: The tracker to run the command on.
|
|
49
|
+
all_flows: All flows in the assistant.
|
|
50
|
+
original_tracker: The tracker before any command was executed.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
The events to apply to the tracker.
|
|
54
|
+
"""
|
|
55
|
+
# do nothing
|
|
56
|
+
return []
|
|
57
|
+
|
|
58
|
+
def __hash__(self) -> int:
|
|
59
|
+
return hash(self.command())
|
|
60
|
+
|
|
61
|
+
def __eq__(self, other: object) -> bool:
|
|
62
|
+
return isinstance(other, ContinueAgentCommand)
|
|
63
|
+
|
|
64
|
+
def to_dsl(self) -> str:
|
|
65
|
+
"""Converts the command to a DSL string."""
|
|
66
|
+
mapper = {
|
|
67
|
+
CommandSyntaxVersion.v1: "ContinueAgent()",
|
|
68
|
+
CommandSyntaxVersion.v2: "continue agent",
|
|
69
|
+
CommandSyntaxVersion.v3: "continue agent",
|
|
70
|
+
}
|
|
71
|
+
return mapper.get(
|
|
72
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
73
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dsl(cls, match: re.Match, **kwargs: Any) -> ContinueAgentCommand:
|
|
78
|
+
"""Converts a DSL string to a command."""
|
|
79
|
+
return ContinueAgentCommand()
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def regex_pattern() -> str:
|
|
83
|
+
mapper = {
|
|
84
|
+
CommandSyntaxVersion.v1: r"ContinueAgent\(\)",
|
|
85
|
+
CommandSyntaxVersion.v2: r"""^[\s\W\d]*continue agent['"`]*$""",
|
|
86
|
+
CommandSyntaxVersion.v3: r"""^[\s\W\d]*continue agent['"`]*$""",
|
|
87
|
+
}
|
|
88
|
+
return mapper.get(
|
|
89
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
90
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
91
|
+
)
|
|
@@ -12,6 +12,10 @@ from rasa.dialogue_understanding.commands.free_form_answer_command import (
|
|
|
12
12
|
FreeFormAnswerCommand,
|
|
13
13
|
)
|
|
14
14
|
from rasa.dialogue_understanding.patterns.search import SearchPatternFlowStackFrame
|
|
15
|
+
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
|
|
16
|
+
AgentStackFrame,
|
|
17
|
+
AgentState,
|
|
18
|
+
)
|
|
15
19
|
from rasa.shared.core.events import Event
|
|
16
20
|
from rasa.shared.core.flows import FlowsList
|
|
17
21
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -52,6 +56,13 @@ class KnowledgeAnswerCommand(FreeFormAnswerCommand):
|
|
|
52
56
|
The events to apply to the tracker.
|
|
53
57
|
"""
|
|
54
58
|
stack = tracker.stack
|
|
59
|
+
|
|
60
|
+
# if the top stack frame is an agent stack frame, we need to
|
|
61
|
+
# update the state to INTERRUPTED
|
|
62
|
+
if top_stack_frame := stack.top():
|
|
63
|
+
if isinstance(top_stack_frame, AgentStackFrame):
|
|
64
|
+
top_stack_frame.state = AgentState.INTERRUPTED
|
|
65
|
+
|
|
55
66
|
stack.push(SearchPatternFlowStackFrame())
|
|
56
67
|
return tracker.create_stack_updated_events(stack)
|
|
57
68
|
|