修复: DeepSeek 400 全量扫描 + 队列 per-conv 隔离

- openai_compat: 扫描所有 assistant 消息剥离 orphan tool_calls(原仅查末条)
- queue 加 conversationId 字段,按会话精准 drain
- regenerate/editMessage 只清本会话排队消息
- newConversation 保留旧会话排队消息
- AiError 只清出错会话的队列项
This commit is contained in:
lxy
2026-07-20 00:19:50 +08:00
parent 42efb31bbf
commit e9e3578d26
59 changed files with 2875 additions and 1330 deletions
+10 -5
View File
@@ -10,7 +10,7 @@ import { state } from '@/stores/ai'
import { notifyConversationChanged } from './useAiEvents'
import { persistUiState } from './useAiPanel'
import { setStreaming } from './streamingGuard'
import { nextMsgId, getConvState, clearConvStreamState, startApprovalTimer } from './aiShared'
import { nextMsgId, getConvState, clearConvStreamState, startApprovalTimer, clearAllApprovalTimers } from './aiShared'
import { t } from '@/i18n/i18n-helpers'
import type { AiConversationDetail, AiMessage, AiToolCallInfo, ConvId } from '@/api/types'
@@ -76,9 +76,8 @@ async function newConversation() {
// 不清 generatingConvs(保留旧 conv 生成态跟踪,侧栏显双会话生成,AiCompleted/AiError 按
// conversation_id 正确收尾旧 conv)。原 state.generatingConvs.clear() 是 A 路线 F-260616-09
// 单 loop 软隔离遗留,真并发下致后台生成前端丢失跟踪,废弃。
// queue 清空防旧会话排队消息带进新会话 drain;agentRound 复位 0;searchQuery 清空防新会话
// 侧栏被旧搜索过滤。此三项均为新 conv 本地视图复位(非跨 conv 跟踪),保留。
state.queue = []
// agentRound 复位 0;searchQuery 清空防新会话侧栏被旧搜索过滤。
// queue 保留旧会话排队消息(它们有 conversationId,会在旧会话 AiCompleted 时按 ID 精准 drain)
state.agentRound = 0
state.searchQuery = ''
await loadConversations()
@@ -90,6 +89,9 @@ let _latestSwitchId = 0
/** 切换到指定会话:加载历史消息(含 tool_calls 回填 + tool_result 映射 + pending 审批恢复) */
export async function switchConversation(id: string) {
// AIC-FIX-17-P0-2:切换会话时清空所有审批计时器(防切走后过期 timer 误拒后台 pending + 错误气泡推错视图)。
// 新会话的审批计时器由下文 restore pending 路径的 startApprovalTimer 重新建立。
clearAllApprovalTimers()
const mySwitchId = ++_latestSwitchId
// 允许生成中切换:后台继续生成,事件按 conversation_id 路由不污染当前视图
let detail: AiConversationDetail
@@ -241,7 +243,7 @@ export async function switchConversation(id: string) {
dir: tc.dir,
reason: tc.reason,
})
// 重新启动审批计时器(APPROVAL_TIMEOUT_MS=Infinity 已决策,不会超时自动拒绝,
// 重新启动审批计时器(APPROVAL_TIMEOUT_MS 默认 15min0=不限时跳过;
// 启动仅用于计时器注册一致性,保持与 AiApprovalRequired 事件处理对称)
startApprovalTimer(tc.id, tc.name, kind)
}
@@ -258,6 +260,9 @@ export async function switchConversation(id: string) {
/** 删除会话;若删的是当前活跃会话则清空消息+移除活跃 id 持久化 */
async function deleteConversation(id: string) {
// AIC-FIX-17-P0-2:删除会话时清空所有审批计时器(防已删会话的过期 timer 到期误拒审批 +
// 错误气泡推错视图)。
clearAllApprovalTimers()
await aiApi.deleteConversation(id)
// F-09 per-conv:清该会话的 stream state(streaming/currentText),防 convStreamStates Map 无限增长
// (与 convStates/待审批等 per-conv 资源同款会话级清理语义)。