@ykurilov/agent-chat-storage-sqlite 0.56.0 → 0.57.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @ykurilov/agent-chat-storage-sqlite
2
2
 
3
+ ## 0.57.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ade99cc: Окно тишины `sendBurstMessage` ждётся по часам службы (`now`): `service.tickBursts()` сверяет ждущие пачки с подменёнными
8
+ часами — в тестах без настоящих пауз. Новый флаг `answerAfterRestart`: ждущая пачка записана в хранилище (новые
9
+ необязательные методы `savePendingBurst`, `takeAbandonedBursts`, `renewPendingBurst`, `removePendingBurst`; таблица `pending_bursts`,
10
+ миграции SQLite 0018 и PostgreSQL 0017) и после перезапуска получает ответ без повтора вызова — событием `turn-started`
11
+ с `unattended: true`. Отвечает по-прежнему одна копия.
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [ade99cc]
16
+ - Updated dependencies [86afa20]
17
+ - Updated dependencies [624c10c]
18
+ - @ykurilov/agent-chat-core@0.57.0
19
+
3
20
  ## 0.56.0
4
21
 
5
22
  ### Patch Changes
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  silenceBoundaryByLocalClock
19
19
  } from "@ykurilov/agent-chat-core";
20
20
  import Database from "better-sqlite3";
21
- import { and, asc, desc, eq, gte, inArray, isNotNull, isNull, sql as sql2 } from "drizzle-orm";
21
+ import { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, ne, sql as sql2 } from "drizzle-orm";
22
22
  import { drizzle } from "drizzle-orm/better-sqlite3";
23
23
  import { readMigrationFiles } from "drizzle-orm/migrator";
24
24
 
@@ -166,6 +166,15 @@ var chatTurnLeases = sqliteTable("chat_turn_leases", {
166
166
  holder: text("holder").notNull(),
167
167
  until: integer("until").notNull()
168
168
  });
169
+ var pendingBursts = sqliteTable("pending_bursts", {
170
+ chatId: text("chat_id").primaryKey(),
171
+ ownerId: text("owner_id").notNull(),
172
+ messageId: text("message_id").notNull(),
173
+ dueAt: integer("due_at").notNull(),
174
+ holder: text("holder").notNull(),
175
+ heldUntil: integer("held_until").notNull(),
176
+ page: text("page", { mode: "json" }).$type()
177
+ });
169
178
  var memoryNotes = sqliteTable(
170
179
  "memory_notes",
171
180
  {
@@ -417,6 +426,7 @@ function createSqliteChatStorage(options) {
417
426
  tx.delete(messages).where(eq(messages.chatId, chatId)).run();
418
427
  tx.delete(chats).where(eq(chats.id, chatId)).run();
419
428
  tx.delete(chatTurnLeases).where(eq(chatTurnLeases.chatId, chatId)).run();
429
+ tx.delete(pendingBursts).where(eq(pendingBursts.chatId, chatId)).run();
420
430
  }, { behavior: "immediate" });
421
431
  },
422
432
  async claimChatTurn(chatId, holder, leaseMs) {
@@ -434,6 +444,41 @@ function createSqliteChatStorage(options) {
434
444
  async clearChatTurnLeases() {
435
445
  db.delete(chatTurnLeases).run();
436
446
  },
447
+ async savePendingBurst(burst) {
448
+ const row = {
449
+ chatId: burst.chatId,
450
+ ownerId: burst.ownerId,
451
+ messageId: burst.messageId,
452
+ dueAt: Date.parse(burst.dueAt),
453
+ holder: burst.holder,
454
+ heldUntil: Date.parse(burst.heldUntil),
455
+ page: burst.page ?? null
456
+ };
457
+ db.insert(pendingBursts).values(row).onConflictDoUpdate({ target: pendingBursts.chatId, set: row }).run();
458
+ },
459
+ async takeAbandonedBursts({ abandonedBefore, holder, heldUntil, limit, exceptHolder }) {
460
+ return db.transaction((tx) => {
461
+ const abandoned = tx.select().from(pendingBursts).where(and(lte(pendingBursts.heldUntil, Date.parse(abandonedBefore)), exceptHolder === void 0 ? void 0 : ne(pendingBursts.holder, exceptHolder))).orderBy(asc(pendingBursts.dueAt)).limit(limit).all();
462
+ const until = Date.parse(heldUntil);
463
+ for (const row of abandoned) tx.update(pendingBursts).set({ holder, heldUntil: until }).where(eq(pendingBursts.chatId, row.chatId)).run();
464
+ return abandoned.map((row) => ({
465
+ chatId: row.chatId,
466
+ ownerId: row.ownerId,
467
+ messageId: row.messageId,
468
+ dueAt: new Date(row.dueAt).toISOString(),
469
+ holder,
470
+ heldUntil,
471
+ ...row.page && { page: row.page }
472
+ }));
473
+ }, { behavior: "immediate" });
474
+ },
475
+ async renewPendingBurst({ chatId, messageId, holder, heldUntil }) {
476
+ const renewed = db.update(pendingBursts).set({ heldUntil: Date.parse(heldUntil) }).where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId), eq(pendingBursts.holder, holder))).run();
477
+ return renewed.changes > 0;
478
+ },
479
+ async removePendingBurst(chatId, messageId) {
480
+ db.delete(pendingBursts).where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId))).run();
481
+ },
437
482
  async getMessage(messageId) {
438
483
  const row = db.select().from(messages).where(eq(messages.id, messageId)).get();
439
484
  if (!row) return null;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sqlite-storage.ts","../src/schema.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport {\n aliveAtByLocalClock,\n assertChatDataFilter,\n assertKnownFormatVersion,\n ChatAlreadyExistsError,\n chatDataFields,\n chatDataOfInput,\n DuplicateChatSubjectError,\n DuplicateMessageError,\n isOptimizationBlocked,\n mergeChatData,\n MessageAlreadyFinishedError,\n MessageNotAwaitingError,\n revertRefusal,\n sameMessageParts,\n silenceBoundaryByLocalClock,\n} from \"@ykurilov/agent-chat-core\";\nimport type { AnswerAliveMark, Chat, ChatDataFilter, ChatListOptions, ChatStorage, ChatSubjectFilter, MemoryMergeGroup, MemoryNote, MemoryNoteInput, MemoryOptimizationRun, MergedMemoryNote, StoredMessage } from \"@ykurilov/agent-chat-core\";\nimport Database from \"better-sqlite3\";\nimport { and, asc, desc, eq, gte, inArray, isNotNull, isNull, sql } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { readMigrationFiles } from \"drizzle-orm/migrator\";\nimport { branchSelections, chats, chatTurnLeases, compactions, memoryNotes, memoryOptimizationRuns, messages, spendingLimitStates, usageRecords, userModelChoices, voiceChoices } from \"./schema\";\n\nexport interface SqliteChatStorage extends ChatStorage {\n /** Закрывает файл базы. */\n close(): void;\n}\n\nconst migrationsFolder = fileURLToPath(new URL(\"../drizzle\", import.meta.url));\n/** Свой журнал миграций SDK: общий журнал drizzle в файле может вести и приложение. */\nconst MIGRATIONS_TABLE = \"__agent_chat_migrations\";\n/** Общий журнал drizzle: в нём SDK вёл свои миграции до 0.32. */\nconst SHARED_MIGRATIONS_TABLE = \"__drizzle_migrations\";\n\n/** В файле таблицы `chats` или `messages` создал не SDK: открывать такой файл нельзя, миграции испортили бы чужие данные. */\nexport class ForeignChatTablesError extends Error {\n constructor(\n readonly filePath: string,\n readonly tables: readonly string[],\n ) {\n super(\n `В файле ${filePath} чужие таблицы ${tables.join(\" и \")}: их создало не SDK чата. ` +\n `Дайте SDK отдельный файл (например, data/chat.sqlite): общий файл с таблицами приложения не поддерживается. Файл не тронут.`,\n );\n this.name = \"ForeignChatTablesError\";\n }\n}\n\n/**\n * Таблицы SDK узнаются по журналу миграций: в нём есть запись первой миграции SDK. Нет `chats`/`messages` — файл\n * пустой или со своими другими таблицами приложения, SDK создаст свои рядом. Есть, а записи нет — таблицы чужие.\n */\nfunction assertNoForeignChatTables(sqlite: Database.Database, filePath: string): void {\n const names = tableNames(sqlite);\n const found = [\"chats\", \"messages\"].filter((name) => names.has(name));\n if (found.length === 0) return;\n const firstMigrationHash = readMigrationFiles({ migrationsFolder })[0]?.hash;\n const ours = [MIGRATIONS_TABLE, SHARED_MIGRATIONS_TABLE].some((table) => {\n try {\n return names.has(table) && sqlite.prepare(`select 1 from \"${table}\" where hash = ?`).get(firstMigrationHash) !== undefined;\n } catch {\n // У журнала приложения другие колонки: он не наш.\n return false;\n }\n });\n if (!ours) throw new ForeignChatTablesError(filePath, found);\n}\n\nfunction tableNames(sqlite: Database.Database): Set<string> {\n return new Set(sqlite.prepare(\"select name from sqlite_master where type = 'table'\").pluck().all() as string[]);\n}\n\n/**\n * До 0.32 SDK вёл миграции в общем журнале drizzle. drizzle смотрит только на время последней записи: запись приложения\n * новее миграций SDK заставляла их пропускать. Записи SDK (узнаются по хешу или времени своих миграций) один раз\n * копируются в свой журнал; общий журнал не меняется. Под замком записи: две копии сервера не перенесут дважды.\n */\nfunction moveSharedMigrationJournal(sqlite: Database.Database): void {\n sqlite\n .transaction(() => {\n const names = tableNames(sqlite);\n if (names.has(MIGRATIONS_TABLE) || !names.has(SHARED_MIGRATIONS_TABLE)) return;\n let rows: Array<{ hash: string; created_at: number }>;\n try {\n rows = sqlite.prepare(`select hash, created_at from \"${SHARED_MIGRATIONS_TABLE}\"`).all() as typeof rows;\n } catch {\n // У журнала приложения другие колонки: записей SDK в нём нет.\n return;\n }\n const sdk = readMigrationFiles({ migrationsFolder });\n const ours = rows.filter((row) => sdk.some((migration) => migration.hash === row.hash || migration.folderMillis === Number(row.created_at)));\n if (ours.length === 0) return;\n // Та же таблица, что создаёт drizzle для журнала.\n sqlite.exec(`create table \"${MIGRATIONS_TABLE}\" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)`);\n const insert = sqlite.prepare(`insert into \"${MIGRATIONS_TABLE}\" (hash, created_at) values (?, ?)`);\n for (const row of ours) insert.run(row.hash, row.created_at);\n })\n .immediate();\n}\n\n/**\n * Применяет миграции SDK, которых нет в своём журнале. Применённой считается миграция, чей хеш или время есть в журнале\n * (drizzle пишет время миграции из `_journal.json`). drizzle сверяет только последнюю запись, поэтому дыру в середине,\n * оставленную общим журналом до 0.32, не видит; здесь она закрывается. Такие миграции идут не по порядку, и это безопасно:\n * пропасть могли только миграции до 0.32, а они лишь добавляют таблицы, столбцы и индексы (это проверяет тест).\n * Журнал тот же, что у drizzle. Всё — одной транзакцией под замком записи: две копии сервера не применят миграцию дважды.\n */\nfunction applyMigrations(sqlite: Database.Database): void {\n const migrations = readMigrationFiles({ migrationsFolder });\n sqlite\n .transaction(() => {\n sqlite.exec(`create table if not exists \"${MIGRATIONS_TABLE}\" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)`);\n const rows = sqlite.prepare(`select hash, created_at from \"${MIGRATIONS_TABLE}\"`).all() as Array<{ hash: string; created_at: number }>;\n const hashes = new Set(rows.map((row) => row.hash));\n const times = new Set(rows.map((row) => Number(row.created_at)));\n const record = sqlite.prepare(`insert into \"${MIGRATIONS_TABLE}\" (hash, created_at) values (?, ?)`);\n for (const migration of migrations) {\n if (hashes.has(migration.hash) || times.has(migration.folderMillis)) continue;\n for (const statement of migration.sql) if (statement.trim()) sqlite.exec(statement);\n record.run(migration.hash, migration.folderMillis);\n }\n })\n .immediate();\n}\n\n/** Хранилище в файле SQLite. Схема приводится к последней миграции при открытии. */\nexport function createSqliteChatStorage(options: { filePath: string }): SqliteChatStorage {\n const sqlite = new Database(options.filePath);\n try {\n assertNoForeignChatTables(sqlite, options.filePath);\n moveSharedMigrationJournal(sqlite);\n } catch (error) {\n sqlite.close();\n throw error;\n }\n sqlite.pragma(\"journal_mode = WAL\");\n sqlite.pragma(\"foreign_keys = ON\");\n const db = drizzle(sqlite, { schema: { chats, messages, compactions, branchSelections, usageRecords, userModelChoices, voiceChoices, spendingLimitStates, memoryNotes, memoryOptimizationRuns } });\n applyMigrations(sqlite);\n\n // Транзакции, которые пишут, — «immediate»: запись базы берётся сразу. Иначе чтение и запись разрывались бы, и вторая\n // копия сервера на том же файле роняла бы запись ошибкой «database is locked» вместо ожидания очереди.\n type Transaction = Parameters<Parameters<typeof db.transaction>[0]>[0];\n\n function visibleNotes(tx: Transaction, ownerId: string): MemoryNote[] {\n return tx\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), desc(memoryNotes.id))\n .all()\n .map(toMemoryNote);\n }\n\n function insertNotes(tx: Transaction, ownerId: string, inputs: MemoryNoteInput[]): MemoryNote[] {\n const now = Date.now();\n const rows = inputs.map(({ categories, content }): typeof memoryNotes.$inferInsert => ({\n id: crypto.randomUUID(),\n ownerId,\n categories,\n content,\n version: 1,\n createdAt: now,\n updatedAt: now,\n }));\n for (const row of rows) tx.insert(memoryNotes).values(row).run();\n return rows.map((row) => toMemoryNote(row as typeof memoryNotes.$inferSelect));\n }\n\n function updateNote(tx: Transaction, ownerId: string, id: string, expectedVersion: number, input: MemoryNoteInput): MemoryNote | \"not_found\" | \"stale_version\" {\n const row = tx.select().from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (!row) return \"not_found\";\n if (row.version !== expectedVersion) return \"stale_version\";\n const updated = tx\n .update(memoryNotes)\n .set({\n categories: input.categories,\n content: input.content,\n version: row.version + 1,\n // Часы не отстают от записи: время правки не убывает.\n updatedAt: Math.max(Date.now(), row.updatedAt),\n })\n .where(and(ownerNote(ownerId, id), eq(memoryNotes.version, expectedVersion)))\n .returning()\n .get();\n return updated ? toMemoryNote(updated) : \"stale_version\";\n }\n\n /** Знак жизни в колонку `alive_at`: SQLite живёт на одной машине с сервером, время — по её часам. */\n const aliveAtColumn = (alive: AnswerAliveMark | undefined) => (alive ? { aliveAt: aliveAtByLocalClock(alive) } : {});\n\n /** Пишет в идущий ответ; отличает «нет такого» от «уже в конечном состоянии». */\n function updateStreaming(messageId: string, { alive, ...values }: Partial<typeof messages.$inferInsert> & { alive?: AnswerAliveMark }): void {\n const result = db\n .update(messages)\n .set({ ...values, ...aliveAtColumn(alive) })\n .where(and(eq(messages.id, messageId), eq(messages.status, \"streaming\")))\n .run();\n if (result.changes > 0) return;\n const existing = db.select({ id: messages.id }).from(messages).where(eq(messages.id, messageId)).get();\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n throw new MessageAlreadyFinishedError(messageId);\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 db.insert(chats).values(row).run();\n } catch (error) {\n if (isSubjectConflict(error)) 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 = db.select().from(chats).where(and(eq(chats.ownerId, ownerId), eq(chats.subjectKey, subjectKey))).get();\n return row ? toChat(row) : null;\n },\n\n async importChat(chat, imported) {\n db.transaction((tx) => {\n try {\n tx.insert(chats).values(chatRow(chat)).run();\n } catch (error) {\n if (isSubjectConflict(error)) throw new DuplicateChatSubjectError(chat.ownerId, chat.subjectKey!);\n if (isPrimaryKeyConflict(error)) throw new ChatAlreadyExistsError(chat.id);\n throw error;\n }\n for (const message of imported) {\n const nextSeq = sql<number>`(select coalesce(max(${messages.seq}), 0) + 1 from ${messages})`;\n const { alive: _alive, ...stored } = message;\n try {\n tx.insert(messages).values({ ...stored, seq: nextSeq }).run();\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n }\n }, { behavior: \"immediate\" });\n },\n\n async setAfterTurnState(messageId, state, options) {\n // Чтение, проверка состояния и запись — одна транзакция с блокировкой записи: другая копия не вклинится.\n return db.transaction(\n (tx) => {\n const existing = tx.select({ parts: messages.parts, afterTurn: messages.afterTurn }).from(messages).where(eq(messages.id, messageId)).get();\n if (!existing || (state !== \"pending\" && existing.afterTurn !== \"pending\")) return false;\n tx.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 .run();\n return true;\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listPendingAfterTurn(filter) {\n return db\n .select({ id: messages.id })\n .from(messages)\n .where(\n filter?.pendingForMs === undefined\n ? eq(messages.afterTurn, \"pending\")\n : and(\n eq(messages.afterTurn, \"pending\"),\n sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${silenceBoundaryByLocalClock(filter.pendingForMs)}`,\n ),\n )\n .all()\n .map((row) => row.id);\n },\n\n async getChat(chatId) {\n const row = db.select().from(chats).where(eq(chats.id, chatId)).get();\n return row ? toChat(row) : null;\n },\n\n async updateChatModel(chatId, model) {\n db.update(chats)\n .set({ modelId: model.modelId, providerId: model.providerId, reasoning: model.reasoning ?? null })\n .where(eq(chats.id, chatId))\n .run();\n },\n\n async updateChatData(chatId, patch, { maxBytes }) {\n // Чтение, слияние и запись — одна транзакция с блокировкой на запись: параллельные правки не затирают друг друга.\n return db.transaction(\n (tx) => {\n const row = tx.select().from(chats).where(eq(chats.id, chatId)).get();\n if (!row) return null;\n const merged = mergeChatData(row.subjectData ?? undefined, patch, maxBytes);\n tx.update(chats).set({ subjectData: merged ?? null }).where(eq(chats.id, chatId)).run();\n return toChat({ ...row, subjectData: merged ?? null });\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listChats(ownerId, options?: ChatListOptions) {\n if (options?.data) assertChatDataFilter(options.data);\n const rows = db\n .select()\n .from(chats)\n .where(and(eq(chats.ownerId, ownerId), subjectCondition(options?.subjects), ...dataConditions(options?.data)))\n .orderBy(desc(chats.updatedAt), desc(chats.createdAt), desc(chats.id))\n .all();\n return rows.map(toChat);\n },\n\n async renameChat(chatId, title) {\n db.update(chats).set({ title }).where(eq(chats.id, chatId)).run();\n },\n\n async setChatClosed(chatId, closed) {\n db.update(chats).set({ closed: closed && { code: closed.code, message: closed.message } }).where(eq(chats.id, chatId)).run();\n },\n\n async deleteChat(chatId) {\n db.transaction((tx) => {\n tx.delete(compactions).where(eq(compactions.chatId, chatId)).run();\n tx.delete(branchSelections).where(eq(branchSelections.chatId, chatId)).run();\n tx.delete(messages).where(eq(messages.chatId, chatId)).run();\n tx.delete(chats).where(eq(chats.id, chatId)).run();\n tx.delete(chatTurnLeases).where(eq(chatTurnLeases.chatId, chatId)).run();\n }, { behavior: \"immediate\" });\n },\n\n async claimChatTurn(chatId, holder, leaseMs) {\n const now = Date.now();\n // Одной записью: свободный чат — вставка; своя или просроченная чужая — замена; живая чужая — ничего.\n const claimed = db\n .insert(chatTurnLeases)\n .values({ chatId, holder, until: now + leaseMs })\n .onConflictDoUpdate({\n target: chatTurnLeases.chatId,\n set: { holder, until: now + leaseMs },\n setWhere: sql`${chatTurnLeases.holder} = ${holder} or ${chatTurnLeases.until} <= ${now}`,\n })\n .returning({ chatId: chatTurnLeases.chatId })\n .all();\n return claimed.length > 0;\n },\n\n async releaseChatTurn(chatId, holder) {\n db.delete(chatTurnLeases).where(and(eq(chatTurnLeases.chatId, chatId), eq(chatTurnLeases.holder, holder))).run();\n },\n\n async clearChatTurnLeases() {\n db.delete(chatTurnLeases).run();\n },\n\n async getMessage(messageId) {\n const row = db.select().from(messages).where(eq(messages.id, messageId)).get();\n if (!row) return null;\n const message = toMessage(row);\n assertKnownFormatVersion(message);\n return message;\n },\n\n // При равном времени порядок записи задаёт `seq`: `rowid` VACUUM вправе перенумеровать.\n async listMessages(chatId) {\n const rows = db\n .select()\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), messages.seq)\n .all();\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), messages.seq)\n .all();\n },\n\n // Части нужных типов выбираются внутри базы: тексты и выводы инструментов в процесс не идут.\n async listMessagePartsOfTypes(chatId, types) {\n const wanted = JSON.stringify([...types]);\n const rows = db\n .select({\n id: messages.id,\n parentId: messages.parentId,\n createdAt: messages.createdAt,\n parts: sql<string>`(select coalesce(json_group_array(json(picked.value)), '[]') from (select part.value from json_each(${messages.parts}) as part where json_extract(part.value, '$.type') in (select value from json_each(${wanted})) order by part.key) as picked)`,\n })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), messages.seq)\n .all();\n return rows.map((row) => ({ ...row, parts: JSON.parse(row.parts) as StoredMessage[\"parts\"] }));\n },\n\n async insertMessage(message) {\n try {\n db.transaction((tx) => {\n const nextSeq = sql<number>`(select coalesce(max(${messages.seq}), 0) + 1 from ${messages})`;\n const { alive, ...stored } = message;\n tx.insert(messages).values({ ...stored, ...aliveAtColumn(alive), seq: nextSeq }).run();\n tx.update(chats).set({ updatedAt: message.createdAt }).where(eq(chats.id, message.chatId)).run();\n }, { behavior: \"immediate\" });\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n },\n\n updateStreamingMessage: async (messageId, patch) => updateStreaming(messageId, patch),\n\n markAnswerAlive: async (messageId) => updateStreaming(messageId, { alive: \"now\" }),\n\n finishMessage: async (messageId, final) => updateStreaming(messageId, { ...final, ...(final.afterTurn === \"pending\" && { alive: \"now\" as const }) }),\n\n async updateAwaitingMessage(messageId, patch) {\n // Чтение, сравнение частей и запись — одна транзакция с блокировкой записи: другая копия не вклинится между ними.\n db.transaction(\n (tx) => {\n const existing = tx.select({ status: messages.status, parts: messages.parts }).from(messages).where(eq(messages.id, messageId)).get();\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 tx.update(messages)\n .set({ parts: patch.parts, ...(patch.status && { status: patch.status }), ...aliveAtColumn(patch.alive) })\n .where(eq(messages.id, messageId))\n .run();\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listStreamingMessageIds() {\n return db\n .select({ id: messages.id })\n .from(messages)\n .where(eq(messages.status, \"streaming\"))\n .all()\n .map((row) => row.id);\n },\n\n async listSilentAnswerIds({ silentForMs, chatId }) {\n const silent = sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${silenceBoundaryByLocalClock(silentForMs)}`;\n return 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 .all()\n .map((row) => row.id);\n },\n\n async insertCompaction(record) {\n const nextSeq = sql<number>`(select coalesce(max(${compactions.seq}), 0) + 1 from ${compactions})`;\n db.insert(compactions).values({ ...record, seq: nextSeq }).run();\n },\n\n async listCompactions(chatId) {\n const rows = db.select().from(compactions).where(eq(compactions.chatId, chatId)).orderBy(asc(compactions.seq)).all();\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertBranchSelection(record) {\n const nextSeq = sql<number>`(select coalesce(max(${branchSelections.seq}), 0) + 1 from ${branchSelections})`;\n db.insert(branchSelections).values({ ...record, seq: nextSeq }).run();\n },\n\n async listBranchSelections(chatId) {\n const rows = db.select().from(branchSelections).where(eq(branchSelections.chatId, chatId)).orderBy(asc(branchSelections.seq)).all();\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertUsageRecord(record) {\n db.insert(usageRecords).values(record).run();\n },\n\n async hasUsageRecord(id) {\n return db.select({ id: usageRecords.id }).from(usageRecords).where(eq(usageRecords.id, id)).get() !== undefined;\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 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 .all();\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 .all();\n },\n\n async getUserModelChoice(ownerId) {\n const row = db.select().from(userModelChoices).where(eq(userModelChoices.ownerId, ownerId)).get();\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 db.insert(userModelChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: userModelChoices.ownerId, set: values }).run();\n },\n\n async setVoiceCut({ ownerId, chatId, messageId, voiceCut }) {\n db.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 .run();\n },\n\n async getSpendingLimitState(key) {\n const row = db.select().from(spendingLimitStates).where(eq(spendingLimitStates.key, key)).get();\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 return db.insert(spendingLimitStates).values({ key, value, version: 1, updatedAt }).onConflictDoNothing().run().changes === 1;\n }\n const changed = db\n .update(spendingLimitStates)\n .set({ value, version: expectedVersion + 1, updatedAt })\n .where(and(eq(spendingLimitStates.key, key), eq(spendingLimitStates.version, expectedVersion)))\n .run().changes;\n return changed === 1;\n },\n\n async deleteSpendingLimitStates(keys) {\n if (keys.length > 0) db.delete(spendingLimitStates).where(inArray(spendingLimitStates.key, keys)).run();\n },\n\n async getVoiceChoice(ownerId) {\n return db.select().from(voiceChoices).where(eq(voiceChoices.ownerId, ownerId)).get()?.voiceId ?? null;\n },\n\n async setVoiceChoice(ownerId, voiceId) {\n const values = { voiceId, updatedAt: new Date().toISOString() };\n db.insert(voiceChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: voiceChoices.ownerId, set: values }).run();\n },\n\n async listMemoryNotes(ownerId) {\n return db.transaction((tx) => visibleNotes(tx, ownerId));\n },\n\n // Пакет вставляется одной транзакцией: негодная запись (NOT NULL) откатывает и остальные.\n async insertMemoryNotes(ownerId, inputs) {\n return db.transaction((tx) => insertNotes(tx, ownerId, inputs), { behavior: \"immediate\" });\n },\n\n async insertMemoryNotesChecked(ownerId, inputs, guard) {\n return db.transaction(\n (tx) => {\n const error = guard(visibleNotes(tx, ownerId));\n return error ?? insertNotes(tx, ownerId, inputs);\n },\n { behavior: \"immediate\" },\n );\n },\n\n async updateMemoryNote(ownerId, id, expectedVersion, input) {\n return db.transaction((tx) => updateNote(tx, ownerId, id, expectedVersion, input), { behavior: \"immediate\" });\n },\n\n async updateMemoryNoteChecked(ownerId, id, expectedVersion, input, guard) {\n return db.transaction((tx) => guard(visibleNotes(tx, ownerId)) ?? updateNote(tx, ownerId, id, expectedVersion, input), { behavior: \"immediate\" });\n },\n\n async deleteMemoryNote(ownerId, id, expectedVersion) {\n return db.transaction((tx) => {\n const row = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (!row) return \"not_found\";\n if (row.version !== expectedVersion) return \"stale_version\";\n const result = tx.delete(memoryNotes).where(and(ownerNote(ownerId, id), eq(memoryNotes.version, expectedVersion))).run();\n if (result.changes === 0) return \"stale_version\";\n // Скрытые оригиналы слияния уходят вместе с результатом.\n tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, id))).run();\n return \"ok\";\n }, { behavior: \"immediate\" });\n },\n\n async clearMemoryNotes(ownerId) {\n return db.transaction((tx) => {\n const deleted = tx.delete(memoryNotes).where(eq(memoryNotes.ownerId, ownerId)).returning({ mergedInto: memoryNotes.mergedInto }).all();\n tx.delete(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId)).run();\n // Считаются записи, которые человек видел; скрытые оригиналы — служебные.\n return deleted.filter((row) => row.mergedInto === null).length;\n }, { behavior: \"immediate\" });\n },\n\n // Взятие запуска — одна транзакция: проверка правил и вставка не разрываются (SQLite пишет по одному).\n async claimMemoryOptimizationRun(ownerId, rules, now) {\n const nowMs = Date.parse(now);\n return db.transaction((tx) => {\n const runs = tx.select().from(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId)).all();\n for (const run of runs) {\n const leaseEnd = run.startedAt + rules.leaseMs;\n if (run.status !== \"running\" || nowMs < leaseEnd) continue;\n tx.update(memoryOptimizationRuns).set({ status: \"failed\", error: \"lease_expired\", finishedAt: leaseEnd }).where(eq(memoryOptimizationRuns.id, run.id)).run();\n Object.assign(run, { status: \"failed\", finishedAt: leaseEnd });\n }\n const blocked = isOptimizationBlocked(\n runs.map((run) => ({ status: run.status, startedAtMs: run.startedAt, endedAtMs: run.finishedAt })),\n rules,\n nowMs,\n );\n if (blocked) return null;\n const row = { id: crypto.randomUUID(), ownerId, startedAt: nowMs, finishedAt: null, status: \"running\" as const, groups: [], error: null, usageRecordId: null };\n tx.insert(memoryOptimizationRuns).values(row).run();\n return toOptimizationRun(row);\n }, { behavior: \"immediate\" });\n },\n\n async finishMemoryOptimizationRun(ownerId, runId, outcome) {\n const result = db\n .update(memoryOptimizationRuns)\n .set({ status: outcome.status, finishedAt: Date.parse(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 .run();\n return result.changes > 0 ? \"ok\" : \"not_found\";\n },\n\n // Слияние — одна транзакция: любая неудача (в том числе негодный результат) откатывает всё.\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 { originals } of merges) {\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 return db.transaction((tx) => {\n const run = tx.select().from(memoryOptimizationRuns).where(and(eq(memoryOptimizationRuns.id, merge.runId), eq(memoryOptimizationRuns.ownerId, ownerId))).get();\n if (run?.status !== \"running\") return \"run_not_active\";\n // Сначала проверка всех оригиналов, потом запись: откат в транзакции только по исключению.\n for (const { originals } of merges) {\n for (const { id, version } of originals) {\n const original = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (original?.version !== version) return \"stale_version\";\n }\n }\n const now = Date.now();\n const groups: MemoryMergeGroup[] = merges.map(({ result, originals }) => {\n const created = { id: crypto.randomUUID(), ownerId, categories: result.categories, content: result.content, version: 1, createdAt: now, updatedAt: now };\n tx.insert(memoryNotes).values(created).run();\n for (const { id } of originals) tx.update(memoryNotes).set({ mergedInto: created.id }).where(ownerNote(ownerId, id)).run();\n return { resultId: created.id, originalIds: originals.map(({ id }) => id), resultVersion: 1 };\n });\n const finished = { status: \"applied\" as const, finishedAt: Date.parse(merge.finishedAt), groups, usageRecordId: merge.usageRecordId ?? null };\n tx.update(memoryOptimizationRuns).set(finished).where(eq(memoryOptimizationRuns.id, run.id)).run();\n return toOptimizationRun({ ...run, ...finished });\n }, { behavior: \"immediate\" });\n },\n\n async revertMemoryMerge(ownerId, runId, guard) {\n return db.transaction((tx) => {\n const run = tx.select().from(memoryOptimizationRuns).where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId))).get();\n if (run?.status !== \"applied\") return \"not_found\";\n for (const { resultId, originalIds, resultVersion } of run.groups) {\n const result = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, resultId)).get();\n if (result?.version !== resultVersion) return \"conflict\";\n const hidden = 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 .all();\n if (hidden.length !== originalIds.length) return \"conflict\";\n }\n if (guard) {\n const resultIds = run.groups.map(({ resultId }) => resultId);\n const remaining = visibleNotes(tx, ownerId).filter((note) => !resultIds.includes(note.id));\n const restored = 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), desc(memoryNotes.id))\n .all()\n .map(toMemoryNote);\n const error = guard(remaining, restored);\n if (error) return revertRefusal(error);\n }\n for (const { resultId } of run.groups) {\n tx.update(memoryNotes).set({ mergedInto: null }).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId))).run();\n tx.delete(memoryNotes).where(ownerNote(ownerId, resultId)).run();\n }\n tx.update(memoryOptimizationRuns).set({ status: \"reverted\" }).where(eq(memoryOptimizationRuns.id, run.id)).run();\n return \"ok\";\n }, { behavior: \"immediate\" });\n },\n\n async listMemoryOptimizationRuns(ownerId, filter) {\n const rows = 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`rowid desc`)\n .limit(filter?.limit ?? -1)\n .all();\n return rows.map(toOptimizationRun);\n },\n\n async listMergedMemoryNotes(ownerId) {\n const rows = db\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNotNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), desc(memoryNotes.id))\n .all();\n return rows.map((row): MergedMemoryNote => ({ ...toMemoryNote(row), mergedInto: row.mergedInto! }));\n },\n\n close() {\n sqlite.close();\n },\n };\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/**\n * Фильтр `listChats` по данным чата: на каждый ключ — проверка через `json_each`: ключ как есть (точки и кавычки не\n * путаются с путём), тип значения важен (`true` не равно `1`, `\"1\"` не равно `1`).\n */\nfunction dataConditions(filter: ChatDataFilter | undefined) {\n return Object.entries(filter ?? {}).map(([key, value]) => {\n const typed =\n value === null\n ? sql`type = 'null'`\n : typeof value === \"string\"\n ? sql`type = 'text' and value = ${value}`\n : typeof value === \"boolean\"\n ? sql`type = ${value ? \"true\" : \"false\"}`\n : sql`type in ('integer', 'real') and value = ${value}`;\n return sql`exists (select 1 from json_each(${chats.subjectData}) where key = ${key} and ${typed})`;\n });\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/** Видимая запись памяти этого человека: чужая по тому же id и скрытый оригинал слияния не находятся. */\nfunction ownerNote(ownerId: string, id: string) {\n return and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), isNull(memoryNotes.mergedInto));\n}\n\n/** Строка запуска в запись ядра: владельца наружу не отдаём, время — в ISO 8601. */\nfunction toOptimizationRun(row: typeof memoryOptimizationRuns.$inferSelect): MemoryOptimizationRun {\n return {\n id: row.id,\n startedAt: new Date(row.startedAt).toISOString(),\n finishedAt: row.finishedAt === null ? null : new Date(row.finishedAt).toISOString(),\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/** Строка памяти в запись ядра: владельца наружу не отдаём, время — в 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: new Date(row.createdAt).toISOString(),\n updatedAt: new Date(row.updatedAt).toISOString(),\n };\n}\n\n/** Нарушен уникальный индекс (владелец, ключ объекта). */\nfunction isSubjectConflict(error: unknown): boolean {\n const { code, message, cause } = (error ?? {}) as { code?: unknown; message?: unknown; cause?: { code?: unknown; message?: unknown } };\n return (\n [code, cause?.code].includes(\"SQLITE_CONSTRAINT_UNIQUE\") &&\n [message, cause?.message].some((text) => typeof text === \"string\" && text.includes(\"chats.subject_key\"))\n );\n}\n\nfunction isPrimaryKeyConflict(error: unknown): boolean {\n const { code, cause } = (error ?? {}) as { code?: unknown; cause?: { code?: unknown } };\n return [code, cause?.code].includes(\"SQLITE_CONSTRAINT_PRIMARYKEY\");\n}\n","import type {\n AnswerStatus,\n ChatClosure,\n ChatErrorKind,\n MemoryMergeGroup,\n MemoryOptimizationStatus,\n StoredMessage,\n TokenUsage,\n UsageSource,\n VoiceCut,\n} from \"@ykurilov/agent-chat-core\";\nimport { sql } from \"drizzle-orm\";\nimport { index, integer, real, sqliteTable, text, uniqueIndex } from \"drizzle-orm/sqlite-core\";\n\nexport const chats = sqliteTable(\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 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: text(\"subject_data\", { mode: \"json\" }).$type<Record<string, unknown>>(),\n /** Закрытие чата (JSON `{ code, message }`); пусто — чат открыт. */\n closed: text(\"closed\", { mode: \"json\" }).$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\nexport const messages = sqliteTable(\n \"messages\",\n {\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: text(\"parts\", { mode: \"json\" }).$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: text(\"usage\", { mode: \"json\" }).$type<TokenUsage>(),\n reasoningDurationsMs: text(\"reasoning_durations_ms\", { mode: \"json\" }).$type<Record<string, number>>().notNull(),\n error: text(\"error\", { mode: \"json\" }).$type<{ kind: ChatErrorKind }>(),\n /** Отметка обрыва озвучки (голосовой режим); пусто — озвучку не обрывали. */\n voiceCut: text(\"voice_cut\", { mode: \"json\" }).$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 /** Порядок записи: при равном `created_at` сообщения читаются по возрастанию `seq`. Задаётся при вставке. */\n seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"messages_chat_created_idx\").on(table.chatId, table.createdAt, table.seq),\n uniqueIndex(\"messages_seq_idx\").on(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 = sqliteTable(\n \"compactions\",\n {\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: text(\"usage\", { mode: \"json\" }).$type<TokenUsage>(),\n createdAt: text(\"created_at\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"compactions_chat_seq_idx\").on(table.chatId, table.seq),\n uniqueIndex(\"compactions_seq_idx\").on(table.seq),\n ],\n);\n\n/** Отметки выбора ветки: только добавляются. Порядок добавления — `seq`. */\nexport const branchSelections = sqliteTable(\n \"branch_selections\",\n {\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 seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"branch_selections_chat_seq_idx\").on(table.chatId, table.seq),\n uniqueIndex(\"branch_selections_seq_idx\").on(table.seq),\n ],\n);\n\n/**\n * Журнал расхода токенов: только добавляется и не связан с чатами внешним ключом, чтобы переживать их удаление.\n * Месячный расход человека от удаления переписки не убывает.\n */\nexport const usageRecords = sqliteTable(\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: integer(\"input_tokens\").notNull(),\n cachedInputTokens: integer(\"cached_input_tokens\").notNull(),\n cacheWriteTokens: integer(\"cache_write_tokens\").notNull(),\n outputTokens: integer(\"output_tokens\").notNull(),\n reasoningTokens: integer(\"reasoning_tokens\").notNull(),\n costUsd: real(\"cost_usd\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n /** Числа «примерно»: прикинуты по длине текста, а не сообщены провайдером. */\n estimated: integer(\"estimated\", { mode: \"boolean\" }).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 = sqliteTable(\"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 = sqliteTable(\"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 = sqliteTable(\"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 = sqliteTable(\"chat_turn_leases\", {\n chatId: text(\"chat_id\").primaryKey(),\n holder: text(\"holder\").notNull(),\n until: integer(\"until\").notNull(),\n});\n\n/**\n * Долгая память: записи человека. С чатами внешним ключом не связаны — удаление чата память не трогает.\n * Время в миллисекундах; `categories` — JSON-список из 1–3 разделов.\n */\nexport const memoryNotes = sqliteTable(\n \"memory_notes\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n categories: text(\"categories\", { mode: \"json\" }).$type<string[]>().notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n createdAt: integer(\"created_at\").notNull(),\n updatedAt: integer(\"updated_at\").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` — JSON-список склеек\n * (результат, оригиналы, версия результата на момент слияния). Запуск `running` у человека не больше одного.\n */\nexport const memoryOptimizationRuns = sqliteTable(\n \"memory_optimization_runs\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n startedAt: integer(\"started_at\").notNull(),\n finishedAt: integer(\"finished_at\"),\n status: text(\"status\").$type<MemoryOptimizationStatus>().notNull(),\n groups: text(\"groups\", { mode: \"json\" }).$type<MemoryMergeGroup[]>().notNull().default(sql`'[]'`),\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"],"mappings":"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","names":["sql","sql","options","text"]}
