优化: 会话状态 per-conv 化与交互守卫
- 待审批跨会话 per-conv 合并,审批类事件全局放行 - 看门狗/重试计数/流式残段按会话键控迁移 - 输入草稿与子代理完成卡数据按会话隔离 - 切换兜底 activeId,收敛守卫防幽灵气泡 - 发送错误按限流/额度/网络分类文案
This commit is contained in:
@@ -9,9 +9,9 @@ import { emit } from '@tauri-apps/api/event'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { state } from '@/stores/ai'
|
||||
import { t } from '@/i18n/i18n-helpers'
|
||||
import { nextMsgId, convStates, clearApprovalTimer, flushCurrentText, clearAllToolSlowTimers, friendlyError, notifyConversationChanged } from './aiShared'
|
||||
import { nextMsgId, convStates, clearApprovalTimer, flushCurrentText, clearAllToolSlowTimers, friendlyError, notifyConversationChanged, clearLastDelta, discardConvPendingApprovals } from './aiShared'
|
||||
import { clearTextIdleTimer, pendingMaxRounds, pendingHelp, pendingDirAuths } from './useAiPendingState'
|
||||
import { clearStreamWatchdog } from './useAiStream'
|
||||
import { clearStreamWatchdog, clearResumeAttempts } from './useAiStream'
|
||||
import { setStreaming } from './streamingGuard'
|
||||
import type { AiChatEvent, AiMessage, MessageId } from '@/api/types'
|
||||
|
||||
@@ -52,6 +52,12 @@ function isShowTokenUsage(): boolean {
|
||||
*/
|
||||
function cleanupTerminatedConversation(convId: string, reason: 'AiCompleted' | 'AiError' | 'AiHelpRequired') {
|
||||
clearStreamWatchdog(convId || undefined)
|
||||
// 正常收尾路径清该会话的 delta 去重记录:flushCurrentText 只清活跃会话的,这里按 convId
|
||||
// 显式清一遍兜住 convId 与 active 不一致或事件缺 convId 的时序,防残留记录误丢下轮同内容 delta
|
||||
clearLastDelta(convId || undefined)
|
||||
// 正常收尾清自动续跑计数:计数只服务于单轮内连续超时的风暴防护,终态后必须归零,
|
||||
// 否则陈旧计数会让下一轮的正常超时提前触发强制收敛(清零只放收尾路径,不在发消息时清)
|
||||
clearResumeAttempts(convId || undefined)
|
||||
clearAllToolSlowTimers() // 整轮/错误/求助结束清全部工具慢执行计时器与已提示集合
|
||||
clearTextIdleTimer() // 清文本空闲定时器 + 置 textIdle=true(整轮结束不该有活跃信号残留)
|
||||
flushCurrentText()
|
||||
@@ -86,6 +92,9 @@ function cleanupTerminatedConversation(convId: string, reason: 'AiCompleted' | '
|
||||
const removedApprovals = state.pendingApprovals.filter(p => p.conversationId === convId)
|
||||
state.pendingApprovals = state.pendingApprovals.filter(p => !p.conversationId || p.conversationId !== convId)
|
||||
for (const p of removedApprovals) clearApprovalTimer(p.id)
|
||||
// 本会话已终止,其 per-conv 挂起集合作废(仅删集合项,视图保留上面无法归属的旧项;
|
||||
// 切回该会话时由 pendingToolCalls 从后端审计表按需重建)
|
||||
discardConvPendingApprovals(convId || undefined)
|
||||
// 清分离窗口生成态快照(per-conv key,清本会话;兼容旧单 key)
|
||||
if (convId) {
|
||||
localStorage.removeItem(`df-ai-gen-${convId}`)
|
||||
@@ -102,12 +111,14 @@ export function handleLifecycleEvent(event: AiChatEvent): boolean {
|
||||
console.warn('[FE-AICOMPLETED] 收到 conv=', event.conversation_id, 'streaming=', state.streaming)
|
||||
cleanupTerminatedConversation(event.conversation_id || '', 'AiCompleted')
|
||||
console.warn('[FE-AICOMPLETED] cleanup 后 streaming=', state.streaming)
|
||||
// 流中途失败保文:后端 emit AiCompleted(incomplete=true),前端追加系统提示气泡
|
||||
// 流中途失败保文:后端 emit AiCompleted(incomplete=true),前端追加系统提示气泡。
|
||||
// incomplete_reason 细分文案:"max_rounds"=达上限自动收尾(非网络中断,语义不同),
|
||||
// 其他/缺省=网络中断等异常走原提示。
|
||||
if (event.incomplete) {
|
||||
state.messages.push({
|
||||
id: `incomplete-${nextMsgId()}` as MessageId,
|
||||
role: 'assistant',
|
||||
content: t('ai.responseIncomplete'),
|
||||
content: event.incomplete_reason === 'max_rounds' ? t('ai.responseIncompleteMaxRounds') : t('ai.responseIncomplete'),
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user