@@ -6,6 +6,35 @@ const messageValidator = v.object({
66 content : v . string ( ) ,
77} )
88
9+ type ChatSessionMessage = {
10+ role : "user" | "assistant" | "system"
11+ content : string
12+ }
13+
14+ function compactRepeatedTurns ( messages : ChatSessionMessage [ ] ) : ChatSessionMessage [ ] {
15+ const compacted : ChatSessionMessage [ ] = [ ]
16+ for ( const message of messages ) {
17+ compacted . push ( message )
18+ const n = compacted . length
19+ if ( n < 4 ) continue
20+ const firstUser = compacted [ n - 4 ]
21+ const firstAssistant = compacted [ n - 3 ]
22+ const secondUser = compacted [ n - 2 ]
23+ const secondAssistant = compacted [ n - 1 ]
24+ if (
25+ firstUser . role === "user" &&
26+ firstAssistant . role === "assistant" &&
27+ secondUser . role === "user" &&
28+ secondAssistant . role === "assistant" &&
29+ firstUser . content === secondUser . content &&
30+ firstAssistant . content === secondAssistant . content
31+ ) {
32+ compacted . splice ( n - 2 , 2 )
33+ }
34+ }
35+ return compacted
36+ }
37+
938export const create = mutation ( {
1039 args : {
1140 skillPath : v . string ( ) ,
@@ -43,12 +72,19 @@ export const appendMessages = mutation({
4372 const identity = await ctx . auth . getUserIdentity ( )
4473 if ( ! identity ) throw new Error ( "Not authenticated" )
4574
46- const session = await ctx . db . get ( args . sessionId )
75+ const session = await ctx . db . get ( "chatSessions" , args . sessionId )
4776 if ( ! session || session . tokenIdentifier !== identity . tokenIdentifier ) {
4877 throw new Error ( "Session not found" )
4978 }
5079
51- const updated = [ ...session . messages , ...args . messages ]
80+ const duplicateTail =
81+ args . messages . length > 0 &&
82+ session . messages . length >= args . messages . length &&
83+ args . messages . every ( ( message , index ) => {
84+ const existing = session . messages [ session . messages . length - args . messages . length + index ]
85+ return existing ?. role === message . role && existing . content === message . content
86+ } )
87+ const updated = compactRepeatedTurns ( duplicateTail ? session . messages : [ ...session . messages , ...args . messages ] )
5288 const patch : Record < string , unknown > = {
5389 messages : updated ,
5490 messageCount : updated . length ,
@@ -57,7 +93,7 @@ export const appendMessages = mutation({
5793 if ( args . title ) {
5894 patch . title = args . title
5995 }
60- await ctx . db . patch ( args . sessionId , patch )
96+ await ctx . db . patch ( "chatSessions" , args . sessionId , patch )
6197 return null
6298 } ,
6399} )
@@ -68,11 +104,12 @@ export const get = query({
68104 const identity = await ctx . auth . getUserIdentity ( )
69105 if ( ! identity ) return null
70106
71- const session = await ctx . db . get ( args . sessionId )
107+ const session = await ctx . db . get ( "chatSessions" , args . sessionId )
72108 if ( ! session || session . tokenIdentifier !== identity . tokenIdentifier ) {
73109 return null
74110 }
75- return session
111+ const messages = compactRepeatedTurns ( session . messages )
112+ return { ...session , messages, messageCount : messages . length }
76113 } ,
77114} )
78115
@@ -108,16 +145,19 @@ export const list = query({
108145 . order ( "desc" )
109146 . take ( 100 )
110147
111- return sessions . map ( ( s ) => ( {
112- _id : s . _id ,
113- skillPath : s . skillPath ,
114- title : s . title ,
115- model : s . model ,
116- workspacePath : s . workspacePath ,
117- messageCount : s . messageCount ,
118- createdAt : s . createdAt ,
119- updatedAt : s . updatedAt ,
120- } ) )
148+ return sessions . map ( ( s ) => {
149+ const messages = compactRepeatedTurns ( s . messages )
150+ return {
151+ _id : s . _id ,
152+ skillPath : s . skillPath ,
153+ title : s . title ,
154+ model : s . model ,
155+ workspacePath : s . workspacePath ,
156+ messageCount : messages . length ,
157+ createdAt : s . createdAt ,
158+ updatedAt : s . updatedAt ,
159+ }
160+ } )
121161 } ,
122162} )
123163
@@ -128,9 +168,9 @@ export const remove = mutation({
128168 const identity = await ctx . auth . getUserIdentity ( )
129169 if ( ! identity ) throw new Error ( "Not authenticated" )
130170
131- const session = await ctx . db . get ( args . sessionId )
171+ const session = await ctx . db . get ( "chatSessions" , args . sessionId )
132172 if ( session && session . tokenIdentifier === identity . tokenIdentifier ) {
133- await ctx . db . delete ( args . sessionId )
173+ await ctx . db . delete ( "chatSessions" , args . sessionId )
134174 }
135175 return null
136176 } ,
0 commit comments