From 959904d72e135b849d866e5cacf14fb3fcafe284 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Thu, 6 Nov 2025 17:41:15 +0800 Subject: [PATCH] feat(chat): enhance resumeStream handling to manage transient status during stream resumption --- .../ai-chat/store/chat-core/chat-instance.ts | 11 +++++++++++ .../ai-chat/store/chat-core/chat-state.ts | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-instance.ts b/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-instance.ts index 6b9d9a086..e460b993e 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-instance.ts +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-instance.ts @@ -17,6 +17,17 @@ export class ZustandChat extends AbstractChat { const state = new ZustandChatState(messages, updateZustandState, init.id || "") super({ ...init, state }) this.state = state + + const baseResumeStream = this.resumeStream.bind(this) + // Track resume calls so the state can ignore the temporary "submitted" status when no stream exists. + this.resumeStream = async (...args) => { + this.state.setResumingStream(true) + try { + return await baseResumeStream(...args) + } finally { + this.state.setResumingStream(false) + } + } } // Public getter for state access diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-state.ts b/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-state.ts index 60d227dcf..ab9c78373 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-state.ts +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/store/chat-core/chat-state.ts @@ -15,6 +15,7 @@ export class ZustandChatState implements ChatState { #status: ChatStatus = "ready" #error: Error | undefined = undefined #eventEmitter = new ChatStateEventEmitter() + #isResumingStream = false constructor( initialMessages: BizUIMessage[] = [], @@ -61,12 +62,24 @@ export class ZustandChatState implements ChatState { }) this.#eventEmitter.on("status", ({ status }) => { + // Suppress the transient "submitted" status emitted when resumeStream probes for an active stream. + if (this.#isResumingStream && status === "submitted") { + return + } + this.updateZustandState((state) => { const isStreaming = status === "streaming" if (isStreaming) { void state.chatActions.markSessionSynced() } + if ( + this.#isResumingStream && + (status === "ready" || status === "streaming" || status === "error") + ) { + this.#isResumingStream = false + } + return { ...state, status, @@ -185,4 +198,8 @@ export class ZustandChatState implements ChatState { destroy(): void { this.#eventEmitter.clear() } + + setResumingStream(isResuming: boolean) { + this.#isResumingStream = isResuming + } }