mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-06-10 09:25:57 +00:00
fix(channels): preserve Feishu clarification thread continuity (#3285)
* fix(channels): preserve Feishu clarification thread continuity * fix(channels): address Feishu clarification review feedback --------- Co-authored-by: zzp1221 <zzp1221@users.noreply.github.com> Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
@@ -15,7 +15,14 @@ import httpx
|
||||
from langgraph_sdk.errors import ConflictError
|
||||
|
||||
from app.channels.commands import KNOWN_CHANNEL_COMMANDS
|
||||
from app.channels.message_bus import InboundMessage, InboundMessageType, MessageBus, OutboundMessage, ResolvedAttachment
|
||||
from app.channels.message_bus import (
|
||||
PENDING_CLARIFICATION_METADATA_KEY,
|
||||
InboundMessage,
|
||||
InboundMessageType,
|
||||
MessageBus,
|
||||
OutboundMessage,
|
||||
ResolvedAttachment,
|
||||
)
|
||||
from app.channels.store import ChannelStore
|
||||
from app.gateway.csrf_middleware import CSRF_COOKIE_NAME, CSRF_HEADER_NAME, generate_csrf_token
|
||||
from app.gateway.internal_auth import create_internal_auth_headers
|
||||
@@ -202,6 +209,54 @@ def _extract_response_text(result: dict | list) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def _messages_from_result(result: dict | list) -> list[Any]:
|
||||
if isinstance(result, list):
|
||||
return result
|
||||
if isinstance(result, dict):
|
||||
messages = result.get("messages", [])
|
||||
if isinstance(messages, list):
|
||||
return messages
|
||||
return []
|
||||
|
||||
|
||||
def _current_turn_messages(result: dict | list) -> list[dict[str, Any]]:
|
||||
messages = _messages_from_result(result)
|
||||
current_turn: list[dict[str, Any]] = []
|
||||
for msg in reversed(messages):
|
||||
if not isinstance(msg, dict):
|
||||
continue
|
||||
if msg.get("type") == "human":
|
||||
break
|
||||
current_turn.append(msg)
|
||||
current_turn.reverse()
|
||||
return current_turn
|
||||
|
||||
|
||||
def _has_current_turn_clarification(result: dict | list) -> bool:
|
||||
"""Return True only when the current turn's final result is clarification."""
|
||||
for msg in reversed(_current_turn_messages(result)):
|
||||
msg_type = msg.get("type")
|
||||
if msg_type == "tool":
|
||||
return msg.get("name") == "ask_clarification"
|
||||
if msg_type == "ai":
|
||||
content = msg.get("content")
|
||||
if isinstance(content, str):
|
||||
if content:
|
||||
return False
|
||||
elif content:
|
||||
return False
|
||||
if msg.get("tool_calls"):
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def _response_metadata(base_metadata: dict[str, Any], *, pending_clarification: bool = False) -> dict[str, Any]:
|
||||
metadata = _slim_metadata(base_metadata)
|
||||
if pending_clarification:
|
||||
metadata[PENDING_CLARIFICATION_METADATA_KEY] = True
|
||||
return metadata
|
||||
|
||||
|
||||
def _extract_text_content(content: Any) -> str:
|
||||
"""Extract text from a streaming payload content field."""
|
||||
if isinstance(content, str):
|
||||
@@ -806,6 +861,7 @@ class ChannelManager:
|
||||
raise
|
||||
|
||||
response_text = _extract_response_text(result)
|
||||
pending_clarification = _has_current_turn_clarification(result)
|
||||
artifacts = _extract_artifacts(result)
|
||||
|
||||
logger.info(
|
||||
@@ -831,7 +887,7 @@ class ChannelManager:
|
||||
artifacts=artifacts,
|
||||
attachments=attachments,
|
||||
thread_ts=msg.thread_ts,
|
||||
metadata=_slim_metadata(msg.metadata),
|
||||
metadata=_response_metadata(msg.metadata, pending_clarification=pending_clarification),
|
||||
)
|
||||
logger.info("[Manager] publishing outbound message to bus: channel=%s, chat_id=%s", msg.channel_name, msg.chat_id)
|
||||
await self.bus.publish_outbound(outbound)
|
||||
@@ -893,7 +949,7 @@ class ChannelManager:
|
||||
text=latest_text,
|
||||
is_final=False,
|
||||
thread_ts=msg.thread_ts,
|
||||
metadata=_slim_metadata(msg.metadata),
|
||||
metadata=_response_metadata(msg.metadata),
|
||||
)
|
||||
)
|
||||
last_published_text = latest_text
|
||||
@@ -907,6 +963,7 @@ class ChannelManager:
|
||||
finally:
|
||||
result = last_values if last_values is not None else {"messages": [{"type": "ai", "content": latest_text}]}
|
||||
response_text = _extract_response_text(result)
|
||||
pending_clarification = _has_current_turn_clarification(result)
|
||||
artifacts = _extract_artifacts(result)
|
||||
response_text, attachments = _prepare_artifact_delivery(thread_id, response_text, artifacts)
|
||||
|
||||
@@ -938,7 +995,7 @@ class ChannelManager:
|
||||
attachments=attachments,
|
||||
is_final=True,
|
||||
thread_ts=msg.thread_ts,
|
||||
metadata=_slim_metadata(msg.metadata),
|
||||
metadata=_response_metadata(msg.metadata, pending_clarification=pending_clarification),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user