From b5b5d499e55ad3f293af3759dc25dba560484c47 Mon Sep 17 00:00:00 2001 From: Junyan Qin Date: Thu, 11 Dec 2025 18:54:16 +0800 Subject: [PATCH] feat: add back streaming switch for web chat --- .../pkg/platform/sources/websocket_adapter.py | 16 +++++++++++++--- .../components/debug-dialog/DebugDialog.tsx | 17 +++++++++++++++-- web/src/app/infra/websocket/WebSocketClient.ts | 2 ++ web/src/i18n/locales/en-US.ts | 1 + web/src/i18n/locales/ja-JP.ts | 1 + web/src/i18n/locales/zh-Hans.ts | 1 + web/src/i18n/locales/zh-Hant.ts | 1 + 7 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/langbot/pkg/platform/sources/websocket_adapter.py b/src/langbot/pkg/platform/sources/websocket_adapter.py index 53ff681e..238276ee 100644 --- a/src/langbot/pkg/platform/sources/websocket_adapter.py +++ b/src/langbot/pkg/platform/sources/websocket_adapter.py @@ -65,6 +65,10 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter) outbound_message_queue: asyncio.Queue = pydantic.Field(default_factory=asyncio.Queue, exclude=True) """后端主动推送消息的队列""" + # 流式输出开关 + stream_enabled: bool = pydantic.Field(default=True, exclude=True) + """是否启用流式输出""" + def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger, **kwargs): super().__init__( config=config, @@ -77,6 +81,7 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter) self.bot_account_id = 'websocketbot' self.outbound_message_queue = asyncio.Queue() + self.stream_enabled = True async def send_message( self, @@ -212,8 +217,8 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter) return message_data.model_dump() async def is_stream_output_supported(self) -> bool: - """WebSocket始终支持流式输出""" - return True + """根据stream_enabled标志返回是否支持流式输出""" + return self.stream_enabled def register_listener( self, @@ -314,11 +319,16 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter) Args: connection: WebSocket连接对象 - message_data: 消息数据 + message_data: 消息数据,包含: + - message: 消息链 + - stream: 是否启用流式输出 (可选,默认True) """ pipeline_uuid = connection.pipeline_uuid session_type = connection.session_type + # 获取stream参数,默认为True + self.stream_enabled = message_data.get('stream', True) + # 选择会话 use_session = self.websocket_group_session if session_type == 'group' else self.websocket_person_session diff --git a/web/src/app/home/pipelines/components/debug-dialog/DebugDialog.tsx b/web/src/app/home/pipelines/components/debug-dialog/DebugDialog.tsx index 9657358a..e4ff4941 100644 --- a/web/src/app/home/pipelines/components/debug-dialog/DebugDialog.tsx +++ b/web/src/app/home/pipelines/components/debug-dialog/DebugDialog.tsx @@ -5,6 +5,7 @@ import { DialogContent } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { ScrollArea } from '@/components/ui/scroll-area'; +import { Switch } from '@/components/ui/switch'; import { cn } from '@/lib/utils'; import { Message, @@ -60,6 +61,7 @@ export default function DebugDialog({ const [rawModeMessages, setRawModeMessages] = useState>( new Set(), ); + const [streamOutput, setStreamOutput] = useState(true); const messagesEndRef = useRef(null); const inputRef = useRef(null); const popoverRef = useRef(null); @@ -384,7 +386,7 @@ export default function DebugDialog({ // 通过WebSocket发送消息 // 不在本地添加消息,等待后端广播回来(带有正确的ID) - wsClientRef.current.sendMessage(messageChain); + wsClientRef.current.sendMessage(messageChain, streamOutput); } catch (error) { console.error('Failed to send message:', error); toast.error(t('pipelines.debugDialog.sendFailed')); @@ -897,7 +899,18 @@ export default function DebugDialog({ )}
-
+
+
+ + {t('pipelines.debugDialog.streamOutput')} + + +
, + stream: boolean = true, ) { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { throw new Error('WebSocket未连接'); @@ -212,6 +213,7 @@ export class WebSocketClient { const message = { type: 'message', message: messageChain, + stream: stream, }; this.ws.send(JSON.stringify(message)); diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index 8bacc613..dc4120c5 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -535,6 +535,7 @@ const enUS = { loadPipelinesFailed: 'Failed to load pipelines', atTips: 'Mention the bot', streaming: 'Streaming', + streamOutput: 'Stream', connected: 'WebSocket connected', disconnected: 'WebSocket disconnected', connectionError: 'WebSocket connection error', diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index 3a06d3a3..d96cc0cd 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -538,6 +538,7 @@ const jaJP = { loadPipelinesFailed: 'パイプラインの読み込みに失敗しました', atTips: 'ボットをメンション', streaming: 'ストリーミング', + streamOutput: 'ストリーム', connected: 'WebSocket接続済み', disconnected: 'WebSocket未接続', connectionError: 'WebSocket接続エラー', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index fdcecf54..c1e9815e 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -517,6 +517,7 @@ const zhHans = { loadPipelinesFailed: '加载流水线失败', atTips: '提及机器人', streaming: '流式传输', + streamOutput: '流式', connected: 'WebSocket已连接', disconnected: 'WebSocket未连接', connectionError: 'WebSocket连接错误', diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts index 7c76fb5d..d55cc17c 100644 --- a/web/src/i18n/locales/zh-Hant.ts +++ b/web/src/i18n/locales/zh-Hant.ts @@ -515,6 +515,7 @@ const zhHant = { loadPipelinesFailed: '載入流程線失敗', atTips: '提及機器人', streaming: '串流傳輸', + streamOutput: '串流', connected: 'WebSocket已連接', disconnected: 'WebSocket未連接', connectionError: 'WebSocket連接錯誤',