fix(ai): fetch remote messages if not exist
Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
a939842ca9
commit
5aed1affab
|
|
@ -49,6 +49,7 @@ class AIChatSessionServiceStatic {
|
|||
createdAt: new Date(session.createdAt),
|
||||
// Use createdAt for updatedAt as we are syncing session instead of messages
|
||||
updatedAt: new Date(session.createdAt),
|
||||
isLocal: false,
|
||||
})
|
||||
})
|
||||
await this.loadSessionsFromDb()
|
||||
|
|
@ -84,11 +85,15 @@ class AIChatSessionServiceStatic {
|
|||
force?: boolean
|
||||
},
|
||||
): Promise<void> {
|
||||
const dbSession = await AIPersistService.getChatSession(session.chatId)
|
||||
const [dbSession, hasPersistedMessages] = await Promise.all([
|
||||
AIPersistService.getChatSession(session.chatId),
|
||||
AIPersistService.hasPersistedMessages(session.chatId),
|
||||
])
|
||||
|
||||
const lastUpdatedAt = dbSession ? dbSession.updatedAt : new Date(0)
|
||||
const hasUpToDateSession = lastUpdatedAt >= new Date(session.updatedAt)
|
||||
|
||||
if (!options?.force && hasUpToDateSession) {
|
||||
if (!options?.force && hasUpToDateSession && hasPersistedMessages) {
|
||||
// If local session is already up-to-date, skip fetching messages
|
||||
return
|
||||
}
|
||||
|
|
@ -104,6 +109,7 @@ class AIChatSessionServiceStatic {
|
|||
// Use createdAt for updatedAt
|
||||
// Because we are fetching session data instead of messages
|
||||
updatedAt: new Date(session.createdAt),
|
||||
isLocal: false,
|
||||
})
|
||||
await AIPersistService.upsertMessages(session.chatId, normalized)
|
||||
|
||||
|
|
@ -120,6 +126,11 @@ class AIChatSessionServiceStatic {
|
|||
|
||||
async syncSessionMessages(chatId: string) {
|
||||
try {
|
||||
const sessionRecord = await AIPersistService.getChatSession(chatId)
|
||||
if (sessionRecord?.isLocal) {
|
||||
return AIPersistService.loadUIMessages(chatId)
|
||||
}
|
||||
|
||||
const sessionResponse = await followApi.aiChatSessions.get({ chatId })
|
||||
const session = sessionResponse.data
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ export const aiChatSessionStoreActions = {
|
|||
title: session.title || t("ai:common.new_chat"),
|
||||
createdAt: new Date(session.createdAt),
|
||||
updatedAt: new Date(session.updatedAt),
|
||||
isLocal: false,
|
||||
syncStatus: "synced" as const,
|
||||
})),
|
||||
)
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -25,20 +25,21 @@ interface AIMessagePartsProps {
|
|||
|
||||
export const AIMessageParts: React.FC<AIMessagePartsProps> = React.memo(
|
||||
({ message, isLastMessage }) => {
|
||||
const [shouldStreamingAnimation, setShouldStreamingAnimation] = React.useState(false)
|
||||
// const [shouldStreamingAnimation, setShouldStreamingAnimation] = React.useState(false)
|
||||
const chatStatus = useChatStatus()
|
||||
|
||||
React.useEffect(() => {
|
||||
// Delay 2s to set shouldStreamingAnimation
|
||||
const timerId = setTimeout(() => {
|
||||
setShouldStreamingAnimation(true)
|
||||
}, 2000)
|
||||
return () => clearTimeout(timerId)
|
||||
}, [])
|
||||
// React.useEffect(() => {
|
||||
// I forgot why do this
|
||||
// // Delay 2s to set shouldStreamingAnimation
|
||||
// const timerId = setTimeout(() => {
|
||||
// setShouldStreamingAnimation(true)
|
||||
// }, 2000)
|
||||
// return () => clearTimeout(timerId)
|
||||
// }, [])
|
||||
|
||||
const shouldMessageAnimation = React.useMemo(() => {
|
||||
return chatStatus === "streaming" && shouldStreamingAnimation && isLastMessage
|
||||
}, [chatStatus, isLastMessage, shouldStreamingAnimation])
|
||||
return chatStatus === "streaming" && isLastMessage // && shouldStreamingAnimation
|
||||
}, [chatStatus, isLastMessage])
|
||||
|
||||
const chainThoughtParts = React.useMemo(() => {
|
||||
const parts = [] as (ChainReasoningPart[] | TextUIPart | ToolUIPart<BizUITools>)[]
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const UserChatMessage: React.FC<UserChatMessageProps> = React.memo(({ mes
|
|||
const setEditingMessageId = useSetEditingMessageId()
|
||||
|
||||
const chatStatus = useChatStatus()
|
||||
|
||||
const isStreaming = chatStatus === "submitted" || chatStatus === "streaming"
|
||||
const isEditing = editingMessageId === messageId
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useEventCallback } from "usehooks-ts"
|
|||
|
||||
import { AIChatSessionService } from "~/modules/ai-chat-session/service"
|
||||
|
||||
import { AIPersistService } from "../services"
|
||||
import { useChatActions } from "../store/hooks"
|
||||
import type { BizUIMessage } from "../store/types"
|
||||
|
||||
|
|
@ -20,6 +21,12 @@ export const useLoadMessages = (
|
|||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (chatActions.get().isLocal) {
|
||||
AIPersistService.loadUIMessages(chatId)
|
||||
setIsLoading(false)
|
||||
|
||||
return
|
||||
}
|
||||
let mounted = true
|
||||
setIsLoading(true)
|
||||
setIsSyncingRemote(false)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,17 @@ class AIPersistServiceStatic {
|
|||
})
|
||||
}
|
||||
|
||||
async hasPersistedMessages(chatId: string): Promise<boolean> {
|
||||
const existingMessage = await db.query.aiChatMessagesTable.findFirst({
|
||||
where: eq(aiChatMessagesTable.chatId, chatId),
|
||||
columns: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
|
||||
return Boolean(existingMessage?.id === chatId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert enhanced database message to BizUIMessage format for compatibility
|
||||
*/
|
||||
|
|
@ -74,6 +85,8 @@ class AIPersistServiceStatic {
|
|||
title?: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
isLocal: boolean
|
||||
syncStatus: "local" | "synced"
|
||||
} | null
|
||||
messages: BizUIMessage[]
|
||||
}> {
|
||||
|
|
@ -97,9 +110,14 @@ class AIPersistServiceStatic {
|
|||
await this.updateSessionTitle(sessionRaw.chatId, resolvedTitle)
|
||||
}
|
||||
|
||||
const isLocal = Boolean(sessionRaw.isLocal)
|
||||
const syncStatus: "local" | "synced" = isLocal ? "local" : "synced"
|
||||
|
||||
const session = {
|
||||
...sessionRaw,
|
||||
title: resolvedTitle ?? undefined,
|
||||
isLocal,
|
||||
syncStatus,
|
||||
}
|
||||
|
||||
return { session, messages }
|
||||
|
|
@ -282,10 +300,11 @@ class AIPersistServiceStatic {
|
|||
*/
|
||||
async ensureSession(
|
||||
chatId: string,
|
||||
options: { title?: string; createdAt?: Date; updatedAt?: Date } = {},
|
||||
options: { title?: string; createdAt?: Date; updatedAt?: Date; isLocal?: boolean } = {},
|
||||
): Promise<void> {
|
||||
const cachedExists = this.getSessionExistsFromCache(chatId)
|
||||
const shouldCheckDb = cachedExists !== true || options.title
|
||||
const shouldCheckDb =
|
||||
cachedExists !== true || options.title !== undefined || typeof options.isLocal === "boolean"
|
||||
|
||||
if (!shouldCheckDb) {
|
||||
return
|
||||
|
|
@ -311,6 +330,11 @@ class AIPersistServiceStatic {
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof options.isLocal === "boolean" && existing.isLocal !== options.isLocal) {
|
||||
updates.isLocal = options.isLocal
|
||||
shouldUpdate = true
|
||||
}
|
||||
|
||||
if (shouldUpdate) {
|
||||
updates.updatedAt = new Date()
|
||||
await db.update(aiChatTable).set(updates).where(eq(aiChatTable.chatId, chatId))
|
||||
|
|
@ -325,7 +349,7 @@ class AIPersistServiceStatic {
|
|||
|
||||
async createSession(
|
||||
chatId: string,
|
||||
options: { title?: string; createdAt?: Date; updatedAt?: Date } = {},
|
||||
options: { title?: string; createdAt?: Date; updatedAt?: Date; isLocal?: boolean } = {},
|
||||
) {
|
||||
const now = new Date()
|
||||
await db.insert(aiChatTable).values({
|
||||
|
|
@ -333,6 +357,7 @@ class AIPersistServiceStatic {
|
|||
title: this.resolveSessionTitle(chatId, options.title, { createdAt: now, updatedAt: now }),
|
||||
createdAt: options.createdAt ?? now,
|
||||
updatedAt: options.updatedAt ?? now,
|
||||
isLocal: options.isLocal ?? true,
|
||||
})
|
||||
// Mark session as existing in cache
|
||||
this.markSessionExists(chatId, true)
|
||||
|
|
@ -369,6 +394,7 @@ class AIPersistServiceStatic {
|
|||
title: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
isLocal: true,
|
||||
},
|
||||
})
|
||||
return result?.chatId ? result : null
|
||||
|
|
@ -381,6 +407,7 @@ class AIPersistServiceStatic {
|
|||
title: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
isLocal: true,
|
||||
},
|
||||
orderBy: (t, { desc }) => desc(t.updatedAt),
|
||||
limit,
|
||||
|
|
@ -408,12 +435,19 @@ class AIPersistServiceStatic {
|
|||
}),
|
||||
)
|
||||
|
||||
return normalizedChats.map((chat) => ({
|
||||
chatId: chat.chatId,
|
||||
title: chat.title,
|
||||
createdAt: chat.createdAt,
|
||||
updatedAt: chat.updatedAt,
|
||||
}))
|
||||
return normalizedChats.map((chat) => {
|
||||
const isLocal = Boolean(chat.isLocal)
|
||||
const syncStatus: "local" | "synced" = isLocal ? "local" : "synced"
|
||||
|
||||
return {
|
||||
chatId: chat.chatId,
|
||||
title: chat.title,
|
||||
createdAt: chat.createdAt,
|
||||
updatedAt: chat.updatedAt,
|
||||
isLocal,
|
||||
syncStatus,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async deleteSession(chatId: string) {
|
||||
|
|
@ -445,6 +479,10 @@ class AIPersistServiceStatic {
|
|||
.where(eq(aiChatTable.chatId, chatId))
|
||||
}
|
||||
|
||||
async markSessionSynced(chatId: string) {
|
||||
await this.ensureSession(chatId, { isLocal: false })
|
||||
}
|
||||
|
||||
async cleanupEmptySessions() {
|
||||
const emptySessions = await db.values<[string]>(
|
||||
sql`
|
||||
|
|
|
|||
|
|
@ -48,6 +48,42 @@ export class ChatSliceActions {
|
|||
return this.params[1]
|
||||
}
|
||||
|
||||
private computeSyncStatus(isLocal: boolean): "local" | "synced" {
|
||||
return isLocal ? "local" : "synced"
|
||||
}
|
||||
|
||||
private setSyncState(isLocal: boolean) {
|
||||
this.set((state) => {
|
||||
const nextStatus = this.computeSyncStatus(isLocal)
|
||||
if (state.isLocal === isLocal && state.syncStatus === nextStatus) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
isLocal,
|
||||
syncStatus: nextStatus,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async markSessionSynced() {
|
||||
const currentChatId = this.get().chatId
|
||||
if (!currentChatId) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.get().isLocal) {
|
||||
return
|
||||
}
|
||||
|
||||
this.setSyncState(false)
|
||||
|
||||
try {
|
||||
await AIPersistService.markSessionSynced(currentChatId)
|
||||
} catch (error) {
|
||||
console.error("Failed to mark chat session as synced:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// Direct message management methods (delegating to chat instance state)
|
||||
setMessages = (
|
||||
messagesParam: BizUIMessage[] | ((messages: BizUIMessage[]) => BizUIMessage[]),
|
||||
|
|
@ -176,8 +212,8 @@ export class ChatSliceActions {
|
|||
},
|
||||
options,
|
||||
)
|
||||
const response = await this.chatInstance.sendMessage(messageObj, finalOptions)
|
||||
return response
|
||||
|
||||
return await this.chatInstance.sendMessage(messageObj, finalOptions)
|
||||
} catch (error) {
|
||||
this.setError(error as Error)
|
||||
throw error
|
||||
|
|
@ -193,8 +229,7 @@ export class ChatSliceActions {
|
|||
},
|
||||
options,
|
||||
)
|
||||
const response = await this.chatInstance.regenerate({ messageId, ...finalOptions })
|
||||
return response
|
||||
return await this.chatInstance.regenerate({ messageId, ...finalOptions })
|
||||
} catch (error) {
|
||||
this.setError(error as Error)
|
||||
throw error
|
||||
|
|
@ -252,6 +287,8 @@ export class ChatSliceActions {
|
|||
isStreaming: false,
|
||||
currentTitle: undefined,
|
||||
chatInstance: newChatInstance,
|
||||
isLocal: true,
|
||||
syncStatus: "local",
|
||||
}))
|
||||
|
||||
// Update the reference
|
||||
|
|
@ -293,6 +330,8 @@ export class ChatSliceActions {
|
|||
isStreaming: false,
|
||||
currentTitle: chatSession?.title || undefined,
|
||||
chatInstance: newChatInstance,
|
||||
isLocal: chatSession ? chatSession.isLocal : true,
|
||||
syncStatus: chatSession ? chatSession.syncStatus : "local",
|
||||
}))
|
||||
|
||||
newChatInstance.resumeStream()
|
||||
|
|
|
|||
|
|
@ -61,11 +61,18 @@ export class ZustandChatState implements ChatState<BizUIMessage> {
|
|||
})
|
||||
|
||||
this.#eventEmitter.on("status", ({ status }) => {
|
||||
this.updateZustandState((state) => ({
|
||||
...state,
|
||||
status,
|
||||
isStreaming: status === "streaming",
|
||||
}))
|
||||
this.updateZustandState((state) => {
|
||||
const isStreaming = status === "streaming"
|
||||
if (isStreaming) {
|
||||
void state.chatActions.markSessionSynced()
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
status,
|
||||
isStreaming,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.#eventEmitter.on("error", ({ error }) => {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ export interface ChatSlice {
|
|||
status: ChatStatus
|
||||
error: Error | undefined
|
||||
isStreaming: boolean
|
||||
isLocal: boolean
|
||||
syncStatus: "local" | "synced"
|
||||
|
||||
// UI state
|
||||
currentTitle: string | undefined
|
||||
|
|
|
|||
|
|
@ -65,6 +65,21 @@ export const useHasMessages = () => {
|
|||
return store((state) => state.messages.length > 0)
|
||||
}
|
||||
|
||||
export const useIsLocalChat = () => {
|
||||
const store = useAIChatStore()
|
||||
return store((state) => state.isLocal)
|
||||
}
|
||||
|
||||
export const useSyncStatus = () => {
|
||||
const store = useAIChatStore()
|
||||
return store((state) => state.syncStatus)
|
||||
}
|
||||
|
||||
export const useSyncStateActions = () => {
|
||||
const store = useAIChatStore()
|
||||
return store((state) => state.chatActions)
|
||||
}
|
||||
|
||||
export const useChatBlockActions = () => useAIChatStore()((state) => state.blockActions)
|
||||
/**
|
||||
* Hook to get the chat status
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ import { createChatTitleHandler, createChatTransport } from "../transport"
|
|||
export const createChatSlice: (options: {
|
||||
chatId: string
|
||||
generateId?: IdGenerator
|
||||
isLocal?: boolean
|
||||
syncStatus?: "local" | "synced"
|
||||
}) => StateCreator<ChatSlice, [], [], ChatSlice> =
|
||||
(options) =>
|
||||
(...params) => {
|
||||
const [set, get] = params
|
||||
const { chatId, generateId } = options
|
||||
const { chatId, generateId, isLocal, syncStatus } = options
|
||||
|
||||
const chatInstance = new ZustandChat(
|
||||
{
|
||||
|
|
@ -43,6 +45,8 @@ export const createChatSlice: (options: {
|
|||
status: "ready",
|
||||
error: undefined,
|
||||
isStreaming: false,
|
||||
isLocal: isLocal ?? true,
|
||||
syncStatus: syncStatus ?? (isLocal === false ? "synced" : "local"),
|
||||
currentTitle: undefined,
|
||||
chatInstance,
|
||||
chatActions,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ export interface AIChatStoreInitial {
|
|||
blocks: AIChatContextBlock[]
|
||||
chatId?: string
|
||||
generateId?: IdGenerator
|
||||
isLocal?: boolean
|
||||
syncStatus?: "local" | "synced"
|
||||
}
|
||||
|
||||
export interface AIChatContextBlocks {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ export interface ChatSession {
|
|||
title?: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
isLocal: boolean
|
||||
syncStatus: "local" | "synced"
|
||||
}
|
||||
|
||||
export type RichTextPart = {
|
||||
|
|
|
|||
|
|
@ -49,10 +49,14 @@ export async function initializeDB() {
|
|||
try {
|
||||
const rows = await query(dbSqlite3, sql)
|
||||
if (method === "get") {
|
||||
return { rows: rows[0] || [] }
|
||||
} else {
|
||||
return { rows }
|
||||
if (rows.length > 0) {
|
||||
return { rows: rows[0] }
|
||||
}
|
||||
|
||||
return { rows: undefined }
|
||||
}
|
||||
|
||||
return { rows }
|
||||
} catch (error) {
|
||||
console.error(`Error executing SQL: ${sql} with params:${params}`, error)
|
||||
return { rows: [] }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
PRAGMA foreign_keys=OFF;--> statement-breakpoint
|
||||
CREATE TABLE `__new_ai_chat_messages` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`chat_id` text NOT NULL,
|
||||
`role` text NOT NULL,
|
||||
`created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
|
||||
`metadata` text,
|
||||
`status` text DEFAULT 'completed',
|
||||
`finished_at` integer,
|
||||
`message_parts` text,
|
||||
FOREIGN KEY (`chat_id`) REFERENCES `ai_chat_sessions`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
INSERT INTO `__new_ai_chat_messages`("id", "chat_id", "role", "created_at", "metadata", "status", "finished_at", "message_parts") SELECT "id", "chat_id", "role", "created_at", "metadata", "status", "finished_at", "message_parts" FROM `ai_chat_messages`;--> statement-breakpoint
|
||||
DROP TABLE `ai_chat_messages`;--> statement-breakpoint
|
||||
ALTER TABLE `__new_ai_chat_messages` RENAME TO `ai_chat_messages`;--> statement-breakpoint
|
||||
PRAGMA foreign_keys=ON;--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_chat_messages_chat_id_created_at` ON `ai_chat_messages` (`chat_id`,`created_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_chat_messages_status` ON `ai_chat_messages` (`status`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_chat_messages_chat_id_role` ON `ai_chat_messages` (`chat_id`,`role`);--> statement-breakpoint
|
||||
ALTER TABLE `ai_chat_sessions` ADD `is_local` integer DEFAULT false NOT NULL;
|
||||
|
|
@ -0,0 +1,947 @@
|
|||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "1ba7c166-20b5-473e-aea4-5fa6e99dff23",
|
||||
"prevId": "6cfe24ba-739c-4f3f-a894-dd70ecb47d02",
|
||||
"tables": {
|
||||
"ai_chat_messages": {
|
||||
"name": "ai_chat_messages",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"chat_id": {
|
||||
"name": "chat_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch() * 1000)"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": "'completed'"
|
||||
},
|
||||
"finished_at": {
|
||||
"name": "finished_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message_parts": {
|
||||
"name": "message_parts",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_ai_chat_messages_chat_id_created_at": {
|
||||
"name": "idx_ai_chat_messages_chat_id_created_at",
|
||||
"columns": ["chat_id", "created_at"],
|
||||
"isUnique": false
|
||||
},
|
||||
"idx_ai_chat_messages_status": {
|
||||
"name": "idx_ai_chat_messages_status",
|
||||
"columns": ["status"],
|
||||
"isUnique": false
|
||||
},
|
||||
"idx_ai_chat_messages_chat_id_role": {
|
||||
"name": "idx_ai_chat_messages_chat_id_role",
|
||||
"columns": ["chat_id", "role"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"ai_chat_messages_chat_id_ai_chat_sessions_id_fk": {
|
||||
"name": "ai_chat_messages_chat_id_ai_chat_sessions_id_fk",
|
||||
"tableFrom": "ai_chat_messages",
|
||||
"tableTo": "ai_chat_sessions",
|
||||
"columnsFrom": ["chat_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"ai_chat_sessions": {
|
||||
"name": "ai_chat_sessions",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch() * 1000)"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch() * 1000)"
|
||||
},
|
||||
"is_local": {
|
||||
"name": "is_local",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"idx_ai_chat_sessions_updated_at": {
|
||||
"name": "idx_ai_chat_sessions_updated_at",
|
||||
"columns": ["updated_at"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"collections": {
|
||||
"name": "collections",
|
||||
"columns": {
|
||||
"feed_id": {
|
||||
"name": "feed_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"entry_id": {
|
||||
"name": "entry_id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"view": {
|
||||
"name": "view",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"entries": {
|
||||
"name": "entries",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"content": {
|
||||
"name": "content",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"source_content": {
|
||||
"name": "source_content",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"readability_updated_at": {
|
||||
"name": "readability_updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"guid": {
|
||||
"name": "guid",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"author": {
|
||||
"name": "author",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"author_url": {
|
||||
"name": "author_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"author_avatar": {
|
||||
"name": "author_avatar",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"inserted_at": {
|
||||
"name": "inserted_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"published_at": {
|
||||
"name": "published_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"media": {
|
||||
"name": "media",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"categories": {
|
||||
"name": "categories",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"attachments": {
|
||||
"name": "attachments",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"extra": {
|
||||
"name": "extra",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"feed_id": {
|
||||
"name": "feed_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"inbox_handle": {
|
||||
"name": "inbox_handle",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"read": {
|
||||
"name": "read",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"sources": {
|
||||
"name": "sources",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"settings": {
|
||||
"name": "settings",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"feeds": {
|
||||
"name": "feeds",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"image": {
|
||||
"name": "image",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"error_at": {
|
||||
"name": "error_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"site_url": {
|
||||
"name": "site_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"owner_user_id": {
|
||||
"name": "owner_user_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"error_message": {
|
||||
"name": "error_message",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"subscription_count": {
|
||||
"name": "subscription_count",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updates_per_week": {
|
||||
"name": "updates_per_week",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"latest_entry_published_at": {
|
||||
"name": "latest_entry_published_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"tip_users": {
|
||||
"name": "tip_users",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"published_at": {
|
||||
"name": "published_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"images": {
|
||||
"name": "images",
|
||||
"columns": {
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"colors": {
|
||||
"name": "colors",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch() * 1000)"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"inboxes": {
|
||||
"name": "inboxes",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"secret": {
|
||||
"name": "secret",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"lists": {
|
||||
"name": "lists",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"feed_ids": {
|
||||
"name": "feed_ids",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"view": {
|
||||
"name": "view",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"image": {
|
||||
"name": "image",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"fee": {
|
||||
"name": "fee",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"owner_user_id": {
|
||||
"name": "owner_user_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"subscription_count": {
|
||||
"name": "subscription_count",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"purchase_amount": {
|
||||
"name": "purchase_amount",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"subscriptions": {
|
||||
"name": "subscriptions",
|
||||
"columns": {
|
||||
"feed_id": {
|
||||
"name": "feed_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"list_id": {
|
||||
"name": "list_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"inbox_id": {
|
||||
"name": "inbox_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"view": {
|
||||
"name": "view",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"is_private": {
|
||||
"name": "is_private",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"hide_from_timeline": {
|
||||
"name": "hide_from_timeline",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"category": {
|
||||
"name": "category",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"summaries": {
|
||||
"name": "summaries",
|
||||
"columns": {
|
||||
"entry_id": {
|
||||
"name": "entry_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"summary": {
|
||||
"name": "summary",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"readability_summary": {
|
||||
"name": "readability_summary",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"unq": {
|
||||
"name": "unq",
|
||||
"columns": ["entry_id", "language"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"translations": {
|
||||
"name": "translations",
|
||||
"columns": {
|
||||
"entry_id": {
|
||||
"name": "entry_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"content": {
|
||||
"name": "content",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"readability_content": {
|
||||
"name": "readability_content",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"translation-unique-index": {
|
||||
"name": "translation-unique-index",
|
||||
"columns": ["entry_id", "language"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"unread": {
|
||||
"name": "unread",
|
||||
"columns": {
|
||||
"subscription_id": {
|
||||
"name": "subscription_id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"count": {
|
||||
"name": "count",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"users": {
|
||||
"name": "users",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"handle": {
|
||||
"name": "handle",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"image": {
|
||||
"name": "image",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"is_me": {
|
||||
"name": "is_me",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email_verified": {
|
||||
"name": "email_verified",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"bio": {
|
||||
"name": "bio",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"website": {
|
||||
"name": "website",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"social_links": {
|
||||
"name": "social_links",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -246,6 +246,13 @@
|
|||
"when": 1753937164043,
|
||||
"tag": "0034_curly_darkstar",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 35,
|
||||
"version": "6",
|
||||
"when": 1761930812297,
|
||||
"tag": "0035_last_valeria_richards",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import m0031 from "./0031_kind_ikaris.sql"
|
|||
import m0032 from "./0032_orange_prima.sql"
|
||||
import m0033 from "./0033_shiny_sebastian_shaw.sql"
|
||||
import m0034 from "./0034_curly_darkstar.sql"
|
||||
import m0035 from "./0035_last_valeria_richards.sql"
|
||||
import journal from "./meta/_journal.json"
|
||||
|
||||
export default {
|
||||
|
|
@ -75,5 +76,6 @@ export default {
|
|||
m0032,
|
||||
m0033,
|
||||
m0034,
|
||||
m0035,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ export const aiChatTable = sqliteTable(
|
|||
.integer("updated_at", { mode: "timestamp_ms" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
isLocal: t.integer("is_local", { mode: "boolean" }).notNull().default(false),
|
||||
}),
|
||||
(table) => [index("idx_ai_chat_sessions_updated_at").on(table.updatedAt)],
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue