@@ -19,8 +19,10 @@ import {
1919import {
2020 appendSavedConversationSummaryContext ,
2121 buildConversationSummaryPrompt ,
22+ buildRollingConversationSummaryPrompt ,
2223 filterSummarizedMessages ,
2324 prepareChatModelContext ,
25+ selectMessagesForPersistentSummary ,
2426} from "@/lib/botchat/chat-context" ;
2527import {
2628 appendChatSkillInstructions ,
@@ -29,6 +31,10 @@ import {
2931
3032export const maxDuration = 30 ;
3133
34+ type SupabaseServerClient = Awaited <
35+ ReturnType < typeof createSupabaseServerClient >
36+ > ;
37+
3238function isRecord ( value : unknown ) : value is Record < string , unknown > {
3339 return typeof value === "object" && value !== null ;
3440}
@@ -105,6 +111,57 @@ function buildCurrentSystemDateTimeContext() {
105111Use this as the authoritative current date/time if the user asks about "now", "today", the current date, the current time, or the current time zone.` ;
106112}
107113
114+ async function persistRequestRollingConversationSummaryIfNeeded (
115+ supabase : SupabaseServerClient ,
116+ sessionId : string ,
117+ previousSummary : string | null ,
118+ messages : UIMessage [ ]
119+ ) {
120+ const rowsToSummarize = selectMessagesForPersistentSummary ( messages ) ;
121+ if ( rowsToSummarize . length === 0 ) {
122+ return { summary : previousSummary , summarizedUiMessageIds : [ ] } ;
123+ }
124+
125+ const { text } = await generateText ( {
126+ model : openai ( getConversationSummaryModelId ( ) ) ,
127+ providerOptions : {
128+ openai : {
129+ reasoningEffort : "none" ,
130+ } ,
131+ } ,
132+ instructions :
133+ "You update a rolling compressed summary of earlier chat history. Preserve facts, decisions, constraints, and unresolved user intent. Do not answer the user." ,
134+ prompt : buildRollingConversationSummaryPrompt (
135+ previousSummary ,
136+ rowsToSummarize
137+ ) ,
138+ } ) ;
139+
140+ const summary = text . trim ( ) ;
141+ const summarizedAt = new Date ( ) . toISOString ( ) ;
142+ const summarizedUiMessageIds = rowsToSummarize . map ( ( message ) => message . id ) ;
143+
144+ const { error : summaryError } = await supabase
145+ . from ( "chat_sessions" )
146+ . update ( {
147+ context_summary : summary ,
148+ context_summary_updated_at : summarizedAt ,
149+ } )
150+ . eq ( "id" , sessionId ) ;
151+
152+ if ( summaryError ) throw new Error ( summaryError . message ) ;
153+
154+ const { error : markerError } = await supabase
155+ . from ( "chat_messages" )
156+ . update ( { summarized_at : summarizedAt } )
157+ . eq ( "session_id" , sessionId )
158+ . in ( "ui_message_id" , summarizedUiMessageIds ) ;
159+
160+ if ( markerError ) throw new Error ( markerError . message ) ;
161+
162+ return { summary, summarizedUiMessageIds } ;
163+ }
164+
108165export async function POST ( request : Request ) {
109166 const body = await request . json ( ) ;
110167 const messages = await Promise . resolve ( body . messages ) ;
@@ -124,9 +181,10 @@ export async function POST(request: Request) {
124181 "You are a premium luggage brand assistant. Be concise, confident, and proactive with tasteful product suggestions." ;
125182 let contextSummary : string | null = null ;
126183 let summarizedUiMessageIds = new Set < string > ( ) ;
184+ let supabase : SupabaseServerClient | null = null ;
127185
128186 try {
129- const supabase = await createSupabaseServerClient ( ) ;
187+ supabase = await createSupabaseServerClient ( ) ;
130188 if ( sessionId ) {
131189 const [ sessionResult , summarizedMessagesResult ] = await Promise . all ( [
132190 supabase
@@ -186,13 +244,37 @@ export async function POST(request: Request) {
186244 system = `${ system } \n\n${ buildCurrentSystemDateTimeContext ( ) } ` ;
187245 }
188246
189- system = appendSavedConversationSummaryContext ( system , contextSummary ) ;
190-
191- const contextMessages = filterSummarizedMessages (
247+ let contextMessages = filterSummarizedMessages (
192248 messages as UIMessage [ ] ,
193249 summarizedUiMessageIds
194250 ) ;
195251
252+ if ( sessionId && supabase ) {
253+ try {
254+ const persistedSummary =
255+ await persistRequestRollingConversationSummaryIfNeeded (
256+ supabase ,
257+ sessionId ,
258+ contextSummary ,
259+ contextMessages
260+ ) ;
261+
262+ contextSummary = persistedSummary . summary ;
263+ summarizedUiMessageIds = new Set ( [
264+ ...summarizedUiMessageIds ,
265+ ...persistedSummary . summarizedUiMessageIds ,
266+ ] ) ;
267+ contextMessages = filterSummarizedMessages (
268+ messages as UIMessage [ ] ,
269+ summarizedUiMessageIds
270+ ) ;
271+ } catch ( error ) {
272+ console . error ( "Failed to persist request conversation summary" , error ) ;
273+ }
274+ }
275+
276+ system = appendSavedConversationSummaryContext ( system , contextSummary ) ;
277+
196278 const preparedContext = await prepareChatModelContext ( contextMessages , {
197279 summarizeMessages : async ( messagesToSummarize ) => {
198280 const { text } = await generateText ( {
0 commit comments