fix: delay tool blocks until text fully streamed
This commit is contained in:
parent
6d330b1388
commit
55af5b52c6
@ -37,6 +37,32 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
ignoreThinking: false
|
||||
};
|
||||
|
||||
const pendingToolEvents: Array<{ event: string; data: any; handler: () => void }> = [];
|
||||
|
||||
const hasPendingStreamingText = () =>
|
||||
!!streamingState.buffer.length ||
|
||||
!!streamingState.pendingCompleteContent ||
|
||||
streamingState.timer !== null ||
|
||||
streamingState.completionTimer !== null;
|
||||
|
||||
const resetPendingToolEvents = () => {
|
||||
pendingToolEvents.length = 0;
|
||||
};
|
||||
|
||||
const flushPendingToolEvents = () => {
|
||||
if (!pendingToolEvents.length) {
|
||||
return;
|
||||
}
|
||||
const queue = pendingToolEvents.splice(0);
|
||||
queue.forEach((item) => {
|
||||
try {
|
||||
item.handler();
|
||||
} catch (error) {
|
||||
console.warn('延后工具事件处理失败:', item.event, error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const snapshotStreamingState = () => ({
|
||||
bufferLength: streamingState.buffer.length,
|
||||
timerActive: streamingState.timer !== null,
|
||||
@ -297,6 +323,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
streamingState.activeMessageIndex = null;
|
||||
streamingState.activeTextAction = null;
|
||||
markStreamingIdleIfPossible('finalizeStreamingText');
|
||||
flushPendingToolEvents();
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -326,6 +353,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
streamingState.renderedText = '';
|
||||
streamingState.activeMessageIndex = null;
|
||||
streamingState.activeTextAction = null;
|
||||
resetPendingToolEvents();
|
||||
logStreamingDebug('resetStreamingBuffer', snapshotStreamingState());
|
||||
};
|
||||
|
||||
@ -658,6 +686,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('AI消息开始');
|
||||
logStreamingDebug('socket:ai_message_start');
|
||||
finalizeStreamingText({ force: true });
|
||||
flushPendingToolEvents();
|
||||
resetStreamingBuffer();
|
||||
ctx.monitorResetSpeech();
|
||||
ctx.cleanupStaleToolActions();
|
||||
@ -807,6 +836,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('跳过tool_preparing(对话不匹配)', data.conversation_id);
|
||||
return;
|
||||
}
|
||||
const handler = () => {
|
||||
const msg = ctx.chatEnsureAssistantMessage();
|
||||
if (!msg) {
|
||||
return;
|
||||
@ -832,10 +862,16 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
ctx.toolTrackAction(data.name, action);
|
||||
ctx.$forceUpdate();
|
||||
ctx.conditionalScrollToBottom();
|
||||
// 虚拟显示器:在模型检测到工具时立即展示“正在XX”预览
|
||||
if (ctx.monitorPreviewTool) {
|
||||
ctx.monitorPreviewTool(data);
|
||||
}
|
||||
};
|
||||
|
||||
if (hasPendingStreamingText()) {
|
||||
pendingToolEvents.push({ event: 'tool_preparing', data, handler });
|
||||
} else {
|
||||
handler();
|
||||
}
|
||||
});
|
||||
|
||||
// 工具状态更新事件 - 实时显示详细状态
|
||||
@ -868,6 +904,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('跳过tool_start(对话不匹配)', data.conversation_id);
|
||||
return;
|
||||
}
|
||||
const handler = () => {
|
||||
let action = null;
|
||||
if (data.preparing_id && ctx.preparingTools.has(data.preparing_id)) {
|
||||
action = ctx.preparingTools.get(data.preparing_id);
|
||||
@ -908,6 +945,13 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
ctx.$forceUpdate();
|
||||
ctx.conditionalScrollToBottom();
|
||||
ctx.monitorQueueTool(data);
|
||||
};
|
||||
|
||||
if (hasPendingStreamingText()) {
|
||||
pendingToolEvents.push({ event: 'tool_start', data, handler });
|
||||
} else {
|
||||
handler();
|
||||
}
|
||||
});
|
||||
|
||||
// 更新action(工具完成)
|
||||
@ -917,6 +961,7 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('跳过update_action(对话不匹配)', data.conversation_id);
|
||||
return;
|
||||
}
|
||||
const handler = () => {
|
||||
let targetAction = ctx.toolFindAction(data.id, data.preparing_id, data.execution_id);
|
||||
if (!targetAction && data.preparing_id && ctx.preparingTools.has(data.preparing_id)) {
|
||||
targetAction = ctx.preparingTools.get(data.preparing_id);
|
||||
@ -981,7 +1026,6 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
ctx.conditionalScrollToBottom();
|
||||
}
|
||||
|
||||
// 关键修复:每个工具完成后都更新当前上下文Token
|
||||
if (data.status === 'completed') {
|
||||
setTimeout(() => {
|
||||
ctx.updateCurrentContextTokens();
|
||||
@ -993,6 +1037,13 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
}
|
||||
}
|
||||
ctx.monitorResolveTool(data);
|
||||
};
|
||||
|
||||
if (hasPendingStreamingText()) {
|
||||
pendingToolEvents.push({ event: 'update_action', data, handler });
|
||||
} else {
|
||||
handler();
|
||||
}
|
||||
});
|
||||
|
||||
ctx.socket.on('append_payload', (data) => {
|
||||
@ -1046,6 +1097,8 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('任务完成', data);
|
||||
ctx.scheduleResetAfterTask('socket:task_complete', { preserveMonitorWindows: true });
|
||||
|
||||
resetPendingToolEvents();
|
||||
|
||||
// 任务完成后立即更新Token统计(关键修复)
|
||||
if (ctx.currentConversationId) {
|
||||
ctx.updateCurrentContextTokens();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user