Node.js版BotBuilder Teams机器人流式响应上下文丢失问题求助
解决Teams Bot流式返回时上下文丢失的问题
问题原因
BotBuilder的TurnContext生命周期绑定当前对话轮次,当主代码执行完(注册完流回调后,当前turn的处理流程结束),框架会自动回收上下文资源,后续流触发异步回调时,原上下文已失效,导致"已撤销"的错误。
解决方案
通过保存对话引用(ConversationReference),在流回调中借助BotAdapter重新创建有效上下文,同时调整消息发送逻辑:
- 保存对话引用:在当前有效上下文阶段,提取对话的引用信息
- 借助Adapter创建新上下文:在流回调中使用
adapter.continueConversation发起新的对话轮次,获取可用的上下文 - 调整消息处理逻辑:可以选择发送新消息累加内容,或先发送初始消息再逐步更新
修改后的代码示例
// 从当前上下文获取BotAdapter实例 const adapter = context.adapter; try { const data = await postDataToEndpoint(url, reqBody, headers); // 保存对话引用,用于后续创建新上下文 const conversationReference = TurnContext.getConversationReference(context.activity); // 发送初始加载提示,若需要更新消息则保存消息ID const initialMessage = await context.sendActivity(MessageFactory.text('正在处理,请稍候...')); const initialMessageId = initialMessage.id; let payloadText = ''; console.log('外部上下文有效: ', context); data.on('data', async (chunk) => { try { // 累加流式返回的文本块 payloadText += chunk.toString(); // 通过adapter重新创建上下文,发起新的对话轮次 await adapter.continueConversation(conversationReference, async (newContext) => { // 方案1:更新初始消息,替换为当前累加的文本 await newContext.updateActivity({ id: initialMessageId, text: payloadText, type: 'message', conversation: conversationReference.conversation }); // 方案2:直接发送新的文本块(适合分段展示) // await newContext.sendActivity(MessageFactory.text(chunk.toString())); }); } catch (streamErr) { console.error('流处理错误: ', streamErr); } }); // 监听流结束事件 data.on('end', async () => { await adapter.continueConversation(conversationReference, async (newContext) => { // 流结束后可以发送完成提示 await newContext.sendActivity(MessageFactory.text('处理完成!')); }); }); // 监听流错误事件 data.on('error', async (err) => { await adapter.continueConversation(conversationReference, async (newContext) => { const errorCardData: ErrorCardData = { error: err.message }; const errorCardJson = AdaptiveCards.declare(errorCard).render(errorCardData); await newContext.sendActivity( MessageFactory.attachment(CardFactory.adaptiveCard(errorCardJson)) ); }); }); } catch (err) { const errorCardData: ErrorCardData = { error: err.message }; const errorCardJson = AdaptiveCards.declare(errorCard).render(errorCardData); await context.sendActivity( MessageFactory.attachment(CardFactory.adaptiveCard(errorCardJson)) ); await next(); }
关键注意点
- 不要在流回调中直接使用原
TurnContext,必须通过ConversationReference和adapter.continueConversation创建新上下文 - 流回调中的异步操作要包裹try/catch,避免未处理的Promise错误
- 若选择更新消息,需确保初始消息ID正确传递,且对话引用的conversation信息完整
- 无需在流回调中调用
next(),因为当前中间件的处理流程已在主代码执行完后结束
内容的提问来源于stack exchange,提问作者Dale
相关产品推荐
相关产品推荐

