优化: 会话状态 per-conv 化与交互守卫

- 待审批跨会话 per-conv 合并,审批类事件全局放行
- 看门狗/重试计数/流式残段按会话键控迁移
- 输入草稿与子代理完成卡数据按会话隔离
- 切换兜底 activeId,收敛守卫防幽灵气泡
- 发送错误按限流/额度/网络分类文案
This commit is contained in:
lxy
2026-10-03 15:35:15 +08:00
parent d406a31722
commit b4fafa0e9a
13 changed files with 460 additions and 96 deletions
+19 -15
View File
@@ -6,7 +6,7 @@
import { emit } from '@tauri-apps/api/event'
import { state } from '@/stores/ai'
import { t } from '@/i18n/i18n-helpers'
import { findToolCall, clearApprovalTimer, startApprovalTimer, startToolSlowTimer, clearToolSlowTimer } from './aiShared'
import { findToolCall, clearApprovalTimer, startApprovalTimer, startToolSlowTimer, clearToolSlowTimer, addPendingApproval, removePendingApprovalById } from './aiShared'
import { removePendingDirAuth } from './useAiPendingState'
import { clearStreamWatchdog } from './useAiStream'
import type { AiChatEvent, AiToolCallInfo } from '@/api/types'
@@ -43,7 +43,8 @@ export function handleToolEvent(event: AiChatEvent): boolean {
tc.result = event.result
tc.completedAt = Date.now()
}
state.pendingApprovals = state.pendingApprovals.filter(p => p.id !== event.id)
// 移除待审批(含 per-conv 集合,后台会话集合里的同 id 挂起一并清)
removePendingApprovalById(event.id)
clearToolSlowTimer(event.id)
// 工具结束(无论审批通过后执行还是被拒),清审批超时计时器
clearApprovalTimer(event.id)
@@ -68,19 +69,21 @@ export function handleToolEvent(event: AiChatEvent): boolean {
reason: event.reason,
conversationId: event.conversation_id ?? state.activeConversationId ?? undefined,
}
state.pendingApprovals.push(info)
const tc = findToolCall(event.id)
if (tc) {
tc.status = 'pending_approval'
tc.reason = event.reason
// write_file 审批注入行级 diff(旧文件 vs 新内容),前端审批卡预览
if (event.diff) tc.diff = event.diff
// per-conv 归会话追加(同 id 幂等):跨会话事件不再互相覆盖;首次到达才做后续副作用
if (addPendingApproval(info)) {
const tc = findToolCall(event.id)
if (tc) {
tc.status = 'pending_approval'
tc.reason = event.reason
// write_file 审批注入行级 diff(旧文件 vs 新内容),前端审批卡预览
if (event.diff) tc.diff = event.diff
}
// 进入审批等待 → 取消该工具慢执行计时器(审批耗时由用户主导,非执行慢),再启动审批超时计时器
clearToolSlowTimer(event.id)
startApprovalTimer(event.id, event.name, 'risk')
// 通知 ToolCardList 展开折叠组 + scroll(pending 卡落折叠分组不可见时)
void emit('ai-pending-arrived', { toolCallId: event.id })
}
// 进入审批等待 → 取消该工具慢执行计时器(审批耗时由用户主导,非执行慢),再启动审批超时计时器
clearToolSlowTimer(event.id)
startApprovalTimer(event.id, event.name, 'risk')
// 通知 ToolCardList 展开折叠组 + scroll(pending 卡落折叠分组不可见时)
void emit('ai-pending-arrived', { toolCallId: event.id })
return true
}
@@ -91,7 +94,8 @@ export function handleToolEvent(event: AiChatEvent): boolean {
tc.status = 'rejected'
tc.result = t('ai.aiTool.rejectedHint')
}
state.pendingApprovals = state.pendingApprovals.filter(p => p.id !== event.id)
// 移除待审批(含 per-conv 集合)
removePendingApprovalById(event.id)
clearToolSlowTimer(event.id)
clearApprovalTimer(event.id)
} else {