mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-11 06:28:58 +00:00
fix(dingtalk): strip leading mentions before command classification (#4724)
Group @bot /command messages are classified as commands like Feishu.
This commit is contained in:
parent
7b57609656
commit
e16ef2969b
@ -14,7 +14,7 @@ from typing import Any
|
|||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from app.channels.base import Channel
|
from app.channels.base import Channel
|
||||||
from app.channels.commands import is_known_channel_command
|
from app.channels.commands import is_known_channel_command, strip_leading_mentions
|
||||||
from app.channels.connection_identity import attach_connection_identity
|
from app.channels.connection_identity import attach_connection_identity
|
||||||
from app.channels.message_bus import InboundMessage, InboundMessageType, MessageBus, OutboundMessage, ResolvedAttachment
|
from app.channels.message_bus import InboundMessage, InboundMessageType, MessageBus, OutboundMessage, ResolvedAttachment
|
||||||
from deerflow.config.paths import VIRTUAL_PATH_PREFIX, get_paths
|
from deerflow.config.paths import VIRTUAL_PATH_PREFIX, get_paths
|
||||||
@ -428,8 +428,16 @@ class DingTalkChannel(Channel):
|
|||||||
len(files),
|
len(files),
|
||||||
)
|
)
|
||||||
|
|
||||||
if _is_dingtalk_command(text):
|
# DingTalk group chats often deliver "@bot /new" with the mention left
|
||||||
|
# in the text (Slack/Discord strip their own bot mention upstream).
|
||||||
|
# Skip a leading mention only for the command path so ordinary chat
|
||||||
|
# keeps @mentions intact for the agent; the stripped form also flows
|
||||||
|
# into the inbound so ChannelManager._handle_command parses the bare
|
||||||
|
# command. Mirrors FeishuChannel.
|
||||||
|
command_text = strip_leading_mentions(text)
|
||||||
|
if _is_dingtalk_command(command_text):
|
||||||
msg_type = InboundMessageType.COMMAND
|
msg_type = InboundMessageType.COMMAND
|
||||||
|
text = command_text
|
||||||
else:
|
else:
|
||||||
msg_type = InboundMessageType.CHAT
|
msg_type = InboundMessageType.CHAT
|
||||||
|
|
||||||
|
|||||||
@ -304,6 +304,71 @@ class TestOnChatbotMessage:
|
|||||||
|
|
||||||
_run(go())
|
_run(go())
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("text", ["@bot /new", "@_user_1 /help", "@bot /goal ship it"])
|
||||||
|
def test_leading_mention_before_command_classifies_and_strips(self, text):
|
||||||
|
"""DingTalk group chats leave "@bot /new" in the text; classify as COMMAND
|
||||||
|
and strip the mention so ChannelManager receives the bare command."""
|
||||||
|
|
||||||
|
async def go():
|
||||||
|
bus = MessageBus()
|
||||||
|
bus.publish_inbound = AsyncMock()
|
||||||
|
channel = DingTalkChannel(bus, config={})
|
||||||
|
channel._client_id = "test_key"
|
||||||
|
channel._main_loop = asyncio.get_event_loop()
|
||||||
|
channel._running = True
|
||||||
|
|
||||||
|
msg = _make_chatbot_message(
|
||||||
|
text=text,
|
||||||
|
conversation_type=_CONVERSATION_TYPE_GROUP,
|
||||||
|
sender_staff_id="user_002",
|
||||||
|
conversation_id="conv_group_001",
|
||||||
|
message_id="msg_mention_cmd",
|
||||||
|
)
|
||||||
|
|
||||||
|
channel._send_running_reply = AsyncMock()
|
||||||
|
channel._on_chatbot_message(msg)
|
||||||
|
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
bus.publish_inbound.assert_awaited_once()
|
||||||
|
inbound = bus.publish_inbound.await_args.args[0]
|
||||||
|
assert inbound.msg_type == InboundMessageType.COMMAND, f"{text!r} should be COMMAND"
|
||||||
|
assert not inbound.text.startswith("@"), "leading mention must be stripped for dispatch"
|
||||||
|
assert inbound.text.split(maxsplit=1)[0] in KNOWN_CHANNEL_COMMANDS
|
||||||
|
|
||||||
|
_run(go())
|
||||||
|
|
||||||
|
def test_leading_mention_before_chat_keeps_mention(self):
|
||||||
|
"""A mentioned non-command stays CHAT and keeps the mention for the agent."""
|
||||||
|
|
||||||
|
async def go():
|
||||||
|
bus = MessageBus()
|
||||||
|
bus.publish_inbound = AsyncMock()
|
||||||
|
channel = DingTalkChannel(bus, config={})
|
||||||
|
channel._client_id = "test_key"
|
||||||
|
channel._main_loop = asyncio.get_event_loop()
|
||||||
|
channel._running = True
|
||||||
|
|
||||||
|
msg = _make_chatbot_message(
|
||||||
|
text="@bot please summarise this",
|
||||||
|
conversation_type=_CONVERSATION_TYPE_GROUP,
|
||||||
|
sender_staff_id="user_002",
|
||||||
|
conversation_id="conv_group_001",
|
||||||
|
message_id="msg_mention_chat",
|
||||||
|
)
|
||||||
|
|
||||||
|
channel._send_running_reply = AsyncMock()
|
||||||
|
channel._on_chatbot_message(msg)
|
||||||
|
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
bus.publish_inbound.assert_awaited_once()
|
||||||
|
inbound = bus.publish_inbound.await_args.args[0]
|
||||||
|
assert inbound.msg_type == InboundMessageType.CHAT
|
||||||
|
assert inbound.text == "@bot please summarise this"
|
||||||
|
|
||||||
|
_run(go())
|
||||||
|
|
||||||
def test_group_message_integer_conversation_type_normalized(self):
|
def test_group_message_integer_conversation_type_normalized(self):
|
||||||
"""SDK may deliver conversationType as int 2 — must still route as group."""
|
"""SDK may deliver conversationType as int 2 — must still route as group."""
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user