优化: L2统一状态机完整(ConvState持久化+事件暴露+前端status联合)

1a PerConvState.conv_state持久化(入口/reset/drop写收敛,CONV_STATE_ENABLED门控)
1b AiChatEvent加AiConvStateChanged变体,guard持app_handle在迁移点emit
1c 前端convStates真相源+停止按钮三态(status union)+MaxRoundsCard读conv_state
双轨过渡:enum视图与generating bool并行,off降级可回退
This commit is contained in:
lxy
2026-06-22 00:34:43 +08:00
parent d2cada97cd
commit cdb227f999
9 changed files with 264 additions and 13 deletions
+16 -2
View File
@@ -27,7 +27,7 @@
import { ref, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAiStore } from '../../stores/ai'
import { pendingMaxRounds } from '../../composables/ai/useAiEvents'
import { pendingMaxRounds, getConvState } from '../../composables/ai/useAiEvents'
import { aiApi } from '../../api'
const emit = defineEmits<{
@@ -47,6 +47,20 @@ const isViewingGenerating = computed(() =>
store.isGenerating(store.state.activeConversationId),
)
// L2 状态机(批2 1c):达 max 可靠弹判断改读 conv_state(generating),诊断痛②看门狗误清 streaming
// 致卡片不弹的根解。conv_state 作新增派生源,旧 isGenerating 双轨过渡兜底——conv_state 未收到
// 时(CONV_STATE_ENABLED=off 或老后端)回退 isGenerating 判断,不强制全替防回归。
// 注:达 max 时后端仍 generating(conv_state=generating,审批挂起期亦是 generating),故读
// conv_state===generating 覆盖挂起态;compressed(压缩派生)也视为活跃可弹(达 max 与压缩互斥,
// 理论不并存,此处宽放以防边界)。
const isViewingGeneratingState = computed(() => {
const cs = getConvState(store.state.activeConversationId)
if (cs === 'generating' || cs === 'compressed') return true
if (cs === 'idle' || cs === 'error' || cs === 'stopping') return false
// conv_state 未追踪过(null)→ 回退旧 isGenerating bool 判断
return isViewingGenerating.value
})
// pendingMaxRounds(达 max 事件置的挂起 convId)+ 当前视图正在生成(防切走后误显)双重守卫。
// TD-260621-02 per-conv:pendingMaxRounds 存挂起 convId(string|null),精确比对
// activeConversationId —— 仅当挂起会话 === 当前展示会话时显操作卡,F-09 并发下不会错显于其他会话。
@@ -56,7 +70,7 @@ const maxRoundsActing = ref(false)
const showMaxRoundsCard = computed(() =>
!!pendingMaxRounds.value
&& pendingMaxRounds.value === store.state.activeConversationId
&& isViewingGenerating.value,
&& isViewingGeneratingState.value,
)
/** 点继续:调 ai_continue_loop。后端续 max_iterations 轮(iteration 从 0 重计)。