From 900e60460ca6cbbc190eba7fab8ccab74af1e290 Mon Sep 17 00:00:00 2001 From: Huarch Date: Tue, 7 Jul 2026 11:23:07 +0800 Subject: [PATCH] fix(chat): avoid implicit stream reuse --- src/routes/chat.ts | 26 +++++++++++++++++++------ tests/routes/chatSession.test.ts | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/routes/chat.ts b/src/routes/chat.ts index 9972ac0..c34f262 100644 --- a/src/routes/chat.ts +++ b/src/routes/chat.ts @@ -193,6 +193,21 @@ const pipeUiChunk = ( } }; +export const resolveRequestedStreamSessionId = (input: { + sessionId?: string; + promptText: string; + createClientSessionId: () => string; +}) => { + const sessionId = input.sessionId?.trim(); + if (sessionId) { + return sessionId; + } + if (isPressureTrendDemoPrompt(input.promptText)) { + return input.createClientSessionId(); + } + return undefined; +}; + export const buildChatRouter = ( sessionBridge: ChatSessionBridge, runtime: OpencodeRuntimeAdapter, @@ -617,12 +632,11 @@ export const buildChatRouter = ( }); return; } - const requestedSessionId = - parsed.data.session_id?.trim() || - parsed.data.id?.trim() || - (isPressureTrendDemoPrompt(promptText) - ? sessionBridge.createClientSessionId() - : undefined); + const requestedSessionId = resolveRequestedStreamSessionId({ + sessionId: parsed.data.session_id, + promptText, + createClientSessionId: () => sessionBridge.createClientSessionId(), + }); const existingSessionRecord = requestedSessionId ? await sessionMetadataStore.get( { actorKey, projectId, projectKey, userId }, diff --git a/tests/routes/chatSession.test.ts b/tests/routes/chatSession.test.ts index 19e5611..426068a 100644 --- a/tests/routes/chatSession.test.ts +++ b/tests/routes/chatSession.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from "bun:test"; import { buildForkedSessionUiState, + resolveRequestedStreamSessionId, } from "../../src/routes/chat.js"; import { buildPromptWithLearningContext, @@ -14,6 +15,38 @@ import { type SessionTurnRecord } from "../../src/sessions/transcriptStore.js"; import { type MemoryStore } from "../../src/memory/store.js"; import { type OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js"; +describe("resolveRequestedStreamSessionId", () => { + it("uses only explicit session_id for normal chat reuse", () => { + const createClientSessionId = () => { + throw new Error("should not create a demo session id"); + }; + + expect( + resolveRequestedStreamSessionId({ + sessionId: " existing-session ", + promptText: "检查压力异常", + createClientSessionId, + }), + ).toBe("existing-session"); + + expect( + resolveRequestedStreamSessionId({ + promptText: "检查压力异常", + createClientSessionId, + }), + ).toBeUndefined(); + }); + + it("keeps the pressure trend demo on its generated client session id", () => { + expect( + resolveRequestedStreamSessionId({ + promptText: "展示最近压力趋势", + createClientSessionId: () => "demo-session", + }), + ).toBe("demo-session"); + }); +}); + describe("shouldGenerateSessionTitle", () => { it("allows auto-title generation for the first turn when the title was not edited", () => { expect(