重构: aichat 双轨状态机收口 + AiCompressed 事件拆分

- generating bool + CONV_STATE_ENABLED 开关双轨退役,ConvState enum 单一真相源
- can_accept_request 接入 chat 域入口(覆盖 Stopping 竞态,严谨于 is_active)
- AiCompressed 拆 AiManualCompressed/AiAutoCompressed(治自动压缩误触桌面toast+刷新)
- convStates/getConvState 下沉 aiShared.ts 破循环依赖
This commit is contained in:
lxy
2026-06-25 03:20:42 +08:00
parent fc705443bd
commit c011f864fd
22 changed files with 526 additions and 428 deletions
+47 -1
View File
@@ -10,11 +10,12 @@
//! - 审批计时器(startApprovalTimer/clearApprovalTimer/clearAllApprovalTimers):
//! events 模块触发(start/clear/allClear),send 模块也需导出给组件,故下沉到共享层
import { reactive } from 'vue'
import { aiApi } from '@/api'
import { state } from '@/stores/ai'
import { useAppSettingsStore } from '@/stores/appSettings'
import { t } from '@/i18n/i18n-helpers'
import type { AiToolCallInfo } from '@/api/types'
import type { AiToolCallInfo, ConvState } from '@/api/types'
const appSettings = useAppSettingsStore()
@@ -124,3 +125,48 @@ export function clearAllApprovalTimers(): void {
for (const timer of _approvalTimers.values()) clearTimeout(timer)
_approvalTimers.clear()
}
// ── L2 统一状态机 convStates(下沉自 useAiEvents,批4 双轨收口) ──
//
// 下沉原因:批4 退役 generatingConvs(bool 轨)后,stores/ai.ts(isGenerating)/
// useAiStream.ts(onStreamTimeout stillGenerating)/useAiConversations.ts(switchConversation 重算)
// 等读点均需 import getConvState。若 getConvState 留在 useAiEvents,这些模块反向 import
// useAiEvents 会与 useAiEvents→useAiStream/useAiEvents←stores 的现有依赖构成环。
// 故将 convStates Map + getConvState + setConvState 全部下沉到本共享层(与 nextMsgId/findToolCall/
// 审批计时器同位置,沿用既有破环模式)。useAiEvents 改为从本模块 import 它们。
/**
* per-conv conv_state 真相源(消费后端 AiConvStateChanged 事件)。
*
* 模块级 reactive Map(convId → ConvState),不进 store.state(与生成生命周期语义独立于
* 消息/会话列表,同 pendingMaxRounds/pendingHelp 模式)。批4 收口后,本 Map 是「会话是否生成中」
* 的唯一真相源,generatingConvs bool 轨已退役。
*/
export const convStates = reactive(new Map<string, ConvState>())
/**
* 取某 conv 的 conv_state;未追踪过返回 null。
*
* 桥接语义(批4 收口):bool 轨 generatingConvs.has(id) 等价于本函数返回值 ∈
* {'generating','stopping','compressed'}(非终止三态);idle/error/null 对应 bool 轨 has()=false。
* 依据:handleConvStateEvent 原同步逻辑将三态都 add,终止态 delete。
*/
export function getConvState(convId: string | null | undefined): ConvState | null {
if (!convId) return null
return convStates.get(convId) ?? null
}
/**
* 写入 conv_state(useAiEvents.handleConvStateEvent 的 AiConvStateChanged case 唯一写入口,
* 及活跃事件兜底写 generating 态)。
*
* idle 为终态收敛:写后删 Map 项(与后端 generating=false 语义对齐,Map 不持陈旧 idle 项)。
*/
export function setConvState(convId: string | null | undefined, s: ConvState): void {
if (!convId) return
if (s === 'idle') {
convStates.delete(convId)
} else {
convStates.set(convId, s)
}
}