diff --git a/src/routes/chat.ts b/src/routes/chat.ts index ed59f78..72b3af3 100644 --- a/src/routes/chat.ts +++ b/src/routes/chat.ts @@ -278,18 +278,27 @@ export const buildChatRouter = ( const assistantText = collectTextContent(assistantMessage?.parts ?? []); const existingSessionTitle = sessionBridge.getSessionTitle(binding.sessionId); let sessionTitle = existingSessionTitle; + const { userMessageCount, assistantMessageCount } = + await getConversationTurnStats(runtime, binding.sessionId); const shouldGenerateTitle = - !existingSessionTitle && - (await isFirstRoundConversation(runtime, binding.sessionId)); + userMessageCount <= 3 && + assistantMessageCount >= 1; if (shouldGenerateTitle) { sessionTitle = await generateSessionTitle(runtime, { sessionId: binding.sessionId, latestUserMessage: parsed.data.message, + fallbackTitle: existingSessionTitle, }); - sessionBridge.setSessionTitle(binding.sessionId, sessionTitle); + if (sessionTitle !== existingSessionTitle) { + sessionBridge.setSessionTitle(binding.sessionId, sessionTitle); + } } if (!streamClosed && !res.writableEnded && !res.destroyed) { - if (shouldGenerateTitle && sessionTitle) { + if ( + shouldGenerateTitle && + sessionTitle && + sessionTitle !== existingSessionTitle + ) { res.write( toSse("session_title", { session_id: clientSessionId, @@ -1044,16 +1053,25 @@ const buildTitleConversationContext = async ( .slice(0, 2400); }; -const isFirstRoundConversation = async ( +const getConversationTurnStats = async ( runtime: OpencodeRuntimeAdapter, sessionId: string, ) => { const messages = await runtime.messages(sessionId, 12); - const chatMessageCount = messages.filter( - (message) => - message.info.role === "user" || message.info.role === "assistant", - ).length; - return chatMessageCount === 2; + return messages.reduce( + (stats, message) => { + if (message.info.role === "user") { + stats.userMessageCount += 1; + } else if (message.info.role === "assistant") { + stats.assistantMessageCount += 1; + } + return stats; + }, + { + userMessageCount: 0, + assistantMessageCount: 0, + }, + ); }; const normalizeGeneratedTitle = (rawTitle: string, fallback: string) => {