修复: OpenAI SSE error 识别 + 条件引擎 warn + MidStream stop_flag 优先 + 双窗口 listener 时序加固
This commit is contained in:
@@ -875,7 +875,7 @@ export async function startListener() {
|
||||
/** 停止事件监听(卸载时调用,释放后端 listener + 清看门狗)
|
||||
* 清看门狗:卸载时若仍在生成,_streamWatchdog 计时器未释放,130s 后 onStreamTimeout
|
||||
* 仍写 state(messages.push/置 streaming)——已卸载组件不应再被触发。故同步清除。 */
|
||||
function stopListener() {
|
||||
export function stopListener() {
|
||||
_unlistenAiEvent?.()
|
||||
_unlistenConvChanged?.()
|
||||
_unlistenApprovalClear?.()
|
||||
|
||||
@@ -14,6 +14,7 @@ import { nextMsgId, getConvState, convStates } from './aiShared'
|
||||
import type { MessageId } from '@/api/types'
|
||||
import { setStreaming } from './streamingGuard'
|
||||
import { persistUiState } from './useAiPanel'
|
||||
import { stopListener } from './useAiEvents'
|
||||
|
||||
// ── 主窗口事件跟随 unlistener ──
|
||||
let _unlistenMove: (() => void) | null = null
|
||||
@@ -100,6 +101,11 @@ async function detachPanel(convId?: string) {
|
||||
stopFollowMain()
|
||||
})
|
||||
state.detached = true
|
||||
// 时序加固:detached 置 true 后立即停主窗口 listener,不依赖 v-if → AiChat onBeforeUnmount 的
|
||||
// 异步传播。消除 detached=true 到 AiChat 实际卸载的窗口期(reattach 重叠期/HMR/极速 mount-unmount
|
||||
// 竞态下,onBeforeUnmount 可能延迟,旧 listener 残留会与分离窗口新 listener 并存竞态)。
|
||||
// stopListener 同步释放后端 listener + 清看门狗,分离窗口 resumeInDetached 起自己的 startListener。
|
||||
stopListener()
|
||||
}
|
||||
|
||||
/** 关闭分离窗口并回到内嵌面板(主窗口侧调用)。
|
||||
@@ -119,6 +125,9 @@ async function reattachPanel() {
|
||||
state.docked = false
|
||||
state.panelOpen = true
|
||||
persistUiState()
|
||||
// 时序加固:reattach 关闭分离窗口后,显式停分离窗口残留 listener(分离窗口 close 异步,
|
||||
// onBeforeUnmount stopListener 可能延迟),防主面板重新挂载 startListener 时与旧 listener 重叠竞态。
|
||||
stopListener()
|
||||
// F-09:清所有 per-conv 快照(分离窗口已全关,快照无消费方)
|
||||
cleanupAllDetachedSnapshots()
|
||||
}
|
||||
@@ -221,6 +230,9 @@ async function resumeInDetached(convId: string | null) {
|
||||
async function closeDetachedWindow() {
|
||||
state.docked = false
|
||||
stopFollowMain()
|
||||
// 时序加固:关闭分离窗口前先停 listener,防 close 异步传播期间 onBeforeUnmount 延迟、
|
||||
// 主面板重挂载 startListener 与旧分离窗口 listener 短暂并存(极速 mount-unmount/HMR 竞态)。
|
||||
stopListener()
|
||||
const { getCurrentWebviewWindow } = await import('@tauri-apps/api/webviewWindow')
|
||||
const currentWin = getCurrentWebviewWindow()
|
||||
const lbl = currentWin.label
|
||||
|
||||
Reference in New Issue
Block a user