@@ -36,11 +36,10 @@ export default defineSchema({
3636 avatarUrl : v . optional ( v . string ( ) ) ,
3737 encryptedOpenRouterKey : v . optional ( v . string ( ) ) ,
3838 fileUploadCount : v . optional ( v . number ( ) ) ,
39- // Future expansion for user preferences
39+ favoriteModels : v . optional ( v . array ( v . string ( ) ) ) ,
4040 preferences : v . optional (
4141 v . object ( {
4242 theme : v . optional ( v . string ( ) ) ,
43- // Add more preferences as needed
4443 } )
4544 ) ,
4645 createdAt : v . number ( ) ,
@@ -70,63 +69,45 @@ export default defineSchema({
7069 chatId : v . id ( "chats" ) ,
7170 clientMessageId : v . optional ( v . string ( ) ) ,
7271 role : v . string ( ) ,
73- // Content can be encrypted (prefixed with enc_v1:). Max length: 100KB (102400 bytes)
7472 content : v . string ( ) ,
75- // Model ID used to generate this message (e.g., "x-ai/grok-4-fast")
7673 modelId : v . optional ( v . string ( ) ) ,
77- // DEPRECATED: Use chainOfThoughtParts instead. Kept for backward compatibility.
78- // Reasoning content from models with reasoning capabilities (e.g., Claude 4, GPT-5, DeepSeek R1)
7974 reasoning : v . optional ( v . string ( ) ) ,
80- // Time spent thinking in milliseconds (for reasoning models)
8175 thinkingTimeMs : v . optional ( v . number ( ) ) ,
82- // Whether reasoning was requested for this message (used to show "redacted" state when
83- // provider doesn't return reasoning data)
8476 reasoningRequested : v . optional ( v . boolean ( ) ) ,
85- // DEPRECATED: Use chainOfThoughtParts instead. Kept for backward compatibility.
86- // Tool invocations that occurred during this message's generation
8777 toolInvocations : v . optional (
8878 v . array (
8979 v . object ( {
9080 toolName : v . string ( ) ,
9181 toolCallId : v . string ( ) ,
92- state : v . string ( ) , // "input-streaming" | "input-available" | "output-available" | "output-error"
82+ state : v . string ( ) ,
9383 input : v . optional ( v . any ( ) ) ,
9484 output : v . optional ( v . any ( ) ) ,
9585 errorText : v . optional ( v . string ( ) ) ,
9686 } )
9787 )
9888 ) ,
99- // NEW: Unified chain of thought parts - preserves exact stream order
100- // This replaces the separate reasoning and toolInvocations fields
101- // Each part has an index representing its position in the original stream
10289 chainOfThoughtParts : v . optional (
10390 v . array (
10491 v . object ( {
105- // Part type: "reasoning" for thinking, "tool" for tool calls
10692 type : v . union ( v . literal ( "reasoning" ) , v . literal ( "tool" ) ) ,
107- // Original position in the AI stream (for ordering)
10893 index : v . number ( ) ,
109- // For reasoning parts
11094 text : v . optional ( v . string ( ) ) ,
111- // For tool parts
11295 toolName : v . optional ( v . string ( ) ) ,
11396 toolCallId : v . optional ( v . string ( ) ) ,
114- state : v . optional ( v . string ( ) ) , // "input-streaming" | "input-available" | "output-available" | "output-error"
97+ state : v . optional ( v . string ( ) ) ,
11598 input : v . optional ( v . any ( ) ) ,
11699 output : v . optional ( v . any ( ) ) ,
117100 errorText : v . optional ( v . string ( ) ) ,
118101 } )
119102 )
120103 ) ,
121- // Token usage for this message
122104 tokenUsage : v . optional (
123105 v . object ( {
124106 promptTokens : v . number ( ) ,
125107 completionTokens : v . number ( ) ,
126108 totalTokens : v . number ( ) ,
127109 } )
128110 ) ,
129- // File attachments
130111 attachments : v . optional (
131112 v . array (
132113 v . object ( {
@@ -139,32 +120,22 @@ export default defineSchema({
139120 } )
140121 )
141122 ) ,
142- // ERROR HANDLING: Store error information for failed AI responses (like T3.chat)
143- // This allows errors to be displayed inline in the conversation history
144123 error : v . optional (
145124 v . object ( {
146- // Error classification: "rate_limit", "auth_error", "model_error", "network_error", "content_filter", "context_length", "unknown"
147125 code : v . string ( ) ,
148- // Human-readable error message
149126 message : v . string ( ) ,
150- // Optional detailed error info (stack trace, API response, etc.) for debugging
151127 details : v . optional ( v . string ( ) ) ,
152- // Which provider/model caused the error
153128 provider : v . optional ( v . string ( ) ) ,
154- // Whether the user can retry this request
155129 retryable : v . optional ( v . boolean ( ) ) ,
156130 } )
157131 ) ,
158- // Message type to distinguish content types: "text" (default), "error", "system"
159- // "error" messages display with error styling, "system" for notifications
160132 messageType : v . optional (
161133 v . union ( v . literal ( "text" ) , v . literal ( "error" ) , v . literal ( "system" ) )
162134 ) ,
163135 createdAt : v . number ( ) ,
164136 status : v . optional ( v . string ( ) ) ,
165137 userId : v . optional ( v . id ( "users" ) ) ,
166138 deletedAt : v . optional ( v . number ( ) ) ,
167- // Stream ID for persistent text streaming - links to @convex-dev/persistent-text-streaming
168139 streamId : v . optional ( v . string ( ) ) ,
169140 } )
170141 . index ( "by_chat" , [ "chatId" , "createdAt" ] )
@@ -173,7 +144,8 @@ export default defineSchema({
173144 . index ( "by_user_status" , [ "userId" , "status" , "createdAt" ] )
174145 . index ( "by_chat_not_deleted" , [ "chatId" , "deletedAt" , "createdAt" ] )
175146 . index ( "by_user_created" , [ "userId" , "createdAt" ] )
176- . index ( "by_stream_id" , [ "streamId" ] ) ,
147+ . index ( "by_stream_id" , [ "streamId" ] )
148+ . index ( "by_chat_status" , [ "chatId" , "status" , "deletedAt" ] ) ,
177149 fileUploads : defineTable ( {
178150 userId : v . id ( "users" ) ,
179151 chatId : v . id ( "chats" ) ,
0 commit comments