1
+ {"version":3,"sources":["../src/sqlite-storage.ts","../src/schema.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport {\n aliveAtByLocalClock,\n assertChatDataFilter,\n assertKnownFormatVersion,\n ChatAlreadyExistsError,\n chatDataFields,\n chatDataOfInput,\n DuplicateChatSubjectError,\n DuplicateMessageError,\n isOptimizationBlocked,\n mergeChatData,\n MessageAlreadyFinishedError,\n MessageNotAwaitingError,\n revertRefusal,\n sameMessageParts,\n silenceBoundaryByLocalClock,\n} from \"@ykurilov/agent-chat-core\";\nimport type { AnswerAliveMark, Chat, ChatDataFilter, ChatListOptions, ChatStorage, ChatSubjectFilter, MemoryMergeGroup, MemoryNote, MemoryNoteInput, MemoryOptimizationRun, MergedMemoryNote, StoredMessage } from \"@ykurilov/agent-chat-core\";\nimport Database from \"better-sqlite3\";\nimport { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, ne, sql } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { readMigrationFiles } from \"drizzle-orm/migrator\";\nimport { branchSelections, chats, chatTurnLeases, compactions, memoryNotes, memoryOptimizationRuns, messages, pendingBursts, spendingLimitStates, usageRecords, userModelChoices, voiceChoices } from \"./schema\";\n\nexport interface SqliteChatStorage extends ChatStorage {\n /** Закрывает файл базы. */\n close(): void;\n}\n\nconst migrationsFolder = fileURLToPath(new URL(\"../drizzle\", import.meta.url));\n/** Свой журнал миграций SDK: общий журнал drizzle в файле может вести и приложение. */\nconst MIGRATIONS_TABLE = \"__agent_chat_migrations\";\n/** Общий журнал drizzle: в нём SDK вёл свои миграции до 0.32. */\nconst SHARED_MIGRATIONS_TABLE = \"__drizzle_migrations\";\n\n/** В файле таблицы `chats` или `messages` создал не SDK: открывать такой файл нельзя, миграции испортили бы чужие данные. */\nexport class ForeignChatTablesError extends Error {\n constructor(\n readonly filePath: string,\n readonly tables: readonly string[],\n ) {\n super(\n `В файле ${filePath} чужие таблицы ${tables.join(\" и \")}: их создало не SDK чата. ` +\n `Дайте SDK отдельный файл (например, data/chat.sqlite): общий файл с таблицами приложения не поддерживается. Файл не тронут.`,\n );\n this.name = \"ForeignChatTablesError\";\n }\n}\n\n/**\n * Таблицы SDK узнаются по журналу миграций: в нём есть запись первой миграции SDK. Нет `chats`/`messages` — файл\n * пустой или со своими другими таблицами приложения, SDK создаст свои рядом. Есть, а записи нет — таблицы чужие.\n */\nfunction assertNoForeignChatTables(sqlite: Database.Database, filePath: string): void {\n const names = tableNames(sqlite);\n const found = [\"chats\", \"messages\"].filter((name) => names.has(name));\n if (found.length === 0) return;\n const firstMigrationHash = readMigrationFiles({ migrationsFolder })[0]?.hash;\n const ours = [MIGRATIONS_TABLE, SHARED_MIGRATIONS_TABLE].some((table) => {\n try {\n return names.has(table) && sqlite.prepare(`select 1 from \"${table}\" where hash = ?`).get(firstMigrationHash) !== undefined;\n } catch {\n // У журнала приложения другие колонки: он не наш.\n return false;\n }\n });\n if (!ours) throw new ForeignChatTablesError(filePath, found);\n}\n\nfunction tableNames(sqlite: Database.Database): Set<string> {\n return new Set(sqlite.prepare(\"select name from sqlite_master where type = 'table'\").pluck().all() as string[]);\n}\n\n/**\n * До 0.32 SDK вёл миграции в общем журнале drizzle. drizzle смотрит только на время последней записи: запись приложения\n * новее миграций SDK заставляла их пропускать. Записи SDK (узнаются по хешу или времени своих миграций) один раз\n * копируются в свой журнал; общий журнал не меняется. Под замком записи: две копии сервера не перенесут дважды.\n */\nfunction moveSharedMigrationJournal(sqlite: Database.Database): void {\n sqlite\n .transaction(() => {\n const names = tableNames(sqlite);\n if (names.has(MIGRATIONS_TABLE) || !names.has(SHARED_MIGRATIONS_TABLE)) return;\n let rows: Array<{ hash: string; created_at: number }>;\n try {\n rows = sqlite.prepare(`select hash, created_at from \"${SHARED_MIGRATIONS_TABLE}\"`).all() as typeof rows;\n } catch {\n // У журнала приложения другие колонки: записей SDK в нём нет.\n return;\n }\n const sdk = readMigrationFiles({ migrationsFolder });\n const ours = rows.filter((row) => sdk.some((migration) => migration.hash === row.hash || migration.folderMillis === Number(row.created_at)));\n if (ours.length === 0) return;\n // Та же таблица, что создаёт drizzle для журнала.\n sqlite.exec(`create table \"${MIGRATIONS_TABLE}\" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)`);\n const insert = sqlite.prepare(`insert into \"${MIGRATIONS_TABLE}\" (hash, created_at) values (?, ?)`);\n for (const row of ours) insert.run(row.hash, row.created_at);\n })\n .immediate();\n}\n\n/**\n * Применяет миграции SDK, которых нет в своём журнале. Применённой считается миграция, чей хеш или время есть в журнале\n * (drizzle пишет время миграции из `_journal.json`). drizzle сверяет только последнюю запись, поэтому дыру в середине,\n * оставленную общим журналом до 0.32, не видит; здесь она закрывается. Такие миграции идут не по порядку, и это безопасно:\n * пропасть могли только миграции до 0.32, а они лишь добавляют таблицы, столбцы и индексы (это проверяет тест).\n * Журнал тот же, что у drizzle. Всё — одной транзакцией под замком записи: две копии сервера не применят миграцию дважды.\n */\nfunction applyMigrations(sqlite: Database.Database): void {\n const migrations = readMigrationFiles({ migrationsFolder });\n sqlite\n .transaction(() => {\n sqlite.exec(`create table if not exists \"${MIGRATIONS_TABLE}\" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)`);\n const rows = sqlite.prepare(`select hash, created_at from \"${MIGRATIONS_TABLE}\"`).all() as Array<{ hash: string; created_at: number }>;\n const hashes = new Set(rows.map((row) => row.hash));\n const times = new Set(rows.map((row) => Number(row.created_at)));\n const record = sqlite.prepare(`insert into \"${MIGRATIONS_TABLE}\" (hash, created_at) values (?, ?)`);\n for (const migration of migrations) {\n if (hashes.has(migration.hash) || times.has(migration.folderMillis)) continue;\n for (const statement of migration.sql) if (statement.trim()) sqlite.exec(statement);\n record.run(migration.hash, migration.folderMillis);\n }\n })\n .immediate();\n}\n\n/** Хранилище в файле SQLite. Схема приводится к последней миграции при открытии. */\nexport function createSqliteChatStorage(options: { filePath: string }): SqliteChatStorage {\n const sqlite = new Database(options.filePath);\n try {\n assertNoForeignChatTables(sqlite, options.filePath);\n moveSharedMigrationJournal(sqlite);\n } catch (error) {\n sqlite.close();\n throw error;\n }\n sqlite.pragma(\"journal_mode = WAL\");\n sqlite.pragma(\"foreign_keys = ON\");\n const db = drizzle(sqlite, { schema: { chats, messages, compactions, branchSelections, usageRecords, userModelChoices, voiceChoices, spendingLimitStates, memoryNotes, memoryOptimizationRuns } });\n applyMigrations(sqlite);\n\n // Транзакции, которые пишут, — «immediate»: запись базы берётся сразу. Иначе чтение и запись разрывались бы, и вторая\n // копия сервера на том же файле роняла бы запись ошибкой «database is locked» вместо ожидания очереди.\n type Transaction = Parameters<Parameters<typeof db.transaction>[0]>[0];\n\n function visibleNotes(tx: Transaction, ownerId: string): MemoryNote[] {\n return tx\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), desc(memoryNotes.id))\n .all()\n .map(toMemoryNote);\n }\n\n function insertNotes(tx: Transaction, ownerId: string, inputs: MemoryNoteInput[]): MemoryNote[] {\n const now = Date.now();\n const rows = inputs.map(({ categories, content }): typeof memoryNotes.$inferInsert => ({\n id: crypto.randomUUID(),\n ownerId,\n categories,\n content,\n version: 1,\n createdAt: now,\n updatedAt: now,\n }));\n for (const row of rows) tx.insert(memoryNotes).values(row).run();\n return rows.map((row) => toMemoryNote(row as typeof memoryNotes.$inferSelect));\n }\n\n function updateNote(tx: Transaction, ownerId: string, id: string, expectedVersion: number, input: MemoryNoteInput): MemoryNote | \"not_found\" | \"stale_version\" {\n const row = tx.select().from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (!row) return \"not_found\";\n if (row.version !== expectedVersion) return \"stale_version\";\n const updated = tx\n .update(memoryNotes)\n .set({\n categories: input.categories,\n content: input.content,\n version: row.version + 1,\n // Часы не отстают от записи: время правки не убывает.\n updatedAt: Math.max(Date.now(), row.updatedAt),\n })\n .where(and(ownerNote(ownerId, id), eq(memoryNotes.version, expectedVersion)))\n .returning()\n .get();\n return updated ? toMemoryNote(updated) : \"stale_version\";\n }\n\n /** Знак жизни в колонку `alive_at`: SQLite живёт на одной машине с сервером, время — по её часам. */\n const aliveAtColumn = (alive: AnswerAliveMark | undefined) => (alive ? { aliveAt: aliveAtByLocalClock(alive) } : {});\n\n /** Пишет в идущий ответ; отличает «нет такого» от «уже в конечном состоянии». */\n function updateStreaming(messageId: string, { alive, ...values }: Partial<typeof messages.$inferInsert> & { alive?: AnswerAliveMark }): void {\n const result = db\n .update(messages)\n .set({ ...values, ...aliveAtColumn(alive) })\n .where(and(eq(messages.id, messageId), eq(messages.status, \"streaming\")))\n .run();\n if (result.changes > 0) return;\n const existing = db.select({ id: messages.id }).from(messages).where(eq(messages.id, messageId)).get();\n if (!existing) throw new Error(`Сообщения ${messageId} нет`);\n throw new MessageAlreadyFinishedError(messageId);\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 db.insert(chats).values(row).run();\n } catch (error) {\n if (isSubjectConflict(error)) 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 = db.select().from(chats).where(and(eq(chats.ownerId, ownerId), eq(chats.subjectKey, subjectKey))).get();\n return row ? toChat(row) : null;\n },\n\n async importChat(chat, imported) {\n db.transaction((tx) => {\n try {\n tx.insert(chats).values(chatRow(chat)).run();\n } catch (error) {\n if (isSubjectConflict(error)) throw new DuplicateChatSubjectError(chat.ownerId, chat.subjectKey!);\n if (isPrimaryKeyConflict(error)) throw new ChatAlreadyExistsError(chat.id);\n throw error;\n }\n for (const message of imported) {\n const nextSeq = sql<number>`(select coalesce(max(${messages.seq}), 0) + 1 from ${messages})`;\n const { alive: _alive, ...stored } = message;\n try {\n tx.insert(messages).values({ ...stored, seq: nextSeq }).run();\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n }\n }, { behavior: \"immediate\" });\n },\n\n async setAfterTurnState(messageId, state, options) {\n // Чтение, проверка состояния и запись — одна транзакция с блокировкой записи: другая копия не вклинится.\n return db.transaction(\n (tx) => {\n const existing = tx.select({ parts: messages.parts, afterTurn: messages.afterTurn }).from(messages).where(eq(messages.id, messageId)).get();\n if (!existing || (state !== \"pending\" && existing.afterTurn !== \"pending\")) return false;\n tx.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 .run();\n return true;\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listPendingAfterTurn(filter) {\n return db\n .select({ id: messages.id })\n .from(messages)\n .where(\n filter?.pendingForMs === undefined\n ? eq(messages.afterTurn, \"pending\")\n : and(\n eq(messages.afterTurn, \"pending\"),\n sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${silenceBoundaryByLocalClock(filter.pendingForMs)}`,\n ),\n )\n .all()\n .map((row) => row.id);\n },\n\n async getChat(chatId) {\n const row = db.select().from(chats).where(eq(chats.id, chatId)).get();\n return row ? toChat(row) : null;\n },\n\n async updateChatModel(chatId, model) {\n db.update(chats)\n .set({ modelId: model.modelId, providerId: model.providerId, reasoning: model.reasoning ?? null })\n .where(eq(chats.id, chatId))\n .run();\n },\n\n async updateChatData(chatId, patch, { maxBytes }) {\n // Чтение, слияние и запись — одна транзакция с блокировкой на запись: параллельные правки не затирают друг друга.\n return db.transaction(\n (tx) => {\n const row = tx.select().from(chats).where(eq(chats.id, chatId)).get();\n if (!row) return null;\n const merged = mergeChatData(row.subjectData ?? undefined, patch, maxBytes);\n tx.update(chats).set({ subjectData: merged ?? null }).where(eq(chats.id, chatId)).run();\n return toChat({ ...row, subjectData: merged ?? null });\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listChats(ownerId, options?: ChatListOptions) {\n if (options?.data) assertChatDataFilter(options.data);\n const rows = db\n .select()\n .from(chats)\n .where(and(eq(chats.ownerId, ownerId), subjectCondition(options?.subjects), ...dataConditions(options?.data)))\n .orderBy(desc(chats.updatedAt), desc(chats.createdAt), desc(chats.id))\n .all();\n return rows.map(toChat);\n },\n\n async renameChat(chatId, title) {\n db.update(chats).set({ title }).where(eq(chats.id, chatId)).run();\n },\n\n async setChatClosed(chatId, closed) {\n db.update(chats).set({ closed: closed && { code: closed.code, message: closed.message } }).where(eq(chats.id, chatId)).run();\n },\n\n async deleteChat(chatId) {\n db.transaction((tx) => {\n tx.delete(compactions).where(eq(compactions.chatId, chatId)).run();\n tx.delete(branchSelections).where(eq(branchSelections.chatId, chatId)).run();\n tx.delete(messages).where(eq(messages.chatId, chatId)).run();\n tx.delete(chats).where(eq(chats.id, chatId)).run();\n tx.delete(chatTurnLeases).where(eq(chatTurnLeases.chatId, chatId)).run();\n tx.delete(pendingBursts).where(eq(pendingBursts.chatId, chatId)).run();\n }, { behavior: \"immediate\" });\n },\n\n async claimChatTurn(chatId, holder, leaseMs) {\n const now = Date.now();\n // Одной записью: свободный чат — вставка; своя или просроченная чужая — замена; живая чужая — ничего.\n const claimed = db\n .insert(chatTurnLeases)\n .values({ chatId, holder, until: now + leaseMs })\n .onConflictDoUpdate({\n target: chatTurnLeases.chatId,\n set: { holder, until: now + leaseMs },\n setWhere: sql`${chatTurnLeases.holder} = ${holder} or ${chatTurnLeases.until} <= ${now}`,\n })\n .returning({ chatId: chatTurnLeases.chatId })\n .all();\n return claimed.length > 0;\n },\n\n async releaseChatTurn(chatId, holder) {\n db.delete(chatTurnLeases).where(and(eq(chatTurnLeases.chatId, chatId), eq(chatTurnLeases.holder, holder))).run();\n },\n\n async clearChatTurnLeases() {\n db.delete(chatTurnLeases).run();\n },\n\n async savePendingBurst(burst) {\n const row = {\n chatId: burst.chatId,\n ownerId: burst.ownerId,\n messageId: burst.messageId,\n dueAt: Date.parse(burst.dueAt),\n holder: burst.holder,\n heldUntil: Date.parse(burst.heldUntil),\n page: burst.page ?? null,\n };\n db.insert(pendingBursts).values(row).onConflictDoUpdate({ target: pendingBursts.chatId, set: row }).run();\n },\n\n async takeAbandonedBursts({ abandonedBefore, holder, heldUntil, limit, exceptHolder }) {\n // Выбор и захват — одной записью: другая копия на той же базе ждёт замка и видит пачку уже взятой.\n return db.transaction((tx) => {\n const abandoned = tx\n .select()\n .from(pendingBursts)\n .where(and(lte(pendingBursts.heldUntil, Date.parse(abandonedBefore)), exceptHolder === undefined ? undefined : ne(pendingBursts.holder, exceptHolder)))\n .orderBy(asc(pendingBursts.dueAt))\n .limit(limit)\n .all();\n const until = Date.parse(heldUntil);\n for (const row of abandoned) tx.update(pendingBursts).set({ holder, heldUntil: until }).where(eq(pendingBursts.chatId, row.chatId)).run();\n return abandoned.map((row) => ({\n chatId: row.chatId,\n ownerId: row.ownerId,\n messageId: row.messageId,\n dueAt: new Date(row.dueAt).toISOString(),\n holder,\n heldUntil,\n ...(row.page && { page: row.page }),\n }));\n }, { behavior: \"immediate\" });\n },\n\n async renewPendingBurst({ chatId, messageId, holder, heldUntil }) {\n const renewed = db\n .update(pendingBursts)\n .set({ heldUntil: Date.parse(heldUntil) })\n .where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId), eq(pendingBursts.holder, holder)))\n .run();\n return renewed.changes > 0;\n },\n\n async removePendingBurst(chatId, messageId) {\n db.delete(pendingBursts).where(and(eq(pendingBursts.chatId, chatId), eq(pendingBursts.messageId, messageId))).run();\n },\n\n async getMessage(messageId) {\n const row = db.select().from(messages).where(eq(messages.id, messageId)).get();\n if (!row) return null;\n const message = toMessage(row);\n assertKnownFormatVersion(message);\n return message;\n },\n\n // При равном времени порядок записи задаёт `seq`: `rowid` VACUUM вправе перенумеровать.\n async listMessages(chatId) {\n const rows = db\n .select()\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), messages.seq)\n .all();\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), messages.seq)\n .all();\n },\n\n // Части нужных типов выбираются внутри базы: тексты и выводы инструментов в процесс не идут.\n async listMessagePartsOfTypes(chatId, types) {\n const wanted = JSON.stringify([...types]);\n const rows = db\n .select({\n id: messages.id,\n parentId: messages.parentId,\n createdAt: messages.createdAt,\n parts: sql<string>`(select coalesce(json_group_array(json(picked.value)), '[]') from (select part.value from json_each(${messages.parts}) as part where json_extract(part.value, '$.type') in (select value from json_each(${wanted})) order by part.key) as picked)`,\n })\n .from(messages)\n .where(eq(messages.chatId, chatId))\n .orderBy(asc(messages.createdAt), messages.seq)\n .all();\n return rows.map((row) => ({ ...row, parts: JSON.parse(row.parts) as StoredMessage[\"parts\"] }));\n },\n\n async insertMessage(message) {\n try {\n db.transaction((tx) => {\n const nextSeq = sql<number>`(select coalesce(max(${messages.seq}), 0) + 1 from ${messages})`;\n const { alive, ...stored } = message;\n tx.insert(messages).values({ ...stored, ...aliveAtColumn(alive), seq: nextSeq }).run();\n tx.update(chats).set({ updatedAt: message.createdAt }).where(eq(chats.id, message.chatId)).run();\n }, { behavior: \"immediate\" });\n } catch (error) {\n if (isPrimaryKeyConflict(error)) throw new DuplicateMessageError(message.id);\n throw error;\n }\n },\n\n updateStreamingMessage: async (messageId, patch) => updateStreaming(messageId, patch),\n\n markAnswerAlive: async (messageId) => updateStreaming(messageId, { alive: \"now\" }),\n\n finishMessage: async (messageId, final) => updateStreaming(messageId, { ...final, ...(final.afterTurn === \"pending\" && { alive: \"now\" as const }) }),\n\n async updateAwaitingMessage(messageId, patch) {\n // Чтение, сравнение частей и запись — одна транзакция с блокировкой записи: другая копия не вклинится между ними.\n db.transaction(\n (tx) => {\n const existing = tx.select({ status: messages.status, parts: messages.parts }).from(messages).where(eq(messages.id, messageId)).get();\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 tx.update(messages)\n .set({ parts: patch.parts, ...(patch.status && { status: patch.status }), ...aliveAtColumn(patch.alive) })\n .where(eq(messages.id, messageId))\n .run();\n },\n { behavior: \"immediate\" },\n );\n },\n\n async listStreamingMessageIds() {\n return db\n .select({ id: messages.id })\n .from(messages)\n .where(eq(messages.status, \"streaming\"))\n .all()\n .map((row) => row.id);\n },\n\n async listSilentAnswerIds({ silentForMs, chatId }) {\n const silent = sql`coalesce(${messages.aliveAt}, ${messages.createdAt}) < ${silenceBoundaryByLocalClock(silentForMs)}`;\n return 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 .all()\n .map((row) => row.id);\n },\n\n async insertCompaction(record) {\n const nextSeq = sql<number>`(select coalesce(max(${compactions.seq}), 0) + 1 from ${compactions})`;\n db.insert(compactions).values({ ...record, seq: nextSeq }).run();\n },\n\n async listCompactions(chatId) {\n const rows = db.select().from(compactions).where(eq(compactions.chatId, chatId)).orderBy(asc(compactions.seq)).all();\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertBranchSelection(record) {\n const nextSeq = sql<number>`(select coalesce(max(${branchSelections.seq}), 0) + 1 from ${branchSelections})`;\n db.insert(branchSelections).values({ ...record, seq: nextSeq }).run();\n },\n\n async listBranchSelections(chatId) {\n const rows = db.select().from(branchSelections).where(eq(branchSelections.chatId, chatId)).orderBy(asc(branchSelections.seq)).all();\n return rows.map(({ seq: _seq, ...record }) => record);\n },\n\n async insertUsageRecord(record) {\n db.insert(usageRecords).values(record).run();\n },\n\n async hasUsageRecord(id) {\n return db.select({ id: usageRecords.id }).from(usageRecords).where(eq(usageRecords.id, id)).get() !== undefined;\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 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 .all();\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 .all();\n },\n\n async getUserModelChoice(ownerId) {\n const row = db.select().from(userModelChoices).where(eq(userModelChoices.ownerId, ownerId)).get();\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 db.insert(userModelChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: userModelChoices.ownerId, set: values }).run();\n },\n\n async setVoiceCut({ ownerId, chatId, messageId, voiceCut }) {\n db.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 .run();\n },\n\n async getSpendingLimitState(key) {\n const row = db.select().from(spendingLimitStates).where(eq(spendingLimitStates.key, key)).get();\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 return db.insert(spendingLimitStates).values({ key, value, version: 1, updatedAt }).onConflictDoNothing().run().changes === 1;\n }\n const changed = db\n .update(spendingLimitStates)\n .set({ value, version: expectedVersion + 1, updatedAt })\n .where(and(eq(spendingLimitStates.key, key), eq(spendingLimitStates.version, expectedVersion)))\n .run().changes;\n return changed === 1;\n },\n\n async deleteSpendingLimitStates(keys) {\n if (keys.length > 0) db.delete(spendingLimitStates).where(inArray(spendingLimitStates.key, keys)).run();\n },\n\n async getVoiceChoice(ownerId) {\n return db.select().from(voiceChoices).where(eq(voiceChoices.ownerId, ownerId)).get()?.voiceId ?? null;\n },\n\n async setVoiceChoice(ownerId, voiceId) {\n const values = { voiceId, updatedAt: new Date().toISOString() };\n db.insert(voiceChoices).values({ ownerId, ...values }).onConflictDoUpdate({ target: voiceChoices.ownerId, set: values }).run();\n },\n\n async listMemoryNotes(ownerId) {\n return db.transaction((tx) => visibleNotes(tx, ownerId));\n },\n\n // Пакет вставляется одной транзакцией: негодная запись (NOT NULL) откатывает и остальные.\n async insertMemoryNotes(ownerId, inputs) {\n return db.transaction((tx) => insertNotes(tx, ownerId, inputs), { behavior: \"immediate\" });\n },\n\n async insertMemoryNotesChecked(ownerId, inputs, guard) {\n return db.transaction(\n (tx) => {\n const error = guard(visibleNotes(tx, ownerId));\n return error ?? insertNotes(tx, ownerId, inputs);\n },\n { behavior: \"immediate\" },\n );\n },\n\n async updateMemoryNote(ownerId, id, expectedVersion, input) {\n return db.transaction((tx) => updateNote(tx, ownerId, id, expectedVersion, input), { behavior: \"immediate\" });\n },\n\n async updateMemoryNoteChecked(ownerId, id, expectedVersion, input, guard) {\n return db.transaction((tx) => guard(visibleNotes(tx, ownerId)) ?? updateNote(tx, ownerId, id, expectedVersion, input), { behavior: \"immediate\" });\n },\n\n async deleteMemoryNote(ownerId, id, expectedVersion) {\n return db.transaction((tx) => {\n const row = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (!row) return \"not_found\";\n if (row.version !== expectedVersion) return \"stale_version\";\n const result = tx.delete(memoryNotes).where(and(ownerNote(ownerId, id), eq(memoryNotes.version, expectedVersion))).run();\n if (result.changes === 0) return \"stale_version\";\n // Скрытые оригиналы слияния уходят вместе с результатом.\n tx.delete(memoryNotes).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, id))).run();\n return \"ok\";\n }, { behavior: \"immediate\" });\n },\n\n async clearMemoryNotes(ownerId) {\n return db.transaction((tx) => {\n const deleted = tx.delete(memoryNotes).where(eq(memoryNotes.ownerId, ownerId)).returning({ mergedInto: memoryNotes.mergedInto }).all();\n tx.delete(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId)).run();\n // Считаются записи, которые человек видел; скрытые оригиналы — служебные.\n return deleted.filter((row) => row.mergedInto === null).length;\n }, { behavior: \"immediate\" });\n },\n\n // Взятие запуска — одна транзакция: проверка правил и вставка не разрываются (SQLite пишет по одному).\n async claimMemoryOptimizationRun(ownerId, rules, now) {\n const nowMs = Date.parse(now);\n return db.transaction((tx) => {\n const runs = tx.select().from(memoryOptimizationRuns).where(eq(memoryOptimizationRuns.ownerId, ownerId)).all();\n for (const run of runs) {\n const leaseEnd = run.startedAt + rules.leaseMs;\n if (run.status !== \"running\" || nowMs < leaseEnd) continue;\n tx.update(memoryOptimizationRuns).set({ status: \"failed\", error: \"lease_expired\", finishedAt: leaseEnd }).where(eq(memoryOptimizationRuns.id, run.id)).run();\n Object.assign(run, { status: \"failed\", finishedAt: leaseEnd });\n }\n const blocked = isOptimizationBlocked(\n runs.map((run) => ({ status: run.status, startedAtMs: run.startedAt, endedAtMs: run.finishedAt })),\n rules,\n nowMs,\n );\n if (blocked) return null;\n const row = { id: crypto.randomUUID(), ownerId, startedAt: nowMs, finishedAt: null, status: \"running\" as const, groups: [], error: null, usageRecordId: null };\n tx.insert(memoryOptimizationRuns).values(row).run();\n return toOptimizationRun(row);\n }, { behavior: \"immediate\" });\n },\n\n async finishMemoryOptimizationRun(ownerId, runId, outcome) {\n const result = db\n .update(memoryOptimizationRuns)\n .set({ status: outcome.status, finishedAt: Date.parse(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 .run();\n return result.changes > 0 ? \"ok\" : \"not_found\";\n },\n\n // Слияние — одна транзакция: любая неудача (в том числе негодный результат) откатывает всё.\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 { originals } of merges) {\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 return db.transaction((tx) => {\n const run = tx.select().from(memoryOptimizationRuns).where(and(eq(memoryOptimizationRuns.id, merge.runId), eq(memoryOptimizationRuns.ownerId, ownerId))).get();\n if (run?.status !== \"running\") return \"run_not_active\";\n // Сначала проверка всех оригиналов, потом запись: откат в транзакции только по исключению.\n for (const { originals } of merges) {\n for (const { id, version } of originals) {\n const original = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, id)).get();\n if (original?.version !== version) return \"stale_version\";\n }\n }\n const now = Date.now();\n const groups: MemoryMergeGroup[] = merges.map(({ result, originals }) => {\n const created = { id: crypto.randomUUID(), ownerId, categories: result.categories, content: result.content, version: 1, createdAt: now, updatedAt: now };\n tx.insert(memoryNotes).values(created).run();\n for (const { id } of originals) tx.update(memoryNotes).set({ mergedInto: created.id }).where(ownerNote(ownerId, id)).run();\n return { resultId: created.id, originalIds: originals.map(({ id }) => id), resultVersion: 1 };\n });\n const finished = { status: \"applied\" as const, finishedAt: Date.parse(merge.finishedAt), groups, usageRecordId: merge.usageRecordId ?? null };\n tx.update(memoryOptimizationRuns).set(finished).where(eq(memoryOptimizationRuns.id, run.id)).run();\n return toOptimizationRun({ ...run, ...finished });\n }, { behavior: \"immediate\" });\n },\n\n async revertMemoryMerge(ownerId, runId, guard) {\n return db.transaction((tx) => {\n const run = tx.select().from(memoryOptimizationRuns).where(and(eq(memoryOptimizationRuns.id, runId), eq(memoryOptimizationRuns.ownerId, ownerId))).get();\n if (run?.status !== \"applied\") return \"not_found\";\n for (const { resultId, originalIds, resultVersion } of run.groups) {\n const result = tx.select({ version: memoryNotes.version }).from(memoryNotes).where(ownerNote(ownerId, resultId)).get();\n if (result?.version !== resultVersion) return \"conflict\";\n const hidden = 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 .all();\n if (hidden.length !== originalIds.length) return \"conflict\";\n }\n if (guard) {\n const resultIds = run.groups.map(({ resultId }) => resultId);\n const remaining = visibleNotes(tx, ownerId).filter((note) => !resultIds.includes(note.id));\n const restored = 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), desc(memoryNotes.id))\n .all()\n .map(toMemoryNote);\n const error = guard(remaining, restored);\n if (error) return revertRefusal(error);\n }\n for (const { resultId } of run.groups) {\n tx.update(memoryNotes).set({ mergedInto: null }).where(and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.mergedInto, resultId))).run();\n tx.delete(memoryNotes).where(ownerNote(ownerId, resultId)).run();\n }\n tx.update(memoryOptimizationRuns).set({ status: \"reverted\" }).where(eq(memoryOptimizationRuns.id, run.id)).run();\n return \"ok\";\n }, { behavior: \"immediate\" });\n },\n\n async listMemoryOptimizationRuns(ownerId, filter) {\n const rows = 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`rowid desc`)\n .limit(filter?.limit ?? -1)\n .all();\n return rows.map(toOptimizationRun);\n },\n\n async listMergedMemoryNotes(ownerId) {\n const rows = db\n .select()\n .from(memoryNotes)\n .where(and(eq(memoryNotes.ownerId, ownerId), isNotNull(memoryNotes.mergedInto)))\n .orderBy(desc(memoryNotes.updatedAt), desc(memoryNotes.createdAt), desc(memoryNotes.id))\n .all();\n return rows.map((row): MergedMemoryNote => ({ ...toMemoryNote(row), mergedInto: row.mergedInto! }));\n },\n\n close() {\n sqlite.close();\n },\n };\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/**\n * Фильтр `listChats` по данным чата: на каждый ключ — проверка через `json_each`: ключ как есть (точки и кавычки не\n * путаются с путём), тип значения важен (`true` не равно `1`, `\"1\"` не равно `1`).\n */\nfunction dataConditions(filter: ChatDataFilter | undefined) {\n return Object.entries(filter ?? {}).map(([key, value]) => {\n const typed =\n value === null\n ? sql`type = 'null'`\n : typeof value === \"string\"\n ? sql`type = 'text' and value = ${value}`\n : typeof value === \"boolean\"\n ? sql`type = ${value ? \"true\" : \"false\"}`\n : sql`type in ('integer', 'real') and value = ${value}`;\n return sql`exists (select 1 from json_each(${chats.subjectData}) where key = ${key} and ${typed})`;\n });\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/** Видимая запись памяти этого человека: чужая по тому же id и скрытый оригинал слияния не находятся. */\nfunction ownerNote(ownerId: string, id: string) {\n return and(eq(memoryNotes.ownerId, ownerId), eq(memoryNotes.id, id), isNull(memoryNotes.mergedInto));\n}\n\n/** Строка запуска в запись ядра: владельца наружу не отдаём, время — в ISO 8601. */\nfunction toOptimizationRun(row: typeof memoryOptimizationRuns.$inferSelect): MemoryOptimizationRun {\n return {\n id: row.id,\n startedAt: new Date(row.startedAt).toISOString(),\n finishedAt: row.finishedAt === null ? null : new Date(row.finishedAt).toISOString(),\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/** Строка памяти в запись ядра: владельца наружу не отдаём, время — в 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: new Date(row.createdAt).toISOString(),\n updatedAt: new Date(row.updatedAt).toISOString(),\n };\n}\n\n/** Нарушен уникальный индекс (владелец, ключ объекта). */\nfunction isSubjectConflict(error: unknown): boolean {\n const { code, message, cause } = (error ?? {}) as { code?: unknown; message?: unknown; cause?: { code?: unknown; message?: unknown } };\n return (\n [code, cause?.code].includes(\"SQLITE_CONSTRAINT_UNIQUE\") &&\n [message, cause?.message].some((text) => typeof text === \"string\" && text.includes(\"chats.subject_key\"))\n );\n}\n\nfunction isPrimaryKeyConflict(error: unknown): boolean {\n const { code, cause } = (error ?? {}) as { code?: unknown; cause?: { code?: unknown } };\n return [code, cause?.code].includes(\"SQLITE_CONSTRAINT_PRIMARYKEY\");\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 { index, integer, real, sqliteTable, text, uniqueIndex } from \"drizzle-orm/sqlite-core\";\n\nexport const chats = sqliteTable(\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 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: text(\"subject_data\", { mode: \"json\" }).$type<Record<string, unknown>>(),\n /** Закрытие чата (JSON `{ code, message }`); пусто — чат открыт. */\n closed: text(\"closed\", { mode: \"json\" }).$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\nexport const messages = sqliteTable(\n \"messages\",\n {\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: text(\"parts\", { mode: \"json\" }).$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: text(\"usage\", { mode: \"json\" }).$type<TokenUsage>(),\n reasoningDurationsMs: text(\"reasoning_durations_ms\", { mode: \"json\" }).$type<Record<string, number>>().notNull(),\n error: text(\"error\", { mode: \"json\" }).$type<{ kind: ChatErrorKind }>(),\n /** Отметка обрыва озвучки (голосовой режим); пусто — озвучку не обрывали. */\n voiceCut: text(\"voice_cut\", { mode: \"json\" }).$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 /** Порядок записи: при равном `created_at` сообщения читаются по возрастанию `seq`. Задаётся при вставке. */\n seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"messages_chat_created_idx\").on(table.chatId, table.createdAt, table.seq),\n uniqueIndex(\"messages_seq_idx\").on(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 = sqliteTable(\n \"compactions\",\n {\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: text(\"usage\", { mode: \"json\" }).$type<TokenUsage>(),\n createdAt: text(\"created_at\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"compactions_chat_seq_idx\").on(table.chatId, table.seq),\n uniqueIndex(\"compactions_seq_idx\").on(table.seq),\n ],\n);\n\n/** Отметки выбора ветки: только добавляются. Порядок добавления — `seq`. */\nexport const branchSelections = sqliteTable(\n \"branch_selections\",\n {\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 seq: integer(\"seq\").notNull().default(0),\n },\n (table) => [\n index(\"branch_selections_chat_seq_idx\").on(table.chatId, table.seq),\n uniqueIndex(\"branch_selections_seq_idx\").on(table.seq),\n ],\n);\n\n/**\n * Журнал расхода токенов: только добавляется и не связан с чатами внешним ключом, чтобы переживать их удаление.\n * Месячный расход человека от удаления переписки не убывает.\n */\nexport const usageRecords = sqliteTable(\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: integer(\"input_tokens\").notNull(),\n cachedInputTokens: integer(\"cached_input_tokens\").notNull(),\n cacheWriteTokens: integer(\"cache_write_tokens\").notNull(),\n outputTokens: integer(\"output_tokens\").notNull(),\n reasoningTokens: integer(\"reasoning_tokens\").notNull(),\n costUsd: real(\"cost_usd\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n /** Числа «примерно»: прикинуты по длине текста, а не сообщены провайдером. */\n estimated: integer(\"estimated\", { mode: \"boolean\" }).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 = sqliteTable(\"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 = sqliteTable(\"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 = sqliteTable(\"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 = sqliteTable(\"chat_turn_leases\", {\n chatId: text(\"chat_id\").primaryKey(),\n holder: text(\"holder\").notNull(),\n until: integer(\"until\").notNull(),\n});\n\n/**\n * Ждущие пачки сообщений человека: одна запись на чат. Сроки — мс по часам службы; `page` — JSON страницы хода.\n * Внешним ключом с чатом не связана: удаление чата снимает её само.\n */\nexport const pendingBursts = sqliteTable(\"pending_bursts\", {\n chatId: text(\"chat_id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n messageId: text(\"message_id\").notNull(),\n dueAt: integer(\"due_at\").notNull(),\n holder: text(\"holder\").notNull(),\n heldUntil: integer(\"held_until\").notNull(),\n page: text(\"page\", { mode: \"json\" }).$type<TurnRequestContext>(),\n});\n\n/**\n * Долгая память: записи человека. С чатами внешним ключом не связаны — удаление чата память не трогает.\n * Время в миллисекундах; `categories` — JSON-список из 1–3 разделов.\n */\nexport const memoryNotes = sqliteTable(\n \"memory_notes\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n categories: text(\"categories\", { mode: \"json\" }).$type<string[]>().notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n createdAt: integer(\"created_at\").notNull(),\n updatedAt: integer(\"updated_at\").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` — JSON-список склеек\n * (результат, оригиналы, версия результата на момент слияния). Запуск `running` у человека не больше одного.\n */\nexport const memoryOptimizationRuns = sqliteTable(\n \"memory_optimization_runs\",\n {\n id: text(\"id\").primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n startedAt: integer(\"started_at\").notNull(),\n finishedAt: integer(\"finished_at\"),\n status: text(\"status\").$type<MemoryOptimizationStatus>().notNull(),\n groups: text(\"groups\", { mode: \"json\" }).$type<MemoryMergeGroup[]>().notNull().default(sql`'[]'`),\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"],"mappings":"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","names":["sql","sql","options","text"]}