@ykurilov/agent-chat-storage-postgres 0.63.2 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/index.js.map +1 -1
- package/dist/types/drizzle-chat-storage.d.ts +2 -6
- package/dist/types/schema.d.ts +3 -7
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @ykurilov/agent-chat-storage-postgres
|
|
2
2
|
|
|
3
|
+
## 0.65.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [814ee7f]
|
|
8
|
+
- @ykurilov/agent-chat-core@0.65.0
|
|
9
|
+
|
|
10
|
+
## 0.64.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 99cded9: Подробности сбоя провайдера для админа. Ответ, упавший на провайдере, хранит `error.details`: провайдер, модель, код, причина одной строкой (до 300 знаков; ключи окружения, `Bearer`, значения `key=`/`token`/`api-key`/`password`, маски ключей со `*`, параметры адресов, `org-…`/`proj_…` и e-mail вычищены; модерация может повторять текст человека) и `resetsAt` — когда провайдер снимет предел (OpenRouter «resets 2026-11-01»; только будущее до двух лет, без пояса — UTC). В браузер подробности уходят только по новому праву `chatCapabilities` → `errorDetails: true` (по умолчанию `false`, при `modelDetails: false` тоже `false`) — в истории, потоке и при переподключении; остальным — только `error.kind`. `afterTurn` получает их всегда. Экран: подпись-функция `labels.errorText(error, plain)`, без неё или если она бросила исключение — прежний текст `labels.errors[kind]`; типы `ChatError`, `ChatErrorDetails`, помощник `customErrorText`. Хранилища: тип колонки `error` — `ChatError`, миграций нет.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [99cded9]
|
|
19
|
+
- @ykurilov/agent-chat-core@0.64.0
|
|
20
|
+
|
|
3
21
|
## 0.63.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/postgres-storage.ts","../src/drizzle-chat-storage.ts","../src/schema.ts","../src/migrate.ts"],"sourcesContent":["import type { ChatStorage } from \"@ykurilov/agent-chat-core\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport pg from \"pg\";\nimport { createDrizzleChatStorage, storageSchema } from \"./drizzle-chat-storage\";\nimport { migrateToLatest } from \"./migrate\";\n\nexport interface PostgresChatStorage extends ChatStorage {\n /** Закрывает соединения с базой. */\n close(): Promise<void>;\n}\n\nexport interface PostgresChatStorageOptions {\n /** Например `postgres://user:password@host:5432/database`. */\n connectionString: string;\n /** Сколько соединений держать открытыми. По умолчанию 10. */\n poolSize?: number;\n /** Журнал сервера: обрывы соединения. По умолчанию `console.error`. */\n logError?: (message: string) => void;\n}\n\nconst DEFAULT_POOL_SIZE = 10;\n\n/**\n * Хранилище в PostgreSQL. Таблицы лежат в схеме `agent_chat`; схема приводится к последней\n * миграции при создании, под блокировкой базы.\n */\nexport async function createPostgresChatStorage(options: PostgresChatStorageOptions): Promise<PostgresChatStorage> {\n const logError = options.logError ?? ((message: string) => console.error(message));\n const pool = new pg.Pool({ connectionString: options.connectionString, max: options.poolSize ?? DEFAULT_POOL_SIZE });\n // Без обработчика оборвавшееся соединение простаивающего пула роняет процесс.\n pool.on(\"error\", (error) => logError(`PostgreSQL: соединение оборвалось: ${error.message}`));\n try {\n await pool.query(\"select 1\");\n } catch (error) {\n await pool.end().catch(() => {});\n throw failure(\"Не удалось подключиться к PostgreSQL\", options.connectionString, error);\n }\n try {\n await migrateToLatest(pool);\n } catch (error) {\n await pool.end().catch(() => {});\n throw failure(\"Не удалось применить миграции PostgreSQL\", options.connectionString, error);\n }\n return {\n ...createDrizzleChatStorage(drizzle(pool, { schema: storageSchema })),\n async close() {\n await pool.end();\n },\n };\n}\n\n/** Ошибка без строки подключения: хост, порт и база берутся из разобранного адреса, пароль в текст не попадает. */\nfunction failure(summary: string, connectionString: string, cause: unknown): Error {\n const reason = cause instanceof Error ? cause.message : String(cause);\n let place = \"адрес не разобран\";\n try {\n const address = new URL(connectionString);\n place = `${address.hostname}:${address.port || \"5432\"}${address.pathname}`;\n } catch {\n // Адрес не разобрать — в текст ошибки он не попадает.\n }\n const safeReason = reason.split(connectionString).join(\"<строка подключения>\");\n return new Error(`${summary} (${place}): ${safeReason}`);\n}\n","import {\n assertChatDataFilter,\n assertKnownFormatVersion,\n ChatAlreadyExistsError,\n chatDataFields,\n chatDataOfInput,\n DuplicateChatSubjectError,\n DuplicateMessageError,\n isOptimizationBlocked,\n mergeChatData,\n MessageAlreadyFinishedError,\n MessageNotAwaitingError,\n RELEASED_ANSWER_ALIVE_AT,\n revertRefusal,\n sameMessageParts,\n} from \"@ykurilov/agent-chat-core\";\nimport type {\n AnswerAliveMark,\n Chat,\n ChatDataFilter,\n ChatListOptions,\n ChatStorage,\n ChatSubjectFilter,\n MemoryMergeGroup,\n MemoryNote,\n MemoryNoteInput,\n MemoryOptimizationRun,\n MergedMemoryNote,\n StoredMessage,\n} from \"@ykurilov/agent-chat-core\";\nimport { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, ne, sql } from \"drizzle-orm\";\nimport type { SQL } from \"drizzle-orm\";\nimport type { PgDatabase, PgQueryResultHKT } from \"drizzle-orm/pg-core\";\nimport { branchSelections, chats, chatTurnLeases, compactions, memoryNotes, memoryOptimizationRuns, messages, pendingBursts, spendingLimitStates, usageRecords, userModelChoices, voiceChoices } from \"./schema\";\n\nexport const storageSchema = { chats, messages, compactions, branchSelections, usageRecords, userModelChoices, voiceChoices, spendingLimitStates, memoryNotes, memoryOptimizationRuns };\n\n/** Слияние не сошлось со снимком: бросается внутри транзакции, чтобы откатить её, и не выходит наружу. */\nclass StaleMerge extends Error {}\n\n/** Любая база Drizzle для PostgreSQL: `pg` в проде, pglite в тестах. Схема должна быть уже создана. */\nexport type ChatDatabase = PgDatabase<PgQueryResultHKT, typeof storageSchema>;\n\n/** Время базы `moment` (timestamptz) строкой ISO в UTC, как `Date.toISOString()`: так оно сравнимо с `created_at`. */\nfunction isoAtDatabase(moment: SQL): SQL<string> {\n return sql<string>`to_char((${moment}) at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`;\n}\n\n/**\n * Знак жизни в колонку `alive_at`. «Сейчас» — по часам базы: копии сервера на разных машинах пишут и сравнивают знак\n * по одним часам, и расхождение часов машин не делает живой ответ брошенным.\n */\nfunction aliveAtColumn(alive: AnswerAliveMark | undefined): { aliveAt?: SQL<string> | string } {\n if (!alive) return {};\n return { aliveAt: alive === \"released\" ? RELEASED_ANSWER_ALIVE_AT : isoAtDatabase(sql`now()`) };\n}\n\n/** Запросы хранилища; соединением и миграциями занимается вызывающий. */\nexport function createDrizzleChatStorage(db: ChatDatabase): ChatStorage {\n /** Пишет в идущий ответ; отличает «нет такого» от «уже в конечном состоянии». */\n async function updateStreaming(\n messageId: string,\n { alive, ...values }: Partial<typeof messages.$inferInsert> & { alive?: AnswerAliveMark },\n ): Promise<void> {\n const updated = await db\n .update(messages)\n .set({ ...values, ...aliveAtColumn(alive) })\n .where(and(eq(messages.id, messageId), eq(messages.status, \"streaming\")))\n .returning({ id: messages.id });\n if (updated.length > 0) return;\n const [existing] = await db.select({ id: messages.id }).from(messages).where(eq(messages.id, messageId));\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n throw new MessageAlreadyFinishedError(messageId);\n }\n\n /** Запросы в транзакции или без неё: транзакция Drizzle умеет то же, что и база. */\n type Executor = ChatDatabase;\n\n /** Записи человека пишутся по одному: замок держится до конца транзакции. Без него две вставки видят одинаковый список и обе проходят проверку. */\n async function lockMemoryNotes(tx: Executor, ownerId: string): Promise<void> {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtextextended(${`agent_chat.memory_notes:${ownerId}`}, 0))`);\n }\n\n async function visibleNotes(exec: Executor, ownerId: string): Promise<MemoryNote[]> {\n const rows = await exec\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNull(memoryNotes.mergedInto)))\n // Идентификаторы сравниваются по кодам знаков, как в договоре, а не по правилам языка базы.\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n return rows.map(toMemoryNote);\n }\n\n async function insertNotes(exec: Executor, ownerId: string, inputs: MemoryNoteInput[]): Promise<MemoryNote[]> {\n inputs.forEach(assertWellFormedNote);\n if (inputs.length === 0) return [];\n const now = new Date();\n // Одна вставка: пакет ложится целиком или не ложится вовсе.\n const rows = await exec\n .insert(memoryNotes)\n .values(\n inputs.map(({ categories, content }) => ({\n id: crypto.randomUUID(),\n ownerId,\n categories: [...categories],\n content,\n version: 1,\n createdAt: now,\n updatedAt: now,\n })),\n )\n .returning();\n return rows.map(toMemoryNote);\n }\n\n async function updateNote(exec: Executor, ownerId: string, id: string, expectedVersion: number, input: MemoryNoteInput): Promise<MemoryNote | \"not_found\" | \"stale_version\"> {\n assertWellFormedNote(input);\n const updated = await exec\n .update(memoryNotes)\n .set({ categories: [...input.categories], content: input.content, version: sql`${memoryNotes.version} + 1`, updatedAt: new Date() })\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, expectedVersion), isNull(memoryNotes.mergedInto)))\n .returning();\n if (updated[0]) return toMemoryNote(updated[0]);\n return (await memoryNoteExists(exec, ownerId, id)) ? \"stale_version\" : \"not_found\";\n }\n\n async function memoryNoteExists(exec: Executor, ownerId: string, id: string): Promise<boolean> {\n const [existing] = await exec\n .select({ id: memoryNotes.id })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), isNull(memoryNotes.mergedInto)));\n return existing !== undefined;\n }\n\n return {\n async createChat({ createdAt, ...input }) {\n const at = createdAt ?? new Date().toISOString();\n const row = chatRow({ ...input, createdAt: at, updatedAt: at });\n try {\n await db.insert(chats).values(row);\n } catch (error) {\n if (isConflictOn(error, \"chats_owner_subject_idx\")) throw new DuplicateChatSubjectError(input.ownerId, input.subjectKey!);\n throw error;\n }\n return toChat(row);\n },\n\n async findChatBySubject(ownerId, subjectKey) {\n const [row] = await db.select().from(chats).where(and(eq(chats.ownerId, ownerId), eq(chats.subjectKey, subjectKey)));\n return row ? toChat(row) : null;\n },\n\n async importChat(chat, imported) {\n // Ошибка внутри транзакции откатывает её целиком: ни чата, ни сообщений.\n await db.transaction(async (tx) => {\n try {\n await tx.insert(chats).values(chatRow(chat));\n } catch (error) {\n if (isConflictOn(error, \"chats_owner_subject_idx\")) throw new DuplicateChatSubjectError(chat.ownerId, chat.subjectKey!);\n if (isConflictOn(error, \"chats_pkey\")) throw new ChatAlreadyExistsError(chat.id);\n throw error;\n }\n // По одному: порядок записи (`seq`) — порядок сообщений при равном времени создания.\n for (const message of imported) {\n const { alive: _alive, ...stored } = message;\n try {\n await tx.insert(messages).values(stored);\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n }\n });\n },\n\n async setAfterTurnState(messageId, state, options) {\n // Строка заперта до конца транзакции: другая копия сервера не закроет хук между проверкой и записью.\n return db.transaction(async (tx) => {\n const [existing] = await tx\n .select({ parts: messages.parts, afterTurn: messages.afterTurn })\n .from(messages)\n .where(eq(messages.id, messageId))\n .for(\"update\");\n if (!existing || (state !== \"pending\" && existing.afterTurn !== \"pending\")) return false;\n await tx\n .update(messages)\n .set({\n afterTurn: state,\n ...(options?.appendParts && { parts: [...existing.parts, ...options.appendParts] }),\n // Отметка ожидания хука — в колонке знака жизни, по часам базы: у законченного ответа она больше ни для чего.\n ...(state === \"pending\" && aliveAtColumn(\"now\")),\n })\n .where(eq(messages.id, messageId));\n return true;\n });\n },\n\n async listPendingAfterTurn(filter) {\n const pending = eq(messages.afterTurn, \"pending\");\n const rows = await db\n .select({ id: messages.id })\n .from(messages)\n .where(\n filter?.pendingForMs === undefined\n ? pending\n : and(\n pending,\n sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${isoAtDatabase(sql`now() - ${filter.pendingForMs} * interval '1 millisecond'`)}`,\n ),\n );\n return rows.map((row) => row.id);\n },\n\n async getChat(chatId) {\n const [chat] = await db.select().from(chats).where(eq(chats.id, chatId));\n return chat ? toChat(chat) : null;\n },\n\n async updateChatModel(chatId, model) {\n await db\n .update(chats)\n .set({ modelId: model.modelId, providerId: model.providerId, reasoning: model.reasoning ?? null })\n .where(eq(chats.id, chatId));\n },\n\n async updateChatData(chatId, patch, { maxBytes }) {\n // Строка чата блокируется на время слияния: параллельные правки идут по очереди и не затирают друг друга.\n return db.transaction(async (tx) => {\n const [row] = await tx.select().from(chats).where(eq(chats.id, chatId)).for(\"update\");\n if (!row) return null;\n const merged = mergeChatData(row.subjectData ?? undefined, patch, maxBytes);\n await tx.update(chats).set({ subjectData: merged ?? null }).where(eq(chats.id, chatId));\n return toChat({ ...row, subjectData: merged ?? null });\n });\n },\n\n async listChats(ownerId, options?: ChatListOptions) {\n if (options?.data) assertChatDataFilter(options.data);\n const rows = await db\n .select()\n .from(chats)\n .where(and(eq(chats.ownerId, ownerId), subjectCondition(options?.subjects), dataCondition(options?.data)))\n .orderBy(desc(chats.updatedAt), desc(chats.createdAt), desc(chats.id));\n return rows.map(toChat);\n },\n\n async renameChat(chatId, title) {\n await db.update(chats).set({ title }).where(eq(chats.id, chatId));\n },\n\n async setChatClosed(chatId, closed) {\n await db.update(chats).set({ closed: closed && { code: closed.code, message: closed.message } }).where(eq(chats.id, chatId));\n },\n\n async deleteChat(chatId) {\n await db.transaction(async (tx) => {\n await tx.delete(compactions).where(eq(compactions.chatId, chatId));\n await tx.delete(branchSelections).where(eq(branchSelections.chatId, chatId));\n await tx.delete(messages).where(eq(messages.chatId, chatId));\n await tx.delete(chats).where(eq(chats.id, chatId));\n await tx.delete(chatTurnLeases).where(eq(chatTurnLeases.chatId, chatId));\n await tx.delete(pendingBursts).where(eq(pendingBursts.chatId, chatId));\n });\n },\n\n async claimChatTurn(chatId, holder, leaseMs) {\n // Одной записью по часам базы: свободный чат — вставка; своя или просроченная чужая — замена; живая чужая — ничего.\n // Две копии разом: вторая ждёт строку первой и видит её живой.\n const until = sql`now() + ${leaseMs} * interval '1 millisecond'`;\n const claimed = await db\n .insert(chatTurnLeases)\n .values({ chatId, holder, until })\n .onConflictDoUpdate({\n target: chatTurnLeases.chatId,\n set: { holder, until },\n setWhere: sql`${chatTurnLeases.holder} = ${holder} or ${chatTurnLeases.until} <= now()`,\n })\n .returning({ chatId: chatTurnLeases.chatId });\n return claimed.length > 0;\n },\n\n async releaseChatTurn(chatId, holder) {\n await db.delete(chatTurnLeases).where(and(eq(chatTurnLeases.chatId, chatId), eq(chatTurnLeases.holder, holder)));\n },\n\n async clearChatTurnLeases() {\n await db.delete(chatTurnLeases);\n },\n\n async savePendingBurst(burst) {\n const row = {\n chatId: burst.chatId,\n ownerId: burst.ownerId,\n messageId: burst.messageId,\n dueAt: new Date(burst.dueAt),\n holder: burst.holder,\n heldUntil: new Date(burst.heldUntil),\n page: burst.page ?? null,\n };\n await db.insert(pendingBursts).values(row).onConflictDoUpdate({ target: pendingBursts.chatId, set: row });\n },\n\n async takeAbandonedBursts({ abandonedBefore, holder, heldUntil, limit, exceptHolder }) {\n const notOwn = exceptHolder === undefined ? undefined : ne(pendingBursts.holder, exceptHolder);\n // Выбор и захват — одной записью; строки, которые прямо сейчас берёт другая копия, пропускаются.\n const abandoned = db\n .select({ chatId: pendingBursts.chatId })\n .from(pendingBursts)\n .where(and(lte(pendingBursts.heldUntil, new Date(abandonedBefore)), notOwn))\n .orderBy(asc(pendingBursts.dueAt))\n .limit(limit)\n .for(\"update\", { skipLocked: true });\n const taken = await db\n .update(pendingBursts)\n .set({ holder, heldUntil: new Date(heldUntil) })\n .where(and(inArray(pendingBursts.chatId, abandoned), lte(pendingBursts.heldUntil, new Date(abandonedBefore)), notOwn))\n .returning();\n return taken\n .sort((first, second) => first.dueAt.getTime() - second.dueAt.getTime())\n .map((row) => ({\n chatId: row.chatId,\n ownerId: row.ownerId,\n messageId: row.messageId,\n dueAt: row.dueAt.toISOString(),\n holder,\n heldUntil,\n ...(row.page && { page: row.page }),\n }));\n },\n\n async renewPendingBurst({ chatId, messageId, holder, heldUntil }) {\n const renewed = await db\n .update(pendingBursts)\n .set({ heldUntil: new Date(heldUntil) })\n .where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId), eq(pendingBursts.holder, holder)))\n .returning({ chatId: pendingBursts.chatId });\n return renewed.length > 0;\n },\n\n async removePendingBurst(chatId, messageId) {\n await db.delete(pendingBursts).where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId)));\n },\n\n async getMessage(messageId) {\n const [row] = await db.select().from(messages).where(eq(messages.id, messageId));\n if (!row) return null;\n const message = toMessage(row);\n assertKnownFormatVersion(message);\n return message;\n },\n\n async listMessages(chatId) {\n const rows = await db\n .select()\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n const found: StoredMessage[] = rows.map(toMessage);\n found.forEach(assertKnownFormatVersion);\n return found;\n },\n\n async listMessageLinks(chatId) {\n return db\n .select({ id: messages.id, parentId: messages.parentId, createdAt: messages.createdAt })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n },\n\n // Части нужных типов выбираются внутри базы: тексты и выводы инструментов в процесс не идут.\n async listMessagePartsOfTypes(chatId, types) {\n const wanted = JSON.stringify([...types]);\n const rows = await db\n .select({\n id: messages.id,\n parentId: messages.parentId,\n createdAt: messages.createdAt,\n parts: sql<unknown>`(select coalesce(json_agg(part.value order by part.position), '[]'::json) from json_array_elements(${messages.parts}) with ordinality as part(value, position) where part.value->>'type' in (select json_array_elements_text(${wanted}::json)))`,\n })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n return rows.map((row) => ({ ...row, parts: (typeof row.parts === \"string\" ? JSON.parse(row.parts) : row.parts) as StoredMessage[\"parts\"] }));\n },\n\n async insertMessage(message) {\n try {\n await db.transaction(async (tx) => {\n const { alive, ...stored } = message;\n await tx.insert(messages).values({ ...stored, ...aliveAtColumn(alive) });\n await tx.update(chats).set({ updatedAt: message.createdAt }).where(eq(chats.id, message.chatId));\n });\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n },\n\n updateStreamingMessage: (messageId, patch) => updateStreaming(messageId, patch),\n\n markAnswerAlive: (messageId) => updateStreaming(messageId, { alive: \"now\" }),\n\n finishMessage: (messageId, final) => updateStreaming(messageId, { ...final, ...(final.afterTurn === \"pending\" && { alive: \"now\" as const }) }),\n\n async updateAwaitingMessage(messageId, patch) {\n // Строка заперта до конца транзакции: другая копия сервера не запишет между сравнением частей и записью.\n await db.transaction(async (tx) => {\n const [existing] = await tx\n .select({ status: messages.status, parts: messages.parts })\n .from(messages)\n .where(eq(messages.id, messageId))\n .for(\"update\");\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n if (existing.status !== \"awaiting_approval\") throw new MessageNotAwaitingError(messageId);\n if (patch.expectedParts && !sameMessageParts(existing.parts, patch.expectedParts)) throw new MessageNotAwaitingError(messageId);\n await tx\n .update(messages)\n .set({ parts: patch.parts, ...(patch.status && { status: patch.status }), ...aliveAtColumn(patch.alive) })\n .where(eq(messages.id, messageId));\n });\n },\n\n async listStreamingMessageIds() {\n const rows = await db.select({ id: messages.id }).from(messages).where(eq(messages.status, \"streaming\")).orderBy(asc(messages.seq));\n return rows.map((row) => row.id);\n },\n\n async listSilentAnswerIds({ silentForMs, chatId }) {\n const silent = sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${isoAtDatabase(sql`now() - ${silentForMs} * interval '1 millisecond'`)}`;\n const rows = await db\n .select({ id: messages.id })\n .from(messages)\n .where(and(eq(messages.status, \"streaming\"), silent, chatId === undefined ? undefined : eq(messages.chatId, chatId)))\n .orderBy(asc(messages.seq));\n return rows.map((row) => row.id);\n },\n\n async insertCompaction(record) {\n await db.insert(compactions).values(record);\n },\n\n async listCompactions(chatId) {\n const rows = await db.select().from(compactions).where(eq(compactions.chatId, chatId)).orderBy(asc(compactions.seq));\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertBranchSelection(record) {\n await db.insert(branchSelections).values(record);\n },\n\n async listBranchSelections(chatId) {\n const rows = await db.select().from(branchSelections).where(eq(branchSelections.chatId, chatId)).orderBy(asc(branchSelections.seq));\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertUsageRecord(record) {\n await db.insert(usageRecords).values(record);\n },\n\n async hasUsageRecord(id) {\n const rows = await db.select({ id: usageRecords.id }).from(usageRecords).where(eq(usageRecords.id, id)).limit(1);\n return rows.length > 0;\n },\n\n async sumUsage({ ownerId, chatId, messageId, source, since }) {\n const filters = [\n ...(ownerId !== undefined ? [eq(usageRecords.ownerId, ownerId)] : []),\n ...(chatId !== undefined ? [eq(usageRecords.chatId, chatId)] : []),\n ...(messageId !== undefined ? [eq(usageRecords.messageId, messageId)] : []),\n ...(source !== undefined ? [eq(usageRecords.source, source)] : []),\n ...(since !== undefined ? [gte(usageRecords.createdAt, since)] : []),\n ];\n // sum() по bigint приходит строкой: суммы токенов помещаются в число.\n return db\n .select({\n modelId: usageRecords.modelId,\n providerId: usageRecords.providerId,\n inputTokens: sql<number>`sum(${usageRecords.inputTokens})`.mapWith(Number),\n cachedInputTokens: sql<number>`sum(${usageRecords.cachedInputTokens})`.mapWith(Number),\n cacheWriteTokens: sql<number>`sum(${usageRecords.cacheWriteTokens})`.mapWith(Number),\n outputTokens: sql<number>`sum(${usageRecords.outputTokens})`.mapWith(Number),\n reasoningTokens: sql<number>`sum(${usageRecords.reasoningTokens})`.mapWith(Number),\n costUsd: sql<number>`sum(${usageRecords.costUsd})`.mapWith(Number),\n })\n .from(usageRecords)\n .where(and(...filters))\n .groupBy(usageRecords.modelId, usageRecords.providerId);\n },\n\n async sumUsageByChat({ chatIds, ownerId, source, since }) {\n if (chatIds.length === 0) return [];\n const filters = [\n inArray(usageRecords.chatId, [...chatIds]),\n ...(ownerId !== undefined ? [eq(usageRecords.ownerId, ownerId)] : []),\n ...(source !== undefined ? [eq(usageRecords.source, source)] : []),\n ...(since !== undefined ? [gte(usageRecords.createdAt, since)] : []),\n ];\n return db\n .select({\n chatId: usageRecords.chatId,\n modelId: usageRecords.modelId,\n providerId: usageRecords.providerId,\n inputTokens: sql<number>`sum(${usageRecords.inputTokens})`.mapWith(Number),\n cachedInputTokens: sql<number>`sum(${usageRecords.cachedInputTokens})`.mapWith(Number),\n cacheWriteTokens: sql<number>`sum(${usageRecords.cacheWriteTokens})`.mapWith(Number),\n outputTokens: sql<number>`sum(${usageRecords.outputTokens})`.mapWith(Number),\n reasoningTokens: sql<number>`sum(${usageRecords.reasoningTokens})`.mapWith(Number),\n costUsd: sql<number>`sum(${usageRecords.costUsd})`.mapWith(Number),\n })\n .from(usageRecords)\n .where(and(...filters))\n .groupBy(usageRecords.chatId, usageRecords.modelId, usageRecords.providerId);\n },\n\n async getUserModelChoice(ownerId) {\n const [row] = await db.select().from(userModelChoices).where(eq(userModelChoices.ownerId, ownerId));\n if (!row) return null;\n return { modelId: row.modelId, providerId: row.providerId, ...(row.reasoning !== null && { reasoning: row.reasoning }) };\n },\n\n async saveUserModelChoice(ownerId, choice) {\n const values = { modelId: choice.modelId, providerId: choice.providerId, reasoning: choice.reasoning ?? null, updatedAt: new Date().toISOString() };\n await db.insert(userModelChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: userModelChoices.ownerId, set: values });\n },\n\n async setVoiceCut({ ownerId, chatId, messageId, voiceCut }) {\n await db\n .update(messages)\n .set({ voiceCut })\n .where(\n and(\n eq(messages.id, messageId),\n eq(messages.chatId, chatId),\n sql`exists (select 1 from ${chats} where ${chats.id} = ${chatId} and ${chats.ownerId} = ${ownerId})`,\n ),\n );\n },\n\n async getSpendingLimitState(key) {\n const [row] = await db.select().from(spendingLimitStates).where(eq(spendingLimitStates.key, key));\n return row ? { value: row.value, version: row.version } : null;\n },\n\n // Одна команда без чтения: вставка или правка срабатывает только при совпавшей версии, из двух одновременных проходит одна.\n async saveSpendingLimitState(key, value, expectedVersion) {\n const updatedAt = new Date().toISOString();\n if (expectedVersion === null) {\n const inserted = await db\n .insert(spendingLimitStates)\n .values({ key, value, version: 1, updatedAt })\n .onConflictDoNothing()\n .returning({ key: spendingLimitStates.key });\n return inserted.length === 1;\n }\n const updated = await db\n .update(spendingLimitStates)\n .set({ value, version: expectedVersion + 1, updatedAt })\n .where(and(eq(spendingLimitStates.key, key), eq(spendingLimitStates.version, expectedVersion)))\n .returning({ key: spendingLimitStates.key });\n return updated.length === 1;\n },\n\n async deleteSpendingLimitStates(keys) {\n if (keys.length > 0) await db.delete(spendingLimitStates).where(inArray(spendingLimitStates.key, keys));\n },\n\n async getVoiceChoice(ownerId) {\n const [row] = await db.select().from(voiceChoices).where(eq(voiceChoices.ownerId, ownerId));\n return row?.voiceId ?? null;\n },\n\n async setVoiceChoice(ownerId, voiceId) {\n const values = { voiceId, updatedAt: new Date().toISOString() };\n await db.insert(voiceChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: voiceChoices.ownerId, set: values });\n },\n\n async listMemoryNotes(ownerId) {\n return visibleNotes(db, ownerId);\n },\n\n async insertMemoryNotes(ownerId, inputs) {\n return insertNotes(db, ownerId, inputs);\n },\n\n async insertMemoryNotesChecked(ownerId, inputs, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const error = guard(await visibleNotes(tx, ownerId));\n return error ?? (await insertNotes(tx, ownerId, inputs));\n });\n },\n\n async updateMemoryNote(ownerId, id, expectedVersion, input) {\n return updateNote(db, ownerId, id, expectedVersion, input);\n },\n\n async updateMemoryNoteChecked(ownerId, id, expectedVersion, input, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const error = guard(await visibleNotes(tx, ownerId));\n return error ?? (await updateNote(tx, ownerId, id, expectedVersion, input));\n });\n },\n\n async deleteMemoryNote(ownerId, id, expectedVersion) {\n const deleted = await db.transaction(async (tx) => {\n const rows = await tx\n .delete(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, expectedVersion), isNull(memoryNotes.mergedInto)))\n .returning({ id: memoryNotes.id });\n // Скрытые оригиналы слияния уходят вместе с результатом.\n if (rows.length > 0) await tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, id)));\n return rows.length > 0;\n });\n if (deleted) return \"ok\";\n return (await memoryNoteExists(db, ownerId, id)) ? \"stale_version\" : \"not_found\";\n },\n\n async clearMemoryNotes(ownerId) {\n return db.transaction(async (tx) => {\n const deleted = await tx.delete(memoryNotes).where(eq(memoryNotes.ownerId, ownerId)).returning({ mergedInto: memoryNotes.mergedInto });\n await tx.delete(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId));\n // Считаются записи, которые человек видел; скрытые оригиналы — служебные.\n return deleted.filter((row) => row.mergedInto === null).length;\n });\n },\n\n // Взятие запуска — одна транзакция под замком человека: проверка правил и вставка не разрываются между процессами.\n async claimMemoryOptimizationRun(ownerId, rules, now) {\n const nowMs = Date.parse(now);\n return db.transaction(async (tx) => {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtextextended(${`agent_chat.memory_optimization:${ownerId}`}, 0))`);\n const runs = await tx.select().from(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId));\n const state = runs.map((run) => {\n const leaseEnd = run.startedAt.getTime() + rules.leaseMs;\n const expired = run.status === \"running\" && nowMs >= leaseEnd;\n return { status: expired ? \"failed\" : run.status, endedAt: expired ? leaseEnd : (run.finishedAt ?? run.startedAt).getTime(), expired, id: run.id };\n });\n for (const run of state.filter((item) => item.expired)) {\n await tx\n .update(memoryOptimizationRuns)\n .set({ status: \"failed\", error: \"lease_expired\", finishedAt: new Date(run.endedAt) })\n .where(eq(memoryOptimizationRuns.id, run.id));\n }\n const blocked = isOptimizationBlocked(\n runs.map((run, index) => ({ status: state[index]!.status, startedAtMs: run.startedAt.getTime(), endedAtMs: state[index]!.endedAt })),\n rules,\n nowMs,\n );\n if (blocked) return null;\n const [created] = await tx\n .insert(memoryOptimizationRuns)\n .values({ id: crypto.randomUUID(), ownerId, startedAt: new Date(nowMs), status: \"running\" })\n .returning();\n return toOptimizationRun(created!);\n });\n },\n\n async finishMemoryOptimizationRun(ownerId, runId, outcome) {\n const finished = await db\n .update(memoryOptimizationRuns)\n .set({ status: outcome.status, finishedAt: new Date(outcome.finishedAt), error: outcome.error ?? null, usageRecordId: outcome.usageRecordId ?? null })\n .where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId), eq(memoryOptimizationRuns.status, \"running\")))\n .returning({ id: memoryOptimizationRuns.id });\n return finished.length > 0 ? \"ok\" : \"not_found\";\n },\n\n // Слияние — одна транзакция: несошедшийся оригинал бросает StaleMerge, и откатывается всё, включая запуск.\n async applyMemoryMerge(ownerId, merge) {\n const { merges } = merge;\n if (merges.length === 0) throw new TypeError(\"Слияние без склеек\");\n const seen = new Set<string>();\n for (const { result, originals } of merges) {\n assertWellFormedNote(result);\n if (originals.length === 0) throw new TypeError(\"Склейка без оригиналов\");\n for (const { id } of originals) {\n if (seen.has(id)) throw new TypeError(`Запись ${id} названа в двух склейках`);\n seen.add(id);\n }\n }\n try {\n return await db.transaction(async (tx) => {\n const [run] = await tx\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.id, merge.runId), eq(memoryOptimizationRuns.ownerId, ownerId)))\n .for(\"update\");\n if (run?.status !== \"running\") return \"run_not_active\" as const;\n const now = new Date();\n const groups: MemoryMergeGroup[] = [];\n for (const { result, originals } of merges) {\n const created = { id: crypto.randomUUID(), ownerId, categories: [...result.categories], content: result.content, version: 1, createdAt: now, updatedAt: now };\n await tx.insert(memoryNotes).values(created);\n // Оригинал прячется, только если он ещё обычный и той же версии; условие проверяет сама база.\n for (const { id, version } of originals) {\n const hidden = await tx\n .update(memoryNotes)\n .set({ mergedInto: created.id })\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, version), isNull(memoryNotes.mergedInto)))\n .returning({ id: memoryNotes.id });\n if (hidden.length === 0) throw new StaleMerge();\n }\n groups.push({ resultId: created.id, originalIds: originals.map(({ id }) => id), resultVersion: 1 });\n }\n const [finished] = await tx\n .update(memoryOptimizationRuns)\n .set({ status: \"applied\", finishedAt: new Date(merge.finishedAt), groups, usageRecordId: merge.usageRecordId ?? null })\n .where(eq(memoryOptimizationRuns.id, run.id))\n .returning();\n return toOptimizationRun(finished!);\n });\n } catch (error) {\n if (error instanceof StaleMerge) return \"stale_version\";\n throw error;\n }\n },\n\n async revertMemoryMerge(ownerId, runId, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const [run] = await tx\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId)))\n .for(\"update\");\n if (run?.status !== \"applied\") return \"not_found\" as const;\n for (const { resultId, originalIds, resultVersion } of run.groups) {\n const [result] = await tx\n .select({ version: memoryNotes.version })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, resultId), isNull(memoryNotes.mergedInto)))\n .for(\"update\");\n if (result?.version !== resultVersion) return \"conflict\" as const;\n const hidden = await tx\n .select({ id: memoryNotes.id })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId), inArray(memoryNotes.id, originalIds)))\n .for(\"update\");\n if (hidden.length !== originalIds.length) return \"conflict\" as const;\n }\n if (guard) {\n const resultIds = run.groups.map(({ resultId }) => resultId);\n const remaining = (await visibleNotes(tx, ownerId)).filter((note) => !resultIds.includes(note.id));\n const restoredRows = await tx\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), inArray(memoryNotes.mergedInto, resultIds)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n const error = guard(remaining, restoredRows.map(toMemoryNote));\n if (error) return revertRefusal(error);\n }\n for (const { resultId } of run.groups) {\n await tx.update(memoryNotes).set({ mergedInto: null }).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId)));\n await tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, resultId)));\n }\n await tx.update(memoryOptimizationRuns).set({ status: \"reverted\" }).where(eq(memoryOptimizationRuns.id, run.id));\n return \"ok\" as const;\n });\n },\n\n async listMemoryOptimizationRuns(ownerId, filter) {\n const query = db\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.ownerId, ownerId), ...(filter?.status ? [inArray(memoryOptimizationRuns.status, filter.status)] : [])))\n .orderBy(desc(memoryOptimizationRuns.startedAt), sql`${memoryOptimizationRuns.id} collate \"C\" desc`);\n const rows = await (filter?.limit === undefined ? query : query.limit(filter.limit));\n return rows.map(toOptimizationRun);\n },\n\n async listMergedMemoryNotes(ownerId) {\n const rows = await db\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNotNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n return rows.map((row): MergedMemoryNote => ({ ...toMemoryNote(row), mergedInto: row.mergedInto! }));\n },\n };\n}\n\ntype UniqueViolation = { code?: unknown; constraint?: unknown; cause?: UniqueViolation };\n\nfunction isPrimaryKeyConflict(error: unknown): boolean {\n return isConflictOn(error, \"messages_pkey\");\n}\n\n/** Нарушен уникальный ключ или индекс с этим именем. */\nfunction isConflictOn(error: unknown, constraintName: string): boolean {\n const { code, constraint, cause } = (error ?? {}) as UniqueViolation;\n return [code, cause?.code].includes(\"23505\") && [constraint, cause?.constraint].includes(constraintName);\n}\n\n/** Запись чата в строку: поле без значения — пусто. */\nfunction chatRow(chat: Chat): typeof chats.$inferSelect {\n return {\n id: chat.id,\n ownerId: chat.ownerId,\n modelId: chat.modelId,\n providerId: chat.providerId,\n reasoning: chat.reasoning ?? null,\n title: chat.title ?? null,\n origin: chat.origin ?? null,\n subjectKey: chat.subjectKey ?? null,\n subjectData: chatDataOfInput(chat) ?? null,\n closed: chat.closed ?? null,\n createdAt: chat.createdAt,\n updatedAt: chat.updatedAt,\n };\n}\n\n/** Строка чата в запись ядра: пустые необязательные поля — отсутствие поля. */\nfunction toChat(row: typeof chats.$inferSelect): Chat {\n const { reasoning, title, origin, subjectKey, subjectData, closed, ...chat } = row;\n return {\n ...chat,\n ...(reasoning !== null && { reasoning }),\n ...(title !== null && { title }),\n ...(origin !== null && { origin }),\n ...(subjectKey !== null && { subjectKey }),\n ...chatDataFields(subjectData),\n ...(closed !== null && { closed }),\n };\n}\n\n/** Фильтр `listChats` по ключу объекта; по умолчанию — только чаты без ключа. */\nfunction subjectCondition(subjects: ChatSubjectFilter = \"exclude\") {\n if (subjects === \"include\") return undefined;\n return subjects === \"only\" ? isNotNull(chats.subjectKey) : isNull(chats.subjectKey);\n}\n\n/** Фильтр `listChats` по данным чата: одно «содержит» (`@>`) по всем ключам; тип значения важен (`true` не равно `1`). */\nfunction dataCondition(filter: ChatDataFilter | undefined) {\n if (!filter || Object.keys(filter).length === 0) return undefined;\n return sql`${chats.subjectData}::jsonb @> ${JSON.stringify(filter)}::jsonb`;\n}\n\n/** Строка сообщения в запись ядра: без служебных колонок; пустое состояние хука итога — отсутствие поля. */\nfunction toMessage(row: typeof messages.$inferSelect): StoredMessage {\n const { seq: _seq, aliveAt: _aliveAt, afterTurn, ...message } = row;\n return { ...message, ...(afterTurn !== null && { afterTurn }) };\n}\n\n/** Строка памяти в запись ядра: без владельца, время — ISO 8601. */\nfunction toMemoryNote(row: typeof memoryNotes.$inferSelect): MemoryNote {\n return {\n id: row.id,\n categories: [...row.categories],\n content: row.content,\n version: row.version,\n createdAt: row.createdAt.toISOString(),\n updatedAt: row.updatedAt.toISOString(),\n };\n}\n\n/** Строка запуска в запись ядра: без владельца, время — ISO 8601. */\nfunction toOptimizationRun(row: typeof memoryOptimizationRuns.$inferSelect): MemoryOptimizationRun {\n return {\n id: row.id,\n startedAt: row.startedAt.toISOString(),\n finishedAt: row.finishedAt ? row.finishedAt.toISOString() : null,\n status: row.status,\n groups: row.groups.map((group) => ({ ...group, originalIds: [...group.originalIds] })),\n error: row.error,\n usageRecordId: row.usageRecordId,\n };\n}\n\n/** Как база с NOT NULL: разделы — список строк, текст — строка. Иначе jsonb принял бы любое значение. */\nfunction assertWellFormedNote(note: MemoryNoteInput): void {\n if (!Array.isArray(note?.categories) || !note.categories.every((category) => typeof category === \"string\")) {\n throw new TypeError(\"Разделы записи памяти — список строк\");\n }\n if (typeof note.content !== \"string\") throw new TypeError(\"Текст записи памяти — строка\");\n}\n","import type {\n AnswerStatus,\n ChatClosure,\n ChatErrorKind,\n MemoryMergeGroup,\n MemoryOptimizationStatus,\n StoredMessage,\n TokenUsage,\n TurnRequestContext,\n UsageSource,\n VoiceCut,\n} from \"@ykurilov/agent-chat-core\";\nimport { sql } from \"drizzle-orm\";\nimport { bigint, boolean, doublePrecision, index, integer, json, jsonb, pgSchema, text, timestamp, uniqueIndex } from \"drizzle-orm/pg-core\";\n\n/** Своя схема базы: у приложения могут быть свои `chats` и `messages`. */\nexport const agentChatSchema = pgSchema(\"agent_chat\");\n\nexport const chats = agentChatSchema.table(\n \"chats\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n /** Уровень рассуждений выбранной модели; пусто — у модели нет уровней. */\n reasoning: text(\"reasoning\"),\n /** Название для списка чатов; пусто — чат без названия. */\n title: text(\"title\"),\n /** Мессенджер, из которого создан чат; пусто — чат создан в вебе. */\n origin: text(\"origin\", { enum: [\"telegram\", \"vk\", \"max\"] }),\n /** Ключ объекта приложения; пусто — обычный чат. У владельца ключ не повторяется. */\n subjectKey: text(\"subject_key\"),\n /** Данные объекта (JSON-объект); пусто — данных нет. */\n subjectData: json(\"subject_data\").$type<Record<string, unknown>>(),\n /** Закрытие чата (`{ code, message }`); пусто — чат открыт. */\n closed: json(\"closed\").$type<ChatClosure>(),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n index(\"chats_owner_updated_idx\").on(table.ownerId, table.updatedAt),\n uniqueIndex(\"chats_owner_subject_idx\").on(table.ownerId, table.subjectKey),\n ],\n);\n\n// Части, использование и ошибка — `json`, а не `jsonb`: текст хранится как записан (порядок ключей, `\\u0000`).\nexport const messages = agentChatSchema.table(\n \"messages\",\n {\n /** Порядок записи: сообщения с одинаковым временем создания отдаются по нему. */\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n parentId: text(\"parent_id\"),\n role: text(\"role\", { enum: [\"user\", \"assistant\"] }).notNull(),\n parts: json(\"parts\").$type<StoredMessage[\"parts\"]>().notNull(),\n formatVersion: integer(\"format_version\").notNull(),\n status: text(\"status\").$type<AnswerStatus>().notNull(),\n modelId: text(\"model_id\"),\n providerId: text(\"provider_id\"),\n usage: json(\"usage\").$type<TokenUsage>(),\n reasoningDurationsMs: json(\"reasoning_durations_ms\").$type<Record<string, number>>().notNull(),\n error: json(\"error\").$type<{ kind: ChatErrorKind }>(),\n /** Отметка обрыва озвучки (голосовой режим); пусто — озвучку не обрывали. */\n voiceCut: json(\"voice_cut\").$type<VoiceCut>(),\n /** Состояние хука итога хода; пусто — хук не зовётся. */\n afterTurn: text(\"after_turn\", { enum: [\"pending\", \"done\", \"failed\"] }),\n createdAt: text(\"created_at\").notNull(),\n /** Последний знак жизни идущего ответа (ISO); пусто — время создания. Только для восстановления, при чтении не отдаётся. */\n aliveAt: text(\"alive_at\"),\n },\n (table) => [\n index(\"messages_chat_created_idx\").on(table.chatId, table.createdAt, table.seq),\n index(\"messages_streaming_idx\").on(table.status).where(sql`${table.status} = 'streaming'`),\n index(\"messages_after_turn_pending_idx\").on(table.afterTurn).where(sql`${table.afterTurn} = 'pending'`),\n ],\n);\n\n/** Записи сжатия: только добавляются. Порядок добавления — `seq`. */\nexport const compactions = agentChatSchema.table(\n \"compactions\",\n {\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n fromMessageId: text(\"from_message_id\").notNull(),\n throughMessageId: text(\"through_message_id\").notNull(),\n summary: text(\"summary\").notNull(),\n summaryTokens: integer(\"summary_tokens\").notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n usage: json(\"usage\").$type<TokenUsage>(),\n createdAt: text(\"created_at\").notNull(),\n },\n (table) => [index(\"compactions_chat_seq_idx\").on(table.chatId, table.seq)],\n);\n\n/** Отметки выбора ветки: только добавляются. Порядок добавления — `seq`. */\nexport const branchSelections = agentChatSchema.table(\n \"branch_selections\",\n {\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n messageId: text(\"message_id\").notNull(),\n selectedAt: text(\"selected_at\").notNull(),\n },\n (table) => [index(\"branch_selections_chat_seq_idx\").on(table.chatId, table.seq)],\n);\n\n/**\n * Журнал расхода токенов: только добавляется и не связан с чатами внешним ключом, чтобы переживать их удаление.\n * Месячный расход человека от удаления переписки не убывает.\n */\nexport const usageRecords = agentChatSchema.table(\n \"usage_records\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n chatId: text(\"chat_id\").notNull(),\n messageId: text(\"message_id\"),\n source: text(\"source\").$type<UsageSource>().notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n inputTokens: bigint(\"input_tokens\", { mode: \"number\" }).notNull(),\n cachedInputTokens: bigint(\"cached_input_tokens\", { mode: \"number\" }).notNull(),\n cacheWriteTokens: bigint(\"cache_write_tokens\", { mode: \"number\" }).notNull(),\n outputTokens: bigint(\"output_tokens\", { mode: \"number\" }).notNull(),\n reasoningTokens: bigint(\"reasoning_tokens\", { mode: \"number\" }).notNull(),\n costUsd: doublePrecision(\"cost_usd\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n /** Числа «примерно»: прикинуты по длине текста, а не сообщены провайдером. */\n estimated: boolean(\"estimated\").notNull().default(false),\n },\n (table) => [\n index(\"usage_records_owner_created_idx\").on(table.ownerId, table.createdAt),\n index(\"usage_records_chat_created_idx\").on(table.chatId, table.createdAt),\n ],\n);\n\n/** Последний выбор модели человека для новых чатов: одна строка на человека; с чатами не связан. */\nexport const userModelChoices = agentChatSchema.table(\"user_model_choices\", {\n ownerId: text(\"owner_id\").primaryKey(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n /** Пусто — у модели нет уровней рассуждений. */\n reasoning: text(\"reasoning\"),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** Выбранный человеком голос озвучки: одна строка на человека; с чатами и выбором модели не связан. */\nexport const voiceChoices = agentChatSchema.table(\"voice_choices\", {\n ownerId: text(\"owner_id\").primaryKey(),\n voiceId: text(\"voice_id\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** Состояние лимитов расходов по ключу: значение — строка (JSON решает ядро); `version` растёт на 1 при каждой записи и служит замком. */\nexport const spendingLimitStates = agentChatSchema.table(\"spending_limit_states\", {\n key: text(\"key\").primaryKey(),\n value: text(\"value\").notNull(),\n version: integer(\"version\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/**\n * Аренда хода чата между копиями сервера: кто держит (`holder`) и до какого времени (`until`, по часам базы). Внешним\n * ключом с чатом не связана: удаление чата снимает её само.\n */\nexport const chatTurnLeases = agentChatSchema.table(\"chat_turn_leases\", {\n chatId: text(\"chat_id\").primaryKey(),\n holder: text(\"holder\").notNull(),\n until: timestamp(\"until\", { withTimezone: true, mode: \"string\" }).notNull(),\n});\n\n/**\n * Ждущие пачки сообщений человека: одна запись на чат. Сроки — по часам службы. Внешним ключом с чатом не связана:\n * удаление чата снимает её само.\n */\nexport const pendingBursts = agentChatSchema.table(\"pending_bursts\", {\n chatId: text(\"chat_id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n messageId: text(\"message_id\").notNull(),\n dueAt: timestamp(\"due_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n holder: text(\"holder\").notNull(),\n heldUntil: timestamp(\"held_until\", { withTimezone: true, mode: \"date\" }).notNull(),\n page: jsonb(\"page\").$type<TurnRequestContext>(),\n});\n\n/**\n * Долгая память: записи принадлежат человеку и с чатами не связаны внешним ключом, чтобы переживать их удаление.\n * `version` — замок правки и удаления: растёт на 1 при каждой правке.\n */\nexport const memoryNotes = agentChatSchema.table(\n \"memory_notes\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n categories: jsonb(\"categories\").$type<string[]>().notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n createdAt: timestamp(\"created_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n /** Оптимизация дублей: id записи-результата у скрытого оригинала слияния; у обычных записей пусто. */\n mergedInto: text(\"merged_into\"),\n },\n (table) => [\n index(\"memory_notes_owner_updated_idx\").on(table.ownerId, table.updatedAt),\n index(\"memory_notes_merged_into_idx\").on(table.mergedInto),\n ],\n);\n\n/**\n * Оптимизация дублей: запуски человека. `groups` — список склеек (результат, оригиналы, версия результата на\n * момент слияния). Запуск `running` у человека не больше одного: за этим следит частичный уникальный индекс.\n */\nexport const memoryOptimizationRuns = agentChatSchema.table(\n \"memory_optimization_runs\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n startedAt: timestamp(\"started_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n finishedAt: timestamp(\"finished_at\", { withTimezone: true, mode: \"date\" }),\n status: text(\"status\").$type<MemoryOptimizationStatus>().notNull(),\n groups: jsonb(\"groups\").$type<MemoryMergeGroup[]>().notNull().default(sql`'[]'::jsonb`),\n error: text(\"error\"),\n usageRecordId: text(\"usage_record_id\"),\n },\n (table) => [\n index(\"memory_optimization_runs_owner_started_idx\").on(table.ownerId, table.startedAt),\n uniqueIndex(\"memory_optimization_runs_one_running_idx\").on(table.ownerId).where(sql`${table.status} = 'running'`),\n ],\n);\n","import { fileURLToPath } from \"node:url\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport { migrate } from \"drizzle-orm/node-postgres/migrator\";\nimport { migratePostgresSchema } from \"@ykurilov/agent-chat-core\";\nimport type { Pool } from \"pg\";\n\nconst migrationsFolder = fileURLToPath(new URL(\"../drizzle\", import.meta.url));\n\n/** Постоянное число для блокировки базы: одинаково у всех серверов и всех версий SDK. */\nconst MIGRATION_LOCK_KEY = 7_311_900_442;\n\n/**\n * Приводит схему `agent_chat` к последней миграции. Схема `agent_chat` создаётся под общей блокировкой всех пакетов, миграции — под своей:\n * копии пакета ждут друг друга, а разные пакеты стартуют разом на пустой базе без гонки за схему.\n */\nexport async function migrateToLatest(pool: Pool): Promise<void> {\n await migratePostgresSchema({\n connect: () => pool.connect(),\n lockKey: MIGRATION_LOCK_KEY,\n migrate: (client) => migrate(drizzle(client), { migrationsFolder, migrationsSchema: \"agent_chat\" }),\n });\n}\n"],"mappings":"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","names":["drizzle","sql","sql","index","drizzle"]}
|
|
1
|
+
{"version":3,"sources":["../src/postgres-storage.ts","../src/drizzle-chat-storage.ts","../src/schema.ts","../src/migrate.ts"],"sourcesContent":["import type { ChatStorage } from \"@ykurilov/agent-chat-core\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport pg from \"pg\";\nimport { createDrizzleChatStorage, storageSchema } from \"./drizzle-chat-storage\";\nimport { migrateToLatest } from \"./migrate\";\n\nexport interface PostgresChatStorage extends ChatStorage {\n /** Закрывает соединения с базой. */\n close(): Promise<void>;\n}\n\nexport interface PostgresChatStorageOptions {\n /** Например `postgres://user:password@host:5432/database`. */\n connectionString: string;\n /** Сколько соединений держать открытыми. По умолчанию 10. */\n poolSize?: number;\n /** Журнал сервера: обрывы соединения. По умолчанию `console.error`. */\n logError?: (message: string) => void;\n}\n\nconst DEFAULT_POOL_SIZE = 10;\n\n/**\n * Хранилище в PostgreSQL. Таблицы лежат в схеме `agent_chat`; схема приводится к последней\n * миграции при создании, под блокировкой базы.\n */\nexport async function createPostgresChatStorage(options: PostgresChatStorageOptions): Promise<PostgresChatStorage> {\n const logError = options.logError ?? ((message: string) => console.error(message));\n const pool = new pg.Pool({ connectionString: options.connectionString, max: options.poolSize ?? DEFAULT_POOL_SIZE });\n // Без обработчика оборвавшееся соединение простаивающего пула роняет процесс.\n pool.on(\"error\", (error) => logError(`PostgreSQL: соединение оборвалось: ${error.message}`));\n try {\n await pool.query(\"select 1\");\n } catch (error) {\n await pool.end().catch(() => {});\n throw failure(\"Не удалось подключиться к PostgreSQL\", options.connectionString, error);\n }\n try {\n await migrateToLatest(pool);\n } catch (error) {\n await pool.end().catch(() => {});\n throw failure(\"Не удалось применить миграции PostgreSQL\", options.connectionString, error);\n }\n return {\n ...createDrizzleChatStorage(drizzle(pool, { schema: storageSchema })),\n async close() {\n await pool.end();\n },\n };\n}\n\n/** Ошибка без строки подключения: хост, порт и база берутся из разобранного адреса, пароль в текст не попадает. */\nfunction failure(summary: string, connectionString: string, cause: unknown): Error {\n const reason = cause instanceof Error ? cause.message : String(cause);\n let place = \"адрес не разобран\";\n try {\n const address = new URL(connectionString);\n place = `${address.hostname}:${address.port || \"5432\"}${address.pathname}`;\n } catch {\n // Адрес не разобрать — в текст ошибки он не попадает.\n }\n const safeReason = reason.split(connectionString).join(\"<строка подключения>\");\n return new Error(`${summary} (${place}): ${safeReason}`);\n}\n","import {\n assertChatDataFilter,\n assertKnownFormatVersion,\n ChatAlreadyExistsError,\n chatDataFields,\n chatDataOfInput,\n DuplicateChatSubjectError,\n DuplicateMessageError,\n isOptimizationBlocked,\n mergeChatData,\n MessageAlreadyFinishedError,\n MessageNotAwaitingError,\n RELEASED_ANSWER_ALIVE_AT,\n revertRefusal,\n sameMessageParts,\n} from \"@ykurilov/agent-chat-core\";\nimport type {\n AnswerAliveMark,\n Chat,\n ChatDataFilter,\n ChatListOptions,\n ChatStorage,\n ChatSubjectFilter,\n MemoryMergeGroup,\n MemoryNote,\n MemoryNoteInput,\n MemoryOptimizationRun,\n MergedMemoryNote,\n StoredMessage,\n} from \"@ykurilov/agent-chat-core\";\nimport { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, ne, sql } from \"drizzle-orm\";\nimport type { SQL } from \"drizzle-orm\";\nimport type { PgDatabase, PgQueryResultHKT } from \"drizzle-orm/pg-core\";\nimport { branchSelections, chats, chatTurnLeases, compactions, memoryNotes, memoryOptimizationRuns, messages, pendingBursts, spendingLimitStates, usageRecords, userModelChoices, voiceChoices } from \"./schema\";\n\nexport const storageSchema = { chats, messages, compactions, branchSelections, usageRecords, userModelChoices, voiceChoices, spendingLimitStates, memoryNotes, memoryOptimizationRuns };\n\n/** Слияние не сошлось со снимком: бросается внутри транзакции, чтобы откатить её, и не выходит наружу. */\nclass StaleMerge extends Error {}\n\n/** Любая база Drizzle для PostgreSQL: `pg` в проде, pglite в тестах. Схема должна быть уже создана. */\nexport type ChatDatabase = PgDatabase<PgQueryResultHKT, typeof storageSchema>;\n\n/** Время базы `moment` (timestamptz) строкой ISO в UTC, как `Date.toISOString()`: так оно сравнимо с `created_at`. */\nfunction isoAtDatabase(moment: SQL): SQL<string> {\n return sql<string>`to_char((${moment}) at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`;\n}\n\n/**\n * Знак жизни в колонку `alive_at`. «Сейчас» — по часам базы: копии сервера на разных машинах пишут и сравнивают знак\n * по одним часам, и расхождение часов машин не делает живой ответ брошенным.\n */\nfunction aliveAtColumn(alive: AnswerAliveMark | undefined): { aliveAt?: SQL<string> | string } {\n if (!alive) return {};\n return { aliveAt: alive === \"released\" ? RELEASED_ANSWER_ALIVE_AT : isoAtDatabase(sql`now()`) };\n}\n\n/** Запросы хранилища; соединением и миграциями занимается вызывающий. */\nexport function createDrizzleChatStorage(db: ChatDatabase): ChatStorage {\n /** Пишет в идущий ответ; отличает «нет такого» от «уже в конечном состоянии». */\n async function updateStreaming(\n messageId: string,\n { alive, ...values }: Partial<typeof messages.$inferInsert> & { alive?: AnswerAliveMark },\n ): Promise<void> {\n const updated = await db\n .update(messages)\n .set({ ...values, ...aliveAtColumn(alive) })\n .where(and(eq(messages.id, messageId), eq(messages.status, \"streaming\")))\n .returning({ id: messages.id });\n if (updated.length > 0) return;\n const [existing] = await db.select({ id: messages.id }).from(messages).where(eq(messages.id, messageId));\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n throw new MessageAlreadyFinishedError(messageId);\n }\n\n /** Запросы в транзакции или без неё: транзакция Drizzle умеет то же, что и база. */\n type Executor = ChatDatabase;\n\n /** Записи человека пишутся по одному: замок держится до конца транзакции. Без него две вставки видят одинаковый список и обе проходят проверку. */\n async function lockMemoryNotes(tx: Executor, ownerId: string): Promise<void> {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtextextended(${`agent_chat.memory_notes:${ownerId}`}, 0))`);\n }\n\n async function visibleNotes(exec: Executor, ownerId: string): Promise<MemoryNote[]> {\n const rows = await exec\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNull(memoryNotes.mergedInto)))\n // Идентификаторы сравниваются по кодам знаков, как в договоре, а не по правилам языка базы.\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n return rows.map(toMemoryNote);\n }\n\n async function insertNotes(exec: Executor, ownerId: string, inputs: MemoryNoteInput[]): Promise<MemoryNote[]> {\n inputs.forEach(assertWellFormedNote);\n if (inputs.length === 0) return [];\n const now = new Date();\n // Одна вставка: пакет ложится целиком или не ложится вовсе.\n const rows = await exec\n .insert(memoryNotes)\n .values(\n inputs.map(({ categories, content }) => ({\n id: crypto.randomUUID(),\n ownerId,\n categories: [...categories],\n content,\n version: 1,\n createdAt: now,\n updatedAt: now,\n })),\n )\n .returning();\n return rows.map(toMemoryNote);\n }\n\n async function updateNote(exec: Executor, ownerId: string, id: string, expectedVersion: number, input: MemoryNoteInput): Promise<MemoryNote | \"not_found\" | \"stale_version\"> {\n assertWellFormedNote(input);\n const updated = await exec\n .update(memoryNotes)\n .set({ categories: [...input.categories], content: input.content, version: sql`${memoryNotes.version} + 1`, updatedAt: new Date() })\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, expectedVersion), isNull(memoryNotes.mergedInto)))\n .returning();\n if (updated[0]) return toMemoryNote(updated[0]);\n return (await memoryNoteExists(exec, ownerId, id)) ? \"stale_version\" : \"not_found\";\n }\n\n async function memoryNoteExists(exec: Executor, ownerId: string, id: string): Promise<boolean> {\n const [existing] = await exec\n .select({ id: memoryNotes.id })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), isNull(memoryNotes.mergedInto)));\n return existing !== undefined;\n }\n\n return {\n async createChat({ createdAt, ...input }) {\n const at = createdAt ?? new Date().toISOString();\n const row = chatRow({ ...input, createdAt: at, updatedAt: at });\n try {\n await db.insert(chats).values(row);\n } catch (error) {\n if (isConflictOn(error, \"chats_owner_subject_idx\")) throw new DuplicateChatSubjectError(input.ownerId, input.subjectKey!);\n throw error;\n }\n return toChat(row);\n },\n\n async findChatBySubject(ownerId, subjectKey) {\n const [row] = await db.select().from(chats).where(and(eq(chats.ownerId, ownerId), eq(chats.subjectKey, subjectKey)));\n return row ? toChat(row) : null;\n },\n\n async importChat(chat, imported) {\n // Ошибка внутри транзакции откатывает её целиком: ни чата, ни сообщений.\n await db.transaction(async (tx) => {\n try {\n await tx.insert(chats).values(chatRow(chat));\n } catch (error) {\n if (isConflictOn(error, \"chats_owner_subject_idx\")) throw new DuplicateChatSubjectError(chat.ownerId, chat.subjectKey!);\n if (isConflictOn(error, \"chats_pkey\")) throw new ChatAlreadyExistsError(chat.id);\n throw error;\n }\n // По одному: порядок записи (`seq`) — порядок сообщений при равном времени создания.\n for (const message of imported) {\n const { alive: _alive, ...stored } = message;\n try {\n await tx.insert(messages).values(stored);\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n }\n });\n },\n\n async setAfterTurnState(messageId, state, options) {\n // Строка заперта до конца транзакции: другая копия сервера не закроет хук между проверкой и записью.\n return db.transaction(async (tx) => {\n const [existing] = await tx\n .select({ parts: messages.parts, afterTurn: messages.afterTurn })\n .from(messages)\n .where(eq(messages.id, messageId))\n .for(\"update\");\n if (!existing || (state !== \"pending\" && existing.afterTurn !== \"pending\")) return false;\n await tx\n .update(messages)\n .set({\n afterTurn: state,\n ...(options?.appendParts && { parts: [...existing.parts, ...options.appendParts] }),\n // Отметка ожидания хука — в колонке знака жизни, по часам базы: у законченного ответа она больше ни для чего.\n ...(state === \"pending\" && aliveAtColumn(\"now\")),\n })\n .where(eq(messages.id, messageId));\n return true;\n });\n },\n\n async listPendingAfterTurn(filter) {\n const pending = eq(messages.afterTurn, \"pending\");\n const rows = await db\n .select({ id: messages.id })\n .from(messages)\n .where(\n filter?.pendingForMs === undefined\n ? pending\n : and(\n pending,\n sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${isoAtDatabase(sql`now() - ${filter.pendingForMs} * interval '1 millisecond'`)}`,\n ),\n );\n return rows.map((row) => row.id);\n },\n\n async getChat(chatId) {\n const [chat] = await db.select().from(chats).where(eq(chats.id, chatId));\n return chat ? toChat(chat) : null;\n },\n\n async updateChatModel(chatId, model) {\n await db\n .update(chats)\n .set({ modelId: model.modelId, providerId: model.providerId, reasoning: model.reasoning ?? null })\n .where(eq(chats.id, chatId));\n },\n\n async updateChatData(chatId, patch, { maxBytes }) {\n // Строка чата блокируется на время слияния: параллельные правки идут по очереди и не затирают друг друга.\n return db.transaction(async (tx) => {\n const [row] = await tx.select().from(chats).where(eq(chats.id, chatId)).for(\"update\");\n if (!row) return null;\n const merged = mergeChatData(row.subjectData ?? undefined, patch, maxBytes);\n await tx.update(chats).set({ subjectData: merged ?? null }).where(eq(chats.id, chatId));\n return toChat({ ...row, subjectData: merged ?? null });\n });\n },\n\n async listChats(ownerId, options?: ChatListOptions) {\n if (options?.data) assertChatDataFilter(options.data);\n const rows = await db\n .select()\n .from(chats)\n .where(and(eq(chats.ownerId, ownerId), subjectCondition(options?.subjects), dataCondition(options?.data)))\n .orderBy(desc(chats.updatedAt), desc(chats.createdAt), desc(chats.id));\n return rows.map(toChat);\n },\n\n async renameChat(chatId, title) {\n await db.update(chats).set({ title }).where(eq(chats.id, chatId));\n },\n\n async setChatClosed(chatId, closed) {\n await db.update(chats).set({ closed: closed && { code: closed.code, message: closed.message } }).where(eq(chats.id, chatId));\n },\n\n async deleteChat(chatId) {\n await db.transaction(async (tx) => {\n await tx.delete(compactions).where(eq(compactions.chatId, chatId));\n await tx.delete(branchSelections).where(eq(branchSelections.chatId, chatId));\n await tx.delete(messages).where(eq(messages.chatId, chatId));\n await tx.delete(chats).where(eq(chats.id, chatId));\n await tx.delete(chatTurnLeases).where(eq(chatTurnLeases.chatId, chatId));\n await tx.delete(pendingBursts).where(eq(pendingBursts.chatId, chatId));\n });\n },\n\n async claimChatTurn(chatId, holder, leaseMs) {\n // Одной записью по часам базы: свободный чат — вставка; своя или просроченная чужая — замена; живая чужая — ничего.\n // Две копии разом: вторая ждёт строку первой и видит её живой.\n const until = sql`now() + ${leaseMs} * interval '1 millisecond'`;\n const claimed = await db\n .insert(chatTurnLeases)\n .values({ chatId, holder, until })\n .onConflictDoUpdate({\n target: chatTurnLeases.chatId,\n set: { holder, until },\n setWhere: sql`${chatTurnLeases.holder} = ${holder} or ${chatTurnLeases.until} <= now()`,\n })\n .returning({ chatId: chatTurnLeases.chatId });\n return claimed.length > 0;\n },\n\n async releaseChatTurn(chatId, holder) {\n await db.delete(chatTurnLeases).where(and(eq(chatTurnLeases.chatId, chatId), eq(chatTurnLeases.holder, holder)));\n },\n\n async clearChatTurnLeases() {\n await db.delete(chatTurnLeases);\n },\n\n async savePendingBurst(burst) {\n const row = {\n chatId: burst.chatId,\n ownerId: burst.ownerId,\n messageId: burst.messageId,\n dueAt: new Date(burst.dueAt),\n holder: burst.holder,\n heldUntil: new Date(burst.heldUntil),\n page: burst.page ?? null,\n };\n await db.insert(pendingBursts).values(row).onConflictDoUpdate({ target: pendingBursts.chatId, set: row });\n },\n\n async takeAbandonedBursts({ abandonedBefore, holder, heldUntil, limit, exceptHolder }) {\n const notOwn = exceptHolder === undefined ? undefined : ne(pendingBursts.holder, exceptHolder);\n // Выбор и захват — одной записью; строки, которые прямо сейчас берёт другая копия, пропускаются.\n const abandoned = db\n .select({ chatId: pendingBursts.chatId })\n .from(pendingBursts)\n .where(and(lte(pendingBursts.heldUntil, new Date(abandonedBefore)), notOwn))\n .orderBy(asc(pendingBursts.dueAt))\n .limit(limit)\n .for(\"update\", { skipLocked: true });\n const taken = await db\n .update(pendingBursts)\n .set({ holder, heldUntil: new Date(heldUntil) })\n .where(and(inArray(pendingBursts.chatId, abandoned), lte(pendingBursts.heldUntil, new Date(abandonedBefore)), notOwn))\n .returning();\n return taken\n .sort((first, second) => first.dueAt.getTime() - second.dueAt.getTime())\n .map((row) => ({\n chatId: row.chatId,\n ownerId: row.ownerId,\n messageId: row.messageId,\n dueAt: row.dueAt.toISOString(),\n holder,\n heldUntil,\n ...(row.page && { page: row.page }),\n }));\n },\n\n async renewPendingBurst({ chatId, messageId, holder, heldUntil }) {\n const renewed = await db\n .update(pendingBursts)\n .set({ heldUntil: new Date(heldUntil) })\n .where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId), eq(pendingBursts.holder, holder)))\n .returning({ chatId: pendingBursts.chatId });\n return renewed.length > 0;\n },\n\n async removePendingBurst(chatId, messageId) {\n await db.delete(pendingBursts).where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId)));\n },\n\n async getMessage(messageId) {\n const [row] = await db.select().from(messages).where(eq(messages.id, messageId));\n if (!row) return null;\n const message = toMessage(row);\n assertKnownFormatVersion(message);\n return message;\n },\n\n async listMessages(chatId) {\n const rows = await db\n .select()\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n const found: StoredMessage[] = rows.map(toMessage);\n found.forEach(assertKnownFormatVersion);\n return found;\n },\n\n async listMessageLinks(chatId) {\n return db\n .select({ id: messages.id, parentId: messages.parentId, createdAt: messages.createdAt })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n },\n\n // Части нужных типов выбираются внутри базы: тексты и выводы инструментов в процесс не идут.\n async listMessagePartsOfTypes(chatId, types) {\n const wanted = JSON.stringify([...types]);\n const rows = await db\n .select({\n id: messages.id,\n parentId: messages.parentId,\n createdAt: messages.createdAt,\n parts: sql<unknown>`(select coalesce(json_agg(part.value order by part.position), '[]'::json) from json_array_elements(${messages.parts}) with ordinality as part(value, position) where part.value->>'type' in (select json_array_elements_text(${wanted}::json)))`,\n })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), asc(messages.seq));\n return rows.map((row) => ({ ...row, parts: (typeof row.parts === \"string\" ? JSON.parse(row.parts) : row.parts) as StoredMessage[\"parts\"] }));\n },\n\n async insertMessage(message) {\n try {\n await db.transaction(async (tx) => {\n const { alive, ...stored } = message;\n await tx.insert(messages).values({ ...stored, ...aliveAtColumn(alive) });\n await tx.update(chats).set({ updatedAt: message.createdAt }).where(eq(chats.id, message.chatId));\n });\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n },\n\n updateStreamingMessage: (messageId, patch) => updateStreaming(messageId, patch),\n\n markAnswerAlive: (messageId) => updateStreaming(messageId, { alive: \"now\" }),\n\n finishMessage: (messageId, final) => updateStreaming(messageId, { ...final, ...(final.afterTurn === \"pending\" && { alive: \"now\" as const }) }),\n\n async updateAwaitingMessage(messageId, patch) {\n // Строка заперта до конца транзакции: другая копия сервера не запишет между сравнением частей и записью.\n await db.transaction(async (tx) => {\n const [existing] = await tx\n .select({ status: messages.status, parts: messages.parts })\n .from(messages)\n .where(eq(messages.id, messageId))\n .for(\"update\");\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n if (existing.status !== \"awaiting_approval\") throw new MessageNotAwaitingError(messageId);\n if (patch.expectedParts && !sameMessageParts(existing.parts, patch.expectedParts)) throw new MessageNotAwaitingError(messageId);\n await tx\n .update(messages)\n .set({ parts: patch.parts, ...(patch.status && { status: patch.status }), ...aliveAtColumn(patch.alive) })\n .where(eq(messages.id, messageId));\n });\n },\n\n async listStreamingMessageIds() {\n const rows = await db.select({ id: messages.id }).from(messages).where(eq(messages.status, \"streaming\")).orderBy(asc(messages.seq));\n return rows.map((row) => row.id);\n },\n\n async listSilentAnswerIds({ silentForMs, chatId }) {\n const silent = sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${isoAtDatabase(sql`now() - ${silentForMs} * interval '1 millisecond'`)}`;\n const rows = await db\n .select({ id: messages.id })\n .from(messages)\n .where(and(eq(messages.status, \"streaming\"), silent, chatId === undefined ? undefined : eq(messages.chatId, chatId)))\n .orderBy(asc(messages.seq));\n return rows.map((row) => row.id);\n },\n\n async insertCompaction(record) {\n await db.insert(compactions).values(record);\n },\n\n async listCompactions(chatId) {\n const rows = await db.select().from(compactions).where(eq(compactions.chatId, chatId)).orderBy(asc(compactions.seq));\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertBranchSelection(record) {\n await db.insert(branchSelections).values(record);\n },\n\n async listBranchSelections(chatId) {\n const rows = await db.select().from(branchSelections).where(eq(branchSelections.chatId, chatId)).orderBy(asc(branchSelections.seq));\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertUsageRecord(record) {\n await db.insert(usageRecords).values(record);\n },\n\n async hasUsageRecord(id) {\n const rows = await db.select({ id: usageRecords.id }).from(usageRecords).where(eq(usageRecords.id, id)).limit(1);\n return rows.length > 0;\n },\n\n async sumUsage({ ownerId, chatId, messageId, source, since }) {\n const filters = [\n ...(ownerId !== undefined ? [eq(usageRecords.ownerId, ownerId)] : []),\n ...(chatId !== undefined ? [eq(usageRecords.chatId, chatId)] : []),\n ...(messageId !== undefined ? [eq(usageRecords.messageId, messageId)] : []),\n ...(source !== undefined ? [eq(usageRecords.source, source)] : []),\n ...(since !== undefined ? [gte(usageRecords.createdAt, since)] : []),\n ];\n // sum() по bigint приходит строкой: суммы токенов помещаются в число.\n return db\n .select({\n modelId: usageRecords.modelId,\n providerId: usageRecords.providerId,\n inputTokens: sql<number>`sum(${usageRecords.inputTokens})`.mapWith(Number),\n cachedInputTokens: sql<number>`sum(${usageRecords.cachedInputTokens})`.mapWith(Number),\n cacheWriteTokens: sql<number>`sum(${usageRecords.cacheWriteTokens})`.mapWith(Number),\n outputTokens: sql<number>`sum(${usageRecords.outputTokens})`.mapWith(Number),\n reasoningTokens: sql<number>`sum(${usageRecords.reasoningTokens})`.mapWith(Number),\n costUsd: sql<number>`sum(${usageRecords.costUsd})`.mapWith(Number),\n })\n .from(usageRecords)\n .where(and(...filters))\n .groupBy(usageRecords.modelId, usageRecords.providerId);\n },\n\n async sumUsageByChat({ chatIds, ownerId, source, since }) {\n if (chatIds.length === 0) return [];\n const filters = [\n inArray(usageRecords.chatId, [...chatIds]),\n ...(ownerId !== undefined ? [eq(usageRecords.ownerId, ownerId)] : []),\n ...(source !== undefined ? [eq(usageRecords.source, source)] : []),\n ...(since !== undefined ? [gte(usageRecords.createdAt, since)] : []),\n ];\n return db\n .select({\n chatId: usageRecords.chatId,\n modelId: usageRecords.modelId,\n providerId: usageRecords.providerId,\n inputTokens: sql<number>`sum(${usageRecords.inputTokens})`.mapWith(Number),\n cachedInputTokens: sql<number>`sum(${usageRecords.cachedInputTokens})`.mapWith(Number),\n cacheWriteTokens: sql<number>`sum(${usageRecords.cacheWriteTokens})`.mapWith(Number),\n outputTokens: sql<number>`sum(${usageRecords.outputTokens})`.mapWith(Number),\n reasoningTokens: sql<number>`sum(${usageRecords.reasoningTokens})`.mapWith(Number),\n costUsd: sql<number>`sum(${usageRecords.costUsd})`.mapWith(Number),\n })\n .from(usageRecords)\n .where(and(...filters))\n .groupBy(usageRecords.chatId, usageRecords.modelId, usageRecords.providerId);\n },\n\n async getUserModelChoice(ownerId) {\n const [row] = await db.select().from(userModelChoices).where(eq(userModelChoices.ownerId, ownerId));\n if (!row) return null;\n return { modelId: row.modelId, providerId: row.providerId, ...(row.reasoning !== null && { reasoning: row.reasoning }) };\n },\n\n async saveUserModelChoice(ownerId, choice) {\n const values = { modelId: choice.modelId, providerId: choice.providerId, reasoning: choice.reasoning ?? null, updatedAt: new Date().toISOString() };\n await db.insert(userModelChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: userModelChoices.ownerId, set: values });\n },\n\n async setVoiceCut({ ownerId, chatId, messageId, voiceCut }) {\n await db\n .update(messages)\n .set({ voiceCut })\n .where(\n and(\n eq(messages.id, messageId),\n eq(messages.chatId, chatId),\n sql`exists (select 1 from ${chats} where ${chats.id} = ${chatId} and ${chats.ownerId} = ${ownerId})`,\n ),\n );\n },\n\n async getSpendingLimitState(key) {\n const [row] = await db.select().from(spendingLimitStates).where(eq(spendingLimitStates.key, key));\n return row ? { value: row.value, version: row.version } : null;\n },\n\n // Одна команда без чтения: вставка или правка срабатывает только при совпавшей версии, из двух одновременных проходит одна.\n async saveSpendingLimitState(key, value, expectedVersion) {\n const updatedAt = new Date().toISOString();\n if (expectedVersion === null) {\n const inserted = await db\n .insert(spendingLimitStates)\n .values({ key, value, version: 1, updatedAt })\n .onConflictDoNothing()\n .returning({ key: spendingLimitStates.key });\n return inserted.length === 1;\n }\n const updated = await db\n .update(spendingLimitStates)\n .set({ value, version: expectedVersion + 1, updatedAt })\n .where(and(eq(spendingLimitStates.key, key), eq(spendingLimitStates.version, expectedVersion)))\n .returning({ key: spendingLimitStates.key });\n return updated.length === 1;\n },\n\n async deleteSpendingLimitStates(keys) {\n if (keys.length > 0) await db.delete(spendingLimitStates).where(inArray(spendingLimitStates.key, keys));\n },\n\n async getVoiceChoice(ownerId) {\n const [row] = await db.select().from(voiceChoices).where(eq(voiceChoices.ownerId, ownerId));\n return row?.voiceId ?? null;\n },\n\n async setVoiceChoice(ownerId, voiceId) {\n const values = { voiceId, updatedAt: new Date().toISOString() };\n await db.insert(voiceChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: voiceChoices.ownerId, set: values });\n },\n\n async listMemoryNotes(ownerId) {\n return visibleNotes(db, ownerId);\n },\n\n async insertMemoryNotes(ownerId, inputs) {\n return insertNotes(db, ownerId, inputs);\n },\n\n async insertMemoryNotesChecked(ownerId, inputs, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const error = guard(await visibleNotes(tx, ownerId));\n return error ?? (await insertNotes(tx, ownerId, inputs));\n });\n },\n\n async updateMemoryNote(ownerId, id, expectedVersion, input) {\n return updateNote(db, ownerId, id, expectedVersion, input);\n },\n\n async updateMemoryNoteChecked(ownerId, id, expectedVersion, input, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const error = guard(await visibleNotes(tx, ownerId));\n return error ?? (await updateNote(tx, ownerId, id, expectedVersion, input));\n });\n },\n\n async deleteMemoryNote(ownerId, id, expectedVersion) {\n const deleted = await db.transaction(async (tx) => {\n const rows = await tx\n .delete(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, expectedVersion), isNull(memoryNotes.mergedInto)))\n .returning({ id: memoryNotes.id });\n // Скрытые оригиналы слияния уходят вместе с результатом.\n if (rows.length > 0) await tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, id)));\n return rows.length > 0;\n });\n if (deleted) return \"ok\";\n return (await memoryNoteExists(db, ownerId, id)) ? \"stale_version\" : \"not_found\";\n },\n\n async clearMemoryNotes(ownerId) {\n return db.transaction(async (tx) => {\n const deleted = await tx.delete(memoryNotes).where(eq(memoryNotes.ownerId, ownerId)).returning({ mergedInto: memoryNotes.mergedInto });\n await tx.delete(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId));\n // Считаются записи, которые человек видел; скрытые оригиналы — служебные.\n return deleted.filter((row) => row.mergedInto === null).length;\n });\n },\n\n // Взятие запуска — одна транзакция под замком человека: проверка правил и вставка не разрываются между процессами.\n async claimMemoryOptimizationRun(ownerId, rules, now) {\n const nowMs = Date.parse(now);\n return db.transaction(async (tx) => {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtextextended(${`agent_chat.memory_optimization:${ownerId}`}, 0))`);\n const runs = await tx.select().from(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId));\n const state = runs.map((run) => {\n const leaseEnd = run.startedAt.getTime() + rules.leaseMs;\n const expired = run.status === \"running\" && nowMs >= leaseEnd;\n return { status: expired ? \"failed\" : run.status, endedAt: expired ? leaseEnd : (run.finishedAt ?? run.startedAt).getTime(), expired, id: run.id };\n });\n for (const run of state.filter((item) => item.expired)) {\n await tx\n .update(memoryOptimizationRuns)\n .set({ status: \"failed\", error: \"lease_expired\", finishedAt: new Date(run.endedAt) })\n .where(eq(memoryOptimizationRuns.id, run.id));\n }\n const blocked = isOptimizationBlocked(\n runs.map((run, index) => ({ status: state[index]!.status, startedAtMs: run.startedAt.getTime(), endedAtMs: state[index]!.endedAt })),\n rules,\n nowMs,\n );\n if (blocked) return null;\n const [created] = await tx\n .insert(memoryOptimizationRuns)\n .values({ id: crypto.randomUUID(), ownerId, startedAt: new Date(nowMs), status: \"running\" })\n .returning();\n return toOptimizationRun(created!);\n });\n },\n\n async finishMemoryOptimizationRun(ownerId, runId, outcome) {\n const finished = await db\n .update(memoryOptimizationRuns)\n .set({ status: outcome.status, finishedAt: new Date(outcome.finishedAt), error: outcome.error ?? null, usageRecordId: outcome.usageRecordId ?? null })\n .where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId), eq(memoryOptimizationRuns.status, \"running\")))\n .returning({ id: memoryOptimizationRuns.id });\n return finished.length > 0 ? \"ok\" : \"not_found\";\n },\n\n // Слияние — одна транзакция: несошедшийся оригинал бросает StaleMerge, и откатывается всё, включая запуск.\n async applyMemoryMerge(ownerId, merge) {\n const { merges } = merge;\n if (merges.length === 0) throw new TypeError(\"Слияние без склеек\");\n const seen = new Set<string>();\n for (const { result, originals } of merges) {\n assertWellFormedNote(result);\n if (originals.length === 0) throw new TypeError(\"Склейка без оригиналов\");\n for (const { id } of originals) {\n if (seen.has(id)) throw new TypeError(`Запись ${id} названа в двух склейках`);\n seen.add(id);\n }\n }\n try {\n return await db.transaction(async (tx) => {\n const [run] = await tx\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.id, merge.runId), eq(memoryOptimizationRuns.ownerId, ownerId)))\n .for(\"update\");\n if (run?.status !== \"running\") return \"run_not_active\" as const;\n const now = new Date();\n const groups: MemoryMergeGroup[] = [];\n for (const { result, originals } of merges) {\n const created = { id: crypto.randomUUID(), ownerId, categories: [...result.categories], content: result.content, version: 1, createdAt: now, updatedAt: now };\n await tx.insert(memoryNotes).values(created);\n // Оригинал прячется, только если он ещё обычный и той же версии; условие проверяет сама база.\n for (const { id, version } of originals) {\n const hidden = await tx\n .update(memoryNotes)\n .set({ mergedInto: created.id })\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), eq(memoryNotes.version, version), isNull(memoryNotes.mergedInto)))\n .returning({ id: memoryNotes.id });\n if (hidden.length === 0) throw new StaleMerge();\n }\n groups.push({ resultId: created.id, originalIds: originals.map(({ id }) => id), resultVersion: 1 });\n }\n const [finished] = await tx\n .update(memoryOptimizationRuns)\n .set({ status: \"applied\", finishedAt: new Date(merge.finishedAt), groups, usageRecordId: merge.usageRecordId ?? null })\n .where(eq(memoryOptimizationRuns.id, run.id))\n .returning();\n return toOptimizationRun(finished!);\n });\n } catch (error) {\n if (error instanceof StaleMerge) return \"stale_version\";\n throw error;\n }\n },\n\n async revertMemoryMerge(ownerId, runId, guard) {\n return db.transaction(async (tx) => {\n await lockMemoryNotes(tx, ownerId);\n const [run] = await tx\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId)))\n .for(\"update\");\n if (run?.status !== \"applied\") return \"not_found\" as const;\n for (const { resultId, originalIds, resultVersion } of run.groups) {\n const [result] = await tx\n .select({ version: memoryNotes.version })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, resultId), isNull(memoryNotes.mergedInto)))\n .for(\"update\");\n if (result?.version !== resultVersion) return \"conflict\" as const;\n const hidden = await tx\n .select({ id: memoryNotes.id })\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId), inArray(memoryNotes.id, originalIds)))\n .for(\"update\");\n if (hidden.length !== originalIds.length) return \"conflict\" as const;\n }\n if (guard) {\n const resultIds = run.groups.map(({ resultId }) => resultId);\n const remaining = (await visibleNotes(tx, ownerId)).filter((note) => !resultIds.includes(note.id));\n const restoredRows = await tx\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), inArray(memoryNotes.mergedInto, resultIds)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n const error = guard(remaining, restoredRows.map(toMemoryNote));\n if (error) return revertRefusal(error);\n }\n for (const { resultId } of run.groups) {\n await tx.update(memoryNotes).set({ mergedInto: null }).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId)));\n await tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, resultId)));\n }\n await tx.update(memoryOptimizationRuns).set({ status: \"reverted\" }).where(eq(memoryOptimizationRuns.id, run.id));\n return \"ok\" as const;\n });\n },\n\n async listMemoryOptimizationRuns(ownerId, filter) {\n const query = db\n .select()\n .from(memoryOptimizationRuns)\n .where(and(eq(memoryOptimizationRuns.ownerId, ownerId), ...(filter?.status ? [inArray(memoryOptimizationRuns.status, filter.status)] : [])))\n .orderBy(desc(memoryOptimizationRuns.startedAt), sql`${memoryOptimizationRuns.id} collate \"C\" desc`);\n const rows = await (filter?.limit === undefined ? query : query.limit(filter.limit));\n return rows.map(toOptimizationRun);\n },\n\n async listMergedMemoryNotes(ownerId) {\n const rows = await db\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNotNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), sql`${memoryNotes.id} collate \"C\" desc`);\n return rows.map((row): MergedMemoryNote => ({ ...toMemoryNote(row), mergedInto: row.mergedInto! }));\n },\n };\n}\n\ntype UniqueViolation = { code?: unknown; constraint?: unknown; cause?: UniqueViolation };\n\nfunction isPrimaryKeyConflict(error: unknown): boolean {\n return isConflictOn(error, \"messages_pkey\");\n}\n\n/** Нарушен уникальный ключ или индекс с этим именем. */\nfunction isConflictOn(error: unknown, constraintName: string): boolean {\n const { code, constraint, cause } = (error ?? {}) as UniqueViolation;\n return [code, cause?.code].includes(\"23505\") && [constraint, cause?.constraint].includes(constraintName);\n}\n\n/** Запись чата в строку: поле без значения — пусто. */\nfunction chatRow(chat: Chat): typeof chats.$inferSelect {\n return {\n id: chat.id,\n ownerId: chat.ownerId,\n modelId: chat.modelId,\n providerId: chat.providerId,\n reasoning: chat.reasoning ?? null,\n title: chat.title ?? null,\n origin: chat.origin ?? null,\n subjectKey: chat.subjectKey ?? null,\n subjectData: chatDataOfInput(chat) ?? null,\n closed: chat.closed ?? null,\n createdAt: chat.createdAt,\n updatedAt: chat.updatedAt,\n };\n}\n\n/** Строка чата в запись ядра: пустые необязательные поля — отсутствие поля. */\nfunction toChat(row: typeof chats.$inferSelect): Chat {\n const { reasoning, title, origin, subjectKey, subjectData, closed, ...chat } = row;\n return {\n ...chat,\n ...(reasoning !== null && { reasoning }),\n ...(title !== null && { title }),\n ...(origin !== null && { origin }),\n ...(subjectKey !== null && { subjectKey }),\n ...chatDataFields(subjectData),\n ...(closed !== null && { closed }),\n };\n}\n\n/** Фильтр `listChats` по ключу объекта; по умолчанию — только чаты без ключа. */\nfunction subjectCondition(subjects: ChatSubjectFilter = \"exclude\") {\n if (subjects === \"include\") return undefined;\n return subjects === \"only\" ? isNotNull(chats.subjectKey) : isNull(chats.subjectKey);\n}\n\n/** Фильтр `listChats` по данным чата: одно «содержит» (`@>`) по всем ключам; тип значения важен (`true` не равно `1`). */\nfunction dataCondition(filter: ChatDataFilter | undefined) {\n if (!filter || Object.keys(filter).length === 0) return undefined;\n return sql`${chats.subjectData}::jsonb @> ${JSON.stringify(filter)}::jsonb`;\n}\n\n/** Строка сообщения в запись ядра: без служебных колонок; пустое состояние хука итога — отсутствие поля. */\nfunction toMessage(row: typeof messages.$inferSelect): StoredMessage {\n const { seq: _seq, aliveAt: _aliveAt, afterTurn, ...message } = row;\n return { ...message, ...(afterTurn !== null && { afterTurn }) };\n}\n\n/** Строка памяти в запись ядра: без владельца, время — ISO 8601. */\nfunction toMemoryNote(row: typeof memoryNotes.$inferSelect): MemoryNote {\n return {\n id: row.id,\n categories: [...row.categories],\n content: row.content,\n version: row.version,\n createdAt: row.createdAt.toISOString(),\n updatedAt: row.updatedAt.toISOString(),\n };\n}\n\n/** Строка запуска в запись ядра: без владельца, время — ISO 8601. */\nfunction toOptimizationRun(row: typeof memoryOptimizationRuns.$inferSelect): MemoryOptimizationRun {\n return {\n id: row.id,\n startedAt: row.startedAt.toISOString(),\n finishedAt: row.finishedAt ? row.finishedAt.toISOString() : null,\n status: row.status,\n groups: row.groups.map((group) => ({ ...group, originalIds: [...group.originalIds] })),\n error: row.error,\n usageRecordId: row.usageRecordId,\n };\n}\n\n/** Как база с NOT NULL: разделы — список строк, текст — строка. Иначе jsonb принял бы любое значение. */\nfunction assertWellFormedNote(note: MemoryNoteInput): void {\n if (!Array.isArray(note?.categories) || !note.categories.every((category) => typeof category === \"string\")) {\n throw new TypeError(\"Разделы записи памяти — список строк\");\n }\n if (typeof note.content !== \"string\") throw new TypeError(\"Текст записи памяти — строка\");\n}\n","import type {\n AnswerStatus,\n ChatClosure,\n ChatError,\n MemoryMergeGroup,\n MemoryOptimizationStatus,\n StoredMessage,\n TokenUsage,\n TurnRequestContext,\n UsageSource,\n VoiceCut,\n} from \"@ykurilov/agent-chat-core\";\nimport { sql } from \"drizzle-orm\";\nimport { bigint, boolean, doublePrecision, index, integer, json, jsonb, pgSchema, text, timestamp, uniqueIndex } from \"drizzle-orm/pg-core\";\n\n/** Своя схема базы: у приложения могут быть свои `chats` и `messages`. */\nexport const agentChatSchema = pgSchema(\"agent_chat\");\n\nexport const chats = agentChatSchema.table(\n \"chats\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n /** Уровень рассуждений выбранной модели; пусто — у модели нет уровней. */\n reasoning: text(\"reasoning\"),\n /** Название для списка чатов; пусто — чат без названия. */\n title: text(\"title\"),\n /** Мессенджер, из которого создан чат; пусто — чат создан в вебе. */\n origin: text(\"origin\", { enum: [\"telegram\", \"vk\", \"max\"] }),\n /** Ключ объекта приложения; пусто — обычный чат. У владельца ключ не повторяется. */\n subjectKey: text(\"subject_key\"),\n /** Данные объекта (JSON-объект); пусто — данных нет. */\n subjectData: json(\"subject_data\").$type<Record<string, unknown>>(),\n /** Закрытие чата (`{ code, message }`); пусто — чат открыт. */\n closed: json(\"closed\").$type<ChatClosure>(),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [\n index(\"chats_owner_updated_idx\").on(table.ownerId, table.updatedAt),\n uniqueIndex(\"chats_owner_subject_idx\").on(table.ownerId, table.subjectKey),\n ],\n);\n\n// Части, использование и ошибка — `json`, а не `jsonb`: текст хранится как записан (порядок ключей, `\\u0000`).\nexport const messages = agentChatSchema.table(\n \"messages\",\n {\n /** Порядок записи: сообщения с одинаковым временем создания отдаются по нему. */\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n parentId: text(\"parent_id\"),\n role: text(\"role\", { enum: [\"user\", \"assistant\"] }).notNull(),\n parts: json(\"parts\").$type<StoredMessage[\"parts\"]>().notNull(),\n formatVersion: integer(\"format_version\").notNull(),\n status: text(\"status\").$type<AnswerStatus>().notNull(),\n modelId: text(\"model_id\"),\n providerId: text(\"provider_id\"),\n usage: json(\"usage\").$type<TokenUsage>(),\n reasoningDurationsMs: json(\"reasoning_durations_ms\").$type<Record<string, number>>().notNull(),\n error: json(\"error\").$type<ChatError>(),\n /** Отметка обрыва озвучки (голосовой режим); пусто — озвучку не обрывали. */\n voiceCut: json(\"voice_cut\").$type<VoiceCut>(),\n /** Состояние хука итога хода; пусто — хук не зовётся. */\n afterTurn: text(\"after_turn\", { enum: [\"pending\", \"done\", \"failed\"] }),\n createdAt: text(\"created_at\").notNull(),\n /** Последний знак жизни идущего ответа (ISO); пусто — время создания. Только для восстановления, при чтении не отдаётся. */\n aliveAt: text(\"alive_at\"),\n },\n (table) => [\n index(\"messages_chat_created_idx\").on(table.chatId, table.createdAt, table.seq),\n index(\"messages_streaming_idx\").on(table.status).where(sql`${table.status} = 'streaming'`),\n index(\"messages_after_turn_pending_idx\").on(table.afterTurn).where(sql`${table.afterTurn} = 'pending'`),\n ],\n);\n\n/** Записи сжатия: только добавляются. Порядок добавления — `seq`. */\nexport const compactions = agentChatSchema.table(\n \"compactions\",\n {\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n fromMessageId: text(\"from_message_id\").notNull(),\n throughMessageId: text(\"through_message_id\").notNull(),\n summary: text(\"summary\").notNull(),\n summaryTokens: integer(\"summary_tokens\").notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n usage: json(\"usage\").$type<TokenUsage>(),\n createdAt: text(\"created_at\").notNull(),\n },\n (table) => [index(\"compactions_chat_seq_idx\").on(table.chatId, table.seq)],\n);\n\n/** Отметки выбора ветки: только добавляются. Порядок добавления — `seq`. */\nexport const branchSelections = agentChatSchema.table(\n \"branch_selections\",\n {\n seq: bigint(\"seq\", { mode: \"number\" }).generatedAlwaysAsIdentity().notNull(),\n id: text(\"id\").primaryKey(),\n chatId: text(\"chat_id\")\n .notNull()\n .references(() => chats.id, { onDelete: \"cascade\" }),\n messageId: text(\"message_id\").notNull(),\n selectedAt: text(\"selected_at\").notNull(),\n },\n (table) => [index(\"branch_selections_chat_seq_idx\").on(table.chatId, table.seq)],\n);\n\n/**\n * Журнал расхода токенов: только добавляется и не связан с чатами внешним ключом, чтобы переживать их удаление.\n * Месячный расход человека от удаления переписки не убывает.\n */\nexport const usageRecords = agentChatSchema.table(\n \"usage_records\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n chatId: text(\"chat_id\").notNull(),\n messageId: text(\"message_id\"),\n source: text(\"source\").$type<UsageSource>().notNull(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n inputTokens: bigint(\"input_tokens\", { mode: \"number\" }).notNull(),\n cachedInputTokens: bigint(\"cached_input_tokens\", { mode: \"number\" }).notNull(),\n cacheWriteTokens: bigint(\"cache_write_tokens\", { mode: \"number\" }).notNull(),\n outputTokens: bigint(\"output_tokens\", { mode: \"number\" }).notNull(),\n reasoningTokens: bigint(\"reasoning_tokens\", { mode: \"number\" }).notNull(),\n costUsd: doublePrecision(\"cost_usd\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n /** Числа «примерно»: прикинуты по длине текста, а не сообщены провайдером. */\n estimated: boolean(\"estimated\").notNull().default(false),\n },\n (table) => [\n index(\"usage_records_owner_created_idx\").on(table.ownerId, table.createdAt),\n index(\"usage_records_chat_created_idx\").on(table.chatId, table.createdAt),\n ],\n);\n\n/** Последний выбор модели человека для новых чатов: одна строка на человека; с чатами не связан. */\nexport const userModelChoices = agentChatSchema.table(\"user_model_choices\", {\n ownerId: text(\"owner_id\").primaryKey(),\n modelId: text(\"model_id\").notNull(),\n providerId: text(\"provider_id\").notNull(),\n /** Пусто — у модели нет уровней рассуждений. */\n reasoning: text(\"reasoning\"),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** Выбранный человеком голос озвучки: одна строка на человека; с чатами и выбором модели не связан. */\nexport const voiceChoices = agentChatSchema.table(\"voice_choices\", {\n ownerId: text(\"owner_id\").primaryKey(),\n voiceId: text(\"voice_id\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** Состояние лимитов расходов по ключу: значение — строка (JSON решает ядро); `version` растёт на 1 при каждой записи и служит замком. */\nexport const spendingLimitStates = agentChatSchema.table(\"spending_limit_states\", {\n key: text(\"key\").primaryKey(),\n value: text(\"value\").notNull(),\n version: integer(\"version\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/**\n * Аренда хода чата между копиями сервера: кто держит (`holder`) и до какого времени (`until`, по часам базы). Внешним\n * ключом с чатом не связана: удаление чата снимает её само.\n */\nexport const chatTurnLeases = agentChatSchema.table(\"chat_turn_leases\", {\n chatId: text(\"chat_id\").primaryKey(),\n holder: text(\"holder\").notNull(),\n until: timestamp(\"until\", { withTimezone: true, mode: \"string\" }).notNull(),\n});\n\n/**\n * Ждущие пачки сообщений человека: одна запись на чат. Сроки — по часам службы. Внешним ключом с чатом не связана:\n * удаление чата снимает её само.\n */\nexport const pendingBursts = agentChatSchema.table(\"pending_bursts\", {\n chatId: text(\"chat_id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n messageId: text(\"message_id\").notNull(),\n dueAt: timestamp(\"due_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n holder: text(\"holder\").notNull(),\n heldUntil: timestamp(\"held_until\", { withTimezone: true, mode: \"date\" }).notNull(),\n page: jsonb(\"page\").$type<TurnRequestContext>(),\n});\n\n/**\n * Долгая память: записи принадлежат человеку и с чатами не связаны внешним ключом, чтобы переживать их удаление.\n * `version` — замок правки и удаления: растёт на 1 при каждой правке.\n */\nexport const memoryNotes = agentChatSchema.table(\n \"memory_notes\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n categories: jsonb(\"categories\").$type<string[]>().notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n createdAt: timestamp(\"created_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n /** Оптимизация дублей: id записи-результата у скрытого оригинала слияния; у обычных записей пусто. */\n mergedInto: text(\"merged_into\"),\n },\n (table) => [\n index(\"memory_notes_owner_updated_idx\").on(table.ownerId, table.updatedAt),\n index(\"memory_notes_merged_into_idx\").on(table.mergedInto),\n ],\n);\n\n/**\n * Оптимизация дублей: запуски человека. `groups` — список склеек (результат, оригиналы, версия результата на\n * момент слияния). Запуск `running` у человека не больше одного: за этим следит частичный уникальный индекс.\n */\nexport const memoryOptimizationRuns = agentChatSchema.table(\n \"memory_optimization_runs\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n startedAt: timestamp(\"started_at\", { withTimezone: true, mode: \"date\" }).notNull(),\n finishedAt: timestamp(\"finished_at\", { withTimezone: true, mode: \"date\" }),\n status: text(\"status\").$type<MemoryOptimizationStatus>().notNull(),\n groups: jsonb(\"groups\").$type<MemoryMergeGroup[]>().notNull().default(sql`'[]'::jsonb`),\n error: text(\"error\"),\n usageRecordId: text(\"usage_record_id\"),\n },\n (table) => [\n index(\"memory_optimization_runs_owner_started_idx\").on(table.ownerId, table.startedAt),\n uniqueIndex(\"memory_optimization_runs_one_running_idx\").on(table.ownerId).where(sql`${table.status} = 'running'`),\n ],\n);\n","import { fileURLToPath } from \"node:url\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport { migrate } from \"drizzle-orm/node-postgres/migrator\";\nimport { migratePostgresSchema } from \"@ykurilov/agent-chat-core\";\nimport type { Pool } from \"pg\";\n\nconst migrationsFolder = fileURLToPath(new URL(\"../drizzle\", import.meta.url));\n\n/** Постоянное число для блокировки базы: одинаково у всех серверов и всех версий SDK. */\nconst MIGRATION_LOCK_KEY = 7_311_900_442;\n\n/**\n * Приводит схему `agent_chat` к последней миграции. Схема `agent_chat` создаётся под общей блокировкой всех пакетов, миграции — под своей:\n * копии пакета ждут друг друга, а разные пакеты стартуют разом на пустой базе без гонки за схему.\n */\nexport async function migrateToLatest(pool: Pool): Promise<void> {\n await migratePostgresSchema({\n connect: () => pool.connect(),\n lockKey: MIGRATION_LOCK_KEY,\n migrate: (client) => migrate(drizzle(client), { migrationsFolder, migrationsSchema: \"agent_chat\" }),\n });\n}\n"],"mappings":"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","names":["drizzle","sql","sql","index","drizzle"]}
|
|
@@ -437,9 +437,7 @@ export declare const storageSchema: {
|
|
|
437
437
|
tableName: "messages";
|
|
438
438
|
dataType: "json";
|
|
439
439
|
columnType: "PgJson";
|
|
440
|
-
data:
|
|
441
|
-
kind: import("@ykurilov/agent-chat-core").ChatErrorKind;
|
|
442
|
-
};
|
|
440
|
+
data: import("@ykurilov/agent-chat-core").ChatError;
|
|
443
441
|
driverParam: unknown;
|
|
444
442
|
notNull: false;
|
|
445
443
|
hasDefault: false;
|
|
@@ -451,9 +449,7 @@ export declare const storageSchema: {
|
|
|
451
449
|
identity: undefined;
|
|
452
450
|
generated: undefined;
|
|
453
451
|
}, {}, {
|
|
454
|
-
$type:
|
|
455
|
-
kind: import("@ykurilov/agent-chat-core").ChatErrorKind;
|
|
456
|
-
};
|
|
452
|
+
$type: import("@ykurilov/agent-chat-core").ChatError;
|
|
457
453
|
}>;
|
|
458
454
|
voiceCut: import("drizzle-orm/pg-core").PgColumn<{
|
|
459
455
|
name: "voice_cut";
|
package/dist/types/schema.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnswerStatus, ChatClosure,
|
|
1
|
+
import type { AnswerStatus, ChatClosure, ChatError, MemoryMergeGroup, MemoryOptimizationStatus, TokenUsage, TurnRequestContext, UsageSource, VoiceCut } from "@ykurilov/agent-chat-core";
|
|
2
2
|
/** Своя схема базы: у приложения могут быть свои `chats` и `messages`. */
|
|
3
3
|
export declare const agentChatSchema: import("drizzle-orm/pg-core").PgSchema<"agent_chat">;
|
|
4
4
|
export declare const chats: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
@@ -437,9 +437,7 @@ export declare const messages: import("drizzle-orm/pg-core").PgTableWithColumns<
|
|
|
437
437
|
tableName: "messages";
|
|
438
438
|
dataType: "json";
|
|
439
439
|
columnType: "PgJson";
|
|
440
|
-
data:
|
|
441
|
-
kind: ChatErrorKind;
|
|
442
|
-
};
|
|
440
|
+
data: ChatError;
|
|
443
441
|
driverParam: unknown;
|
|
444
442
|
notNull: false;
|
|
445
443
|
hasDefault: false;
|
|
@@ -451,9 +449,7 @@ export declare const messages: import("drizzle-orm/pg-core").PgTableWithColumns<
|
|
|
451
449
|
identity: undefined;
|
|
452
450
|
generated: undefined;
|
|
453
451
|
}, {}, {
|
|
454
|
-
$type:
|
|
455
|
-
kind: ChatErrorKind;
|
|
456
|
-
};
|
|
452
|
+
$type: ChatError;
|
|
457
453
|
}>;
|
|
458
454
|
voiceCut: import("drizzle-orm/pg-core").PgColumn<{
|
|
459
455
|
name: "voice_cut";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ykurilov/agent-chat-storage-postgres",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.65.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"drizzle-orm": "^0.45.3",
|
|
34
34
|
"pg": "^8.23.0",
|
|
35
|
-
"@ykurilov/agent-chat-core": "0.
|
|
35
|
+
"@ykurilov/agent-chat-core": "0.65.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@electric-sql/pglite": "0.5.8",
|
|
39
39
|
"@electric-sql/pglite-socket": "0.2.11",
|
|
40
40
|
"@types/pg": "^8.23.1",
|
|
41
41
|
"drizzle-kit": "^0.31.11",
|
|
42
|
-
"@ykurilov/agent-chat-storage-sqlite": "0.
|
|
42
|
+
"@ykurilov/agent-chat-storage-sqlite": "0.65.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "node ../../scripts/build-package.mjs",
|