@deepagents/context 7.1.2 → 7.1.4

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/dist/index.js CHANGED
@@ -3299,7 +3299,10 @@ var SavePipeline = class _SavePipeline {
3299
3299
  };
3300
3300
 
3301
3301
  // packages/context/src/lib/store/sqlite.store.ts
3302
- import { DatabaseSync } from "node:sqlite";
3302
+ import { transaction } from "@zukhruf/sqlite-transaction";
3303
+ import {
3304
+ DatabaseSync
3305
+ } from "node:sqlite";
3303
3306
  import { z as z4 } from "zod";
3304
3307
 
3305
3308
  // packages/context/src/lib/store/columns.ts
@@ -3448,92 +3451,82 @@ function toMessage(row) {
3448
3451
  createdAt: row.createdAt
3449
3452
  };
3450
3453
  }
3454
+ var SearchQuerySyntaxError = class extends Error {
3455
+ constructor(query, options) {
3456
+ super(
3457
+ `The search query ${JSON.stringify(query)} is not valid FTS5 syntax. Put a term that has characters such as - or : in double quotes: "well-known" finds the term well-known.`,
3458
+ options
3459
+ );
3460
+ this.name = "SearchQuerySyntaxError";
3461
+ }
3462
+ };
3463
+ function isFts5QueryError(error) {
3464
+ return error instanceof Error && "errcode" in error && error.errcode === 1 && /^(fts5: syntax error near |no such column: |unterminated string$|unknown special query: |expected integer, got )/.test(
3465
+ error.message
3466
+ );
3467
+ }
3451
3468
  var SqliteContextStore = class extends ContextStore {
3452
3469
  #db;
3453
- #statements = /* @__PURE__ */ new Map();
3454
- /**
3455
- * Get or create a prepared statement.
3456
- * Statements are cached for the lifetime of the store to avoid
3457
- * repeated SQL parsing and compilation overhead.
3458
- */
3459
- #stmt(sql) {
3460
- let stmt = this.#statements.get(sql);
3461
- if (!stmt) {
3462
- stmt = this.#db.prepare(sql);
3463
- this.#statements.set(sql, stmt);
3464
- }
3465
- return stmt;
3466
- }
3470
+ #sql;
3467
3471
  constructor(pathOrDb) {
3468
3472
  super();
3469
3473
  this.#db = typeof pathOrDb === "string" ? new DatabaseSync(pathOrDb) : pathOrDb;
3470
3474
  this.#db.exec(ddl_sqlite_default);
3471
- }
3472
- /**
3473
- * Execute a function within a transaction.
3474
- * Automatically commits on success or rolls back on error.
3475
- */
3476
- #useTransaction(fn, mode = "deferred") {
3477
- this.#db.exec(
3478
- mode === "immediate" ? "BEGIN IMMEDIATE" : "BEGIN TRANSACTION"
3479
- );
3480
- try {
3481
- const result = fn();
3482
- this.#db.exec("COMMIT");
3483
- return result;
3484
- } catch (error) {
3485
- try {
3486
- this.#db.exec("ROLLBACK");
3487
- } catch {
3488
- }
3489
- throw error;
3490
- }
3475
+ this.#sql = this.#db.createTagStore();
3491
3476
  }
3492
3477
  // ==========================================================================
3493
3478
  // Chat Operations
3494
3479
  // ==========================================================================
3495
3480
  async createChat(chat2) {
3496
- return this.#useTransaction(() => {
3497
- const created = storedChat.parse(
3498
- this.#db.prepare(
3499
- `INSERT INTO chats (id, userId, title, metadata)
3481
+ return transaction(
3482
+ this.#db,
3483
+ () => {
3484
+ const created = storedChat.parse(
3485
+ this.#db.prepare(
3486
+ `INSERT INTO chats (id, userId, title, metadata)
3500
3487
  VALUES (?, ?, ?, ?)
3501
3488
  RETURNING *`
3502
- ).get(
3503
- chat2.id,
3504
- chat2.userId,
3505
- chat2.title ?? null,
3506
- chat2.metadata ? JSON.stringify(chat2.metadata) : null
3507
- )
3508
- );
3509
- this.#db.prepare(
3510
- `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
3489
+ ).get(
3490
+ chat2.id,
3491
+ chat2.userId,
3492
+ chat2.title ?? null,
3493
+ chat2.metadata ? JSON.stringify(chat2.metadata) : null
3494
+ )
3495
+ );
3496
+ this.#db.prepare(
3497
+ `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
3511
3498
  VALUES (?, ?, 'main', NULL, 1, ?)`
3512
- ).run(crypto.randomUUID(), chat2.id, Date.now());
3513
- return created;
3514
- });
3499
+ ).run(crypto.randomUUID(), chat2.id, Date.now());
3500
+ return created;
3501
+ },
3502
+ { mode: "deferred" }
3503
+ );
3515
3504
  }
3516
3505
  async upsertChat(chat2) {
3517
- return this.#useTransaction(() => {
3518
- const upserted = storedChat.parse(
3519
- this.#db.prepare(
3520
- `INSERT INTO chats (id, userId, title, metadata)
3506
+ return transaction(
3507
+ this.#db,
3508
+ () => {
3509
+ const upserted = storedChat.parse(
3510
+ this.#db.prepare(
3511
+ `INSERT INTO chats (id, userId, title, metadata)
3521
3512
  VALUES (?, ?, ?, ?)
3522
3513
  ON CONFLICT(id) DO UPDATE SET id = excluded.id
3523
3514
  RETURNING *`
3524
- ).get(
3525
- chat2.id,
3526
- chat2.userId,
3527
- chat2.title ?? null,
3528
- chat2.metadata ? JSON.stringify(chat2.metadata) : null
3529
- )
3530
- );
3531
- this.#db.prepare(
3532
- `INSERT OR IGNORE INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
3515
+ ).get(
3516
+ chat2.id,
3517
+ chat2.userId,
3518
+ chat2.title ?? null,
3519
+ chat2.metadata ? JSON.stringify(chat2.metadata) : null
3520
+ )
3521
+ );
3522
+ this.#db.prepare(
3523
+ `INSERT OR IGNORE INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
3533
3524
  VALUES (?, ?, 'main', NULL, 1, ?)`
3534
- ).run(crypto.randomUUID(), chat2.id, Date.now());
3535
- return upserted;
3536
- });
3525
+ ).run(crypto.randomUUID(), chat2.id, Date.now());
3526
+ return upserted;
3527
+ },
3528
+ { mode: "deferred" }
3529
+ );
3537
3530
  }
3538
3531
  #getChat(chatId) {
3539
3532
  return storedChat.optional().parse(this.#db.prepare("SELECT * FROM chats WHERE id = ?").get(chatId));
@@ -3542,30 +3535,36 @@ var SqliteContextStore = class extends ContextStore {
3542
3535
  return this.#getChat(chatId);
3543
3536
  }
3544
3537
  async updateChat(chatId, update) {
3545
- return this.#useTransaction(() => {
3546
- const current = this.#getChat(chatId);
3547
- if (!current) {
3548
- throw new Error(`updateChat: chat "${chatId}" not found`);
3549
- }
3550
- const updates = update(current);
3551
- if (updates === void 0) return current;
3552
- const setClauses = ["updatedAt = strftime('%s', 'now') * 1000"];
3553
- const params = [];
3554
- if (updates.title !== void 0) {
3555
- setClauses.push("title = ?");
3556
- params.push(updates.title);
3557
- }
3558
- if (updates.metadata !== void 0) {
3559
- setClauses.push("metadata = ?");
3560
- params.push(JSON.stringify(updates.metadata));
3561
- }
3562
- params.push(chatId);
3563
- return storedChat.parse(
3564
- this.#db.prepare(
3565
- `UPDATE chats SET ${setClauses.join(", ")} WHERE id = ? RETURNING *`
3566
- ).get(...params)
3567
- );
3568
- }, "immediate");
3538
+ return transaction(
3539
+ this.#db,
3540
+ () => {
3541
+ const current = this.#getChat(chatId);
3542
+ if (!current) {
3543
+ throw new Error(`updateChat: chat "${chatId}" not found`);
3544
+ }
3545
+ const updates = update(current);
3546
+ if (updates === void 0) return current;
3547
+ const setClauses = [
3548
+ "updatedAt = strftime('%s', 'now') * 1000"
3549
+ ];
3550
+ const params = [];
3551
+ if (updates.title !== void 0) {
3552
+ setClauses.push("title = ?");
3553
+ params.push(updates.title);
3554
+ }
3555
+ if (updates.metadata !== void 0) {
3556
+ setClauses.push("metadata = ?");
3557
+ params.push(JSON.stringify(updates.metadata));
3558
+ }
3559
+ params.push(chatId);
3560
+ return storedChat.parse(
3561
+ this.#db.prepare(
3562
+ `UPDATE chats SET ${setClauses.join(", ")} WHERE id = ? RETURNING *`
3563
+ ).get(...params)
3564
+ );
3565
+ },
3566
+ { mode: "immediate" }
3567
+ );
3569
3568
  }
3570
3569
  async listChats(options) {
3571
3570
  const params = [];
@@ -3612,25 +3611,29 @@ var SqliteContextStore = class extends ContextStore {
3612
3611
  );
3613
3612
  }
3614
3613
  async deleteChat(chatId, options) {
3615
- return this.#useTransaction(() => {
3616
- const messageIds = z4.array(idRow).parse(
3617
- this.#db.prepare("SELECT id FROM messages WHERE chatId = ?").all(chatId)
3618
- );
3619
- let sql = "DELETE FROM chats WHERE id = ?";
3620
- const params = [chatId];
3621
- if (options?.userId !== void 0) {
3622
- sql += " AND userId = ?";
3623
- params.push(options.userId);
3624
- }
3625
- const result = this.#db.prepare(sql).run(...params);
3626
- if (result.changes > 0 && messageIds.length > 0) {
3627
- const placeholders = messageIds.map(() => "?").join(", ");
3628
- this.#db.prepare(
3629
- `DELETE FROM messages_fts WHERE messageId IN (${placeholders})`
3630
- ).run(...messageIds.map((m) => m.id));
3631
- }
3632
- return result.changes > 0;
3633
- });
3614
+ return transaction(
3615
+ this.#db,
3616
+ () => {
3617
+ const messageIds = z4.array(idRow).parse(
3618
+ this.#db.prepare("SELECT id FROM messages WHERE chatId = ?").all(chatId)
3619
+ );
3620
+ let sql = "DELETE FROM chats WHERE id = ?";
3621
+ const params = [chatId];
3622
+ if (options?.userId !== void 0) {
3623
+ sql += " AND userId = ?";
3624
+ params.push(options.userId);
3625
+ }
3626
+ const result = this.#db.prepare(sql).run(...params);
3627
+ if (result.changes > 0 && messageIds.length > 0) {
3628
+ const placeholders = messageIds.map(() => "?").join(", ");
3629
+ this.#db.prepare(
3630
+ `DELETE FROM messages_fts WHERE messageId IN (${placeholders})`
3631
+ ).run(...messageIds.map((m) => m.id));
3632
+ }
3633
+ return result.changes > 0;
3634
+ },
3635
+ { mode: "deferred" }
3636
+ );
3634
3637
  }
3635
3638
  // ==========================================================================
3636
3639
  // Message Operations (Graph Nodes)
@@ -3639,59 +3642,48 @@ var SqliteContextStore = class extends ContextStore {
3639
3642
  if (message2.parentId === message2.id) {
3640
3643
  throw new Error(`Message ${message2.id} cannot be its own parent`);
3641
3644
  }
3642
- this.#stmt(
3643
- `INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
3644
- VALUES (?, ?, ?, ?, ?, ?, ?)
3645
+ this.#sql.run`INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
3646
+ VALUES (${message2.id}, ${message2.chatId}, ${message2.parentId}, ${message2.name}, ${message2.type ?? null}, ${JSON.stringify(message2.data)}, ${message2.createdAt})
3645
3647
  ON CONFLICT(id) DO UPDATE SET
3646
3648
  name = excluded.name,
3647
3649
  type = excluded.type,
3648
- data = excluded.data`
3649
- ).run(
3650
- message2.id,
3651
- message2.chatId,
3652
- message2.parentId,
3653
- message2.name,
3654
- message2.type ?? null,
3655
- JSON.stringify(message2.data),
3656
- message2.createdAt
3657
- );
3650
+ data = excluded.data`;
3658
3651
  const content = typeof message2.data === "string" ? message2.data : JSON.stringify(message2.data);
3659
- this.#stmt(`DELETE FROM messages_fts WHERE messageId = ?`).run(message2.id);
3660
- this.#stmt(
3661
- `INSERT INTO messages_fts(messageId, chatId, name, content)
3662
- VALUES (?, ?, ?, ?)`
3663
- ).run(message2.id, message2.chatId, message2.name, content);
3652
+ this.#sql.run`DELETE FROM messages_fts WHERE messageId = ${message2.id}`;
3653
+ this.#sql.run`INSERT INTO messages_fts(messageId, chatId, name, content)
3654
+ VALUES (${message2.id}, ${message2.chatId}, ${message2.name}, ${content})`;
3664
3655
  }
3665
3656
  async addMessage(message2) {
3666
3657
  this.#insertMessage(message2);
3667
3658
  }
3668
3659
  async addMessages(messages) {
3669
3660
  if (messages.length === 0) return;
3670
- this.#useTransaction(() => {
3671
- for (const message2 of messages) {
3672
- this.#insertMessage(message2);
3673
- }
3674
- });
3661
+ transaction(
3662
+ this.#db,
3663
+ () => {
3664
+ for (const message2 of messages) {
3665
+ this.#insertMessage(message2);
3666
+ }
3667
+ },
3668
+ { mode: "deferred" }
3669
+ );
3675
3670
  }
3676
3671
  async setMessageParent(messageId, parentId) {
3677
3672
  if (parentId === messageId) {
3678
3673
  throw new Error(`Message ${messageId} cannot be its own parent`);
3679
3674
  }
3680
- const result = this.#stmt(
3681
- "UPDATE messages SET parentId = ? WHERE id = ?"
3682
- ).run(parentId, messageId);
3675
+ const result = this.#sql.run`UPDATE messages SET parentId = ${parentId} WHERE id = ${messageId}`;
3683
3676
  if (result.changes === 0) {
3684
3677
  throw new Error(`Message ${messageId} not found`);
3685
3678
  }
3686
3679
  }
3687
3680
  async getMessage(messageId) {
3688
- return storedMessage.optional().parse(this.#stmt("SELECT * FROM messages WHERE id = ?").get(messageId));
3681
+ return storedMessage.optional().parse(this.#sql.get`SELECT * FROM messages WHERE id = ${messageId}`);
3689
3682
  }
3690
3683
  async getMessageChain(headId) {
3691
3684
  return z4.array(storedMessage).parse(
3692
- this.#stmt(
3693
- `WITH RECURSIVE chain AS (
3694
- SELECT *, 0 as depth FROM messages WHERE id = ?
3685
+ this.#sql.all`WITH RECURSIVE chain AS (
3686
+ SELECT *, 0 as depth FROM messages WHERE id = ${headId}
3695
3687
  UNION ALL
3696
3688
  SELECT m.*, c.depth + 1 FROM messages m
3697
3689
  INNER JOIN chain c ON m.id = c.parentId
@@ -3699,14 +3691,11 @@ var SqliteContextStore = class extends ContextStore {
3699
3691
  )
3700
3692
  SELECT * FROM chain
3701
3693
  ORDER BY depth DESC`
3702
- ).all(headId)
3703
3694
  );
3704
3695
  }
3705
3696
  async hasChildren(messageId) {
3706
3697
  const row = hasChildrenRow.parse(
3707
- this.#stmt(
3708
- "SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = ?) as hasChildren"
3709
- ).get(messageId)
3698
+ this.#sql.get`SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = ${messageId}) as hasChildren`
3710
3699
  );
3711
3700
  return row.hasChildren === 1;
3712
3701
  }
@@ -3744,9 +3733,7 @@ var SqliteContextStore = class extends ContextStore {
3744
3733
  }
3745
3734
  async getActiveBranch(chatId) {
3746
3735
  return storedBranch.optional().parse(
3747
- this.#stmt(
3748
- "SELECT * FROM branches WHERE chatId = ? AND isActive = 1"
3749
- ).get(chatId)
3736
+ this.#sql.get`SELECT * FROM branches WHERE chatId = ${chatId} AND isActive = 1`
3750
3737
  );
3751
3738
  }
3752
3739
  async setActiveBranch(chatId, branchId) {
@@ -3754,9 +3741,7 @@ var SqliteContextStore = class extends ContextStore {
3754
3741
  this.#db.prepare("UPDATE branches SET isActive = 1 WHERE id = ?").run(branchId);
3755
3742
  }
3756
3743
  async updateBranchHead(branchId, messageId, expectedHeadMessageId) {
3757
- const result = this.#stmt(
3758
- "UPDATE branches SET headMessageId = ? WHERE id = ? AND headMessageId IS ?"
3759
- ).run(messageId, branchId, expectedHeadMessageId);
3744
+ const result = this.#sql.run`UPDATE branches SET headMessageId = ${messageId} WHERE id = ${branchId} AND headMessageId IS ${expectedHeadMessageId}`;
3760
3745
  return result.changes > 0;
3761
3746
  }
3762
3747
  async listBranches(chatId) {
@@ -3852,7 +3837,15 @@ var SqliteContextStore = class extends ContextStore {
3852
3837
  }
3853
3838
  sql += " ORDER BY fts.rank LIMIT ?";
3854
3839
  params.push(limit);
3855
- return z4.array(searchResult).parse(this.#db.prepare(sql).all(...params));
3840
+ const statement2 = this.#db.prepare(sql);
3841
+ try {
3842
+ return z4.array(searchResult).parse(statement2.all(...params));
3843
+ } catch (error) {
3844
+ if (isFts5QueryError(error)) {
3845
+ throw new SearchQuerySyntaxError(query, { cause: error });
3846
+ }
3847
+ throw error;
3848
+ }
3856
3849
  }
3857
3850
  // ==========================================================================
3858
3851
  // Visualization Operations
@@ -11212,6 +11205,16 @@ function soul() {
11212
11205
  return fragment("soul_protocol", ...children);
11213
11206
  }
11214
11207
 
11208
+ // packages/context/src/lib/store/postgres-schema-lock.ts
11209
+ function lockSchemaDDL(ddl, schema) {
11210
+ if (schema !== void 0 && !/^[a-zA-Z_]\w*$/.test(schema)) {
11211
+ throw new Error(`Invalid schema name: "${schema}"`);
11212
+ }
11213
+ const key = schema === void 0 ? `coalesce(current_schema(), '')` : `'${schema}'`;
11214
+ return `SELECT pg_advisory_xact_lock(hashtextextended('deepagents:schema-ddl:' || ${key}, 0));
11215
+ ${ddl}`;
11216
+ }
11217
+
11215
11218
  // packages/context/src/lib/store/postgres.store.ts
11216
11219
  import { createRequire } from "node:module";
11217
11220
  import { z as z14 } from "zod";
@@ -11467,8 +11470,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
11467
11470
  return store;
11468
11471
  }
11469
11472
  async #initialize() {
11470
- const ddl = storeDDL(this.#schema);
11471
- await this.#pool.query(ddl);
11473
+ await this.#pool.query(lockSchemaDDL(storeDDL(this.#schema), this.#schema));
11472
11474
  }
11473
11475
  /**
11474
11476
  * Execute a function within a transaction.
@@ -12095,6 +12097,38 @@ END;
12095
12097
  `;
12096
12098
  }
12097
12099
 
12100
+ // packages/context/src/lib/store/sqlserver-schema-lock.ts
12101
+ async function withSqlServerSchemaLock(mssql, pool, schema, run) {
12102
+ const holder = new mssql.Transaction(pool);
12103
+ await holder.begin();
12104
+ let result;
12105
+ try {
12106
+ const lock = new mssql.Request(holder);
12107
+ lock.input(
12108
+ "resource",
12109
+ mssql.NVarChar(255),
12110
+ `deepagents:schema-ddl:${schema}`
12111
+ );
12112
+ const { recordset } = await lock.query(`
12113
+ DECLARE @status int;
12114
+ EXEC @status = sp_getapplock @Resource = @resource, @LockMode = 'Exclusive', @LockOwner = 'Transaction', @LockTimeout = -1;
12115
+ SELECT @status AS status;
12116
+ `);
12117
+ if (recordset[0].status < 0) {
12118
+ throw new Error(
12119
+ `Could not lock the DDL of schema "${schema}": sp_getapplock returned ${recordset[0].status}.`
12120
+ );
12121
+ }
12122
+ result = await run();
12123
+ } catch (error) {
12124
+ await holder.rollback().catch(() => {
12125
+ });
12126
+ throw error;
12127
+ }
12128
+ await holder.rollback();
12129
+ return result;
12130
+ }
12131
+
12098
12132
  // packages/context/src/lib/store/sqlserver.store.ts
12099
12133
  var chatColumns3 = z15.object({
12100
12134
  id: z15.string(),
@@ -12242,22 +12276,29 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12242
12276
  if (this.#ownsPool) {
12243
12277
  await this.#pool.connect();
12244
12278
  }
12245
- const schemaReq = this.#pool.request();
12246
- schemaReq.input("schema", this.#schema);
12247
- await schemaReq.query(`
12248
- IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = @schema)
12249
- BEGIN
12250
- DECLARE @sql NVARCHAR(MAX) = N'CREATE SCHEMA ' + QUOTENAME(@schema);
12251
- EXEC sp_executesql @sql;
12252
- END
12253
- `);
12254
- const ddl = storeDDL2(this.#schema);
12255
- const batches = ddl.split(/\bGO\b/i).filter((b) => b.trim());
12256
- for (const batch of batches) {
12257
- if (batch.trim()) {
12258
- await this.#pool.request().batch(batch);
12279
+ await withSqlServerSchemaLock(
12280
+ _SqlServerContextStore.#requireMssql(),
12281
+ this.#pool,
12282
+ this.#schema,
12283
+ async () => {
12284
+ const schemaReq = this.#pool.request();
12285
+ schemaReq.input("schema", this.#schema);
12286
+ await schemaReq.query(`
12287
+ IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = @schema)
12288
+ BEGIN
12289
+ DECLARE @sql NVARCHAR(MAX) = N'CREATE SCHEMA ' + QUOTENAME(@schema);
12290
+ EXEC sp_executesql @sql;
12291
+ END
12292
+ `);
12293
+ const ddl = storeDDL2(this.#schema);
12294
+ const batches = ddl.split(/\bGO\b/i).filter((b) => b.trim());
12295
+ for (const batch of batches) {
12296
+ if (batch.trim()) {
12297
+ await this.#pool.request().batch(batch);
12298
+ }
12299
+ }
12259
12300
  }
12260
- }
12301
+ );
12261
12302
  }
12262
12303
  /**
12263
12304
  * Execute a function within a transaction.
@@ -12265,14 +12306,14 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12265
12306
  */
12266
12307
  async #useTransaction(fn) {
12267
12308
  const mssql = _SqlServerContextStore.#requireMssql();
12268
- const transaction = new mssql.Transaction(this.#pool);
12309
+ const transaction3 = new mssql.Transaction(this.#pool);
12269
12310
  try {
12270
- await transaction.begin();
12271
- const result = await fn(transaction);
12272
- await transaction.commit();
12311
+ await transaction3.begin();
12312
+ const result = await fn(transaction3);
12313
+ await transaction3.commit();
12273
12314
  return result;
12274
12315
  } catch (error) {
12275
- await transaction.rollback();
12316
+ await transaction3.rollback();
12276
12317
  throw error;
12277
12318
  }
12278
12319
  }
@@ -12307,9 +12348,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12307
12348
  // Chat Operations
12308
12349
  // ==========================================================================
12309
12350
  async createChat(chat2) {
12310
- return this.#useTransaction(async (transaction) => {
12351
+ return this.#useTransaction(async (transaction3) => {
12311
12352
  const mssql = _SqlServerContextStore.#requireMssql();
12312
- const request = transaction.request();
12353
+ const request = transaction3.request();
12313
12354
  request.input("p0", mssql.NVarChar, chat2.id);
12314
12355
  request.input("p1", mssql.NVarChar, chat2.userId);
12315
12356
  request.input("p2", mssql.NVarChar, chat2.title ?? null);
@@ -12324,7 +12365,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12324
12365
  VALUES (@p0, @p1, @p2, @p3)
12325
12366
  `);
12326
12367
  const created = storedChat3.parse(result.recordset[0]);
12327
- const branchRequest = transaction.request();
12368
+ const branchRequest = transaction3.request();
12328
12369
  branchRequest.input("p0", mssql.NVarChar, crypto.randomUUID());
12329
12370
  branchRequest.input("p1", mssql.NVarChar, chat2.id);
12330
12371
  branchRequest.input("p2", mssql.BigInt, Date.now());
@@ -12336,9 +12377,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12336
12377
  });
12337
12378
  }
12338
12379
  async upsertChat(chat2) {
12339
- return this.#useTransaction(async (transaction) => {
12380
+ return this.#useTransaction(async (transaction3) => {
12340
12381
  const mssql = _SqlServerContextStore.#requireMssql();
12341
- const request = transaction.request();
12382
+ const request = transaction3.request();
12342
12383
  request.input("p0", mssql.NVarChar, chat2.id);
12343
12384
  request.input("p1", mssql.NVarChar, chat2.userId);
12344
12385
  request.input("p2", mssql.NVarChar, chat2.title ?? null);
@@ -12360,7 +12401,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12360
12401
  OUTPUT INSERTED.*;
12361
12402
  `);
12362
12403
  const upserted = storedChat3.parse(result.recordset[0]);
12363
- const branchRequest = transaction.request();
12404
+ const branchRequest = transaction3.request();
12364
12405
  branchRequest.input("p0", mssql.NVarChar, crypto.randomUUID());
12365
12406
  branchRequest.input("p1", mssql.NVarChar, chat2.id);
12366
12407
  branchRequest.input("p2", mssql.BigInt, Date.now());
@@ -12383,9 +12424,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12383
12424
  return chat2;
12384
12425
  }
12385
12426
  async updateChat(chatId, update) {
12386
- return this.#useTransaction(async (transaction) => {
12427
+ return this.#useTransaction(async (transaction3) => {
12387
12428
  const mssql = _SqlServerContextStore.#requireMssql();
12388
- const read = transaction.request();
12429
+ const read = transaction3.request();
12389
12430
  read.input("chatId", mssql.NVarChar, chatId);
12390
12431
  const result = await read.query(`
12391
12432
  SELECT *
@@ -12402,7 +12443,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12402
12443
  "updatedAt = DATEDIFF_BIG(ms, '1970-01-01', GETUTCDATE())"
12403
12444
  ];
12404
12445
  let paramIndex = 0;
12405
- const write = transaction.request();
12446
+ const write = transaction3.request();
12406
12447
  if (updates.title !== void 0) {
12407
12448
  const name = `p${paramIndex++}`;
12408
12449
  setClauses.push(`title = @${name}`);
@@ -12467,9 +12508,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12467
12508
  );
12468
12509
  }
12469
12510
  async deleteChat(chatId, options) {
12470
- return this.#useTransaction(async (transaction) => {
12511
+ return this.#useTransaction(async (transaction3) => {
12471
12512
  const mssql = _SqlServerContextStore.#requireMssql();
12472
- const request = transaction.request();
12513
+ const request = transaction3.request();
12473
12514
  request.input("p0", mssql.NVarChar, chatId);
12474
12515
  let sql = `DELETE FROM ${this.#t("chats")} WHERE id = @p0`;
12475
12516
  if (options?.userId !== void 0) {
@@ -12487,9 +12528,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12487
12528
  if (message2.parentId === message2.id) {
12488
12529
  throw new Error(`Message ${message2.id} cannot be its own parent`);
12489
12530
  }
12490
- await this.#useTransaction(async (transaction) => {
12531
+ await this.#useTransaction(async (transaction3) => {
12491
12532
  const mssql = _SqlServerContextStore.#requireMssql();
12492
- const request = transaction.request();
12533
+ const request = transaction3.request();
12493
12534
  request.input("p0", mssql.NVarChar, message2.id);
12494
12535
  request.input("p1", mssql.NVarChar, message2.chatId);
12495
12536
  request.input("p2", mssql.NVarChar, message2.parentId);
@@ -12508,7 +12549,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12508
12549
  VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6);
12509
12550
  `);
12510
12551
  const content = typeof message2.data === "string" ? message2.data : JSON.stringify(message2.data);
12511
- const ftsRequest = transaction.request();
12552
+ const ftsRequest = transaction3.request();
12512
12553
  ftsRequest.input("p0", mssql.NVarChar, message2.id);
12513
12554
  ftsRequest.input("p1", mssql.NVarChar, message2.chatId);
12514
12555
  ftsRequest.input("p2", mssql.NVarChar, message2.name);
@@ -12616,14 +12657,14 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12616
12657
  return branch;
12617
12658
  }
12618
12659
  async setActiveBranch(chatId, branchId) {
12619
- await this.#useTransaction(async (transaction) => {
12660
+ await this.#useTransaction(async (transaction3) => {
12620
12661
  const mssql = _SqlServerContextStore.#requireMssql();
12621
- const deactivateRequest = transaction.request();
12662
+ const deactivateRequest = transaction3.request();
12622
12663
  deactivateRequest.input("p0", mssql.NVarChar, chatId);
12623
12664
  await deactivateRequest.query(
12624
12665
  `UPDATE ${this.#t("branches")} SET isActive = 0 WHERE chatId = @p0`
12625
12666
  );
12626
- const activateRequest = transaction.request();
12667
+ const activateRequest = transaction3.request();
12627
12668
  activateRequest.input("p0", mssql.NVarChar, branchId);
12628
12669
  await activateRequest.query(
12629
12670
  `UPDATE ${this.#t("branches")} SET isActive = 1 WHERE id = @p0`
@@ -12686,9 +12727,9 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
12686
12727
  // Checkpoint Operations
12687
12728
  // ==========================================================================
12688
12729
  async createCheckpoint(checkpoint) {
12689
- await this.#useTransaction(async (transaction) => {
12730
+ await this.#useTransaction(async (transaction3) => {
12690
12731
  const mssql = _SqlServerContextStore.#requireMssql();
12691
- const request = transaction.request();
12732
+ const request = transaction3.request();
12692
12733
  request.input("p0", mssql.NVarChar, checkpoint.id);
12693
12734
  request.input("p1", mssql.NVarChar, checkpoint.chatId);
12694
12735
  request.input("p2", mssql.NVarChar, checkpoint.name);
@@ -13295,7 +13336,10 @@ var PostgresNotifyChangeSource = class _PostgresNotifyChangeSource {
13295
13336
  const source = new _PostgresNotifyChangeSource(options);
13296
13337
  try {
13297
13338
  await source.#pool.query(
13298
- postgresStreamNotifyDDL(source.#schema, source.#channel)
13339
+ lockSchemaDDL(
13340
+ postgresStreamNotifyDDL(source.#schema, source.#channel),
13341
+ source.#schema
13342
+ )
13299
13343
  );
13300
13344
  } catch (error) {
13301
13345
  await source.close();
@@ -13549,7 +13593,9 @@ var PostgresStreamStore = class _PostgresStreamStore extends StreamStore {
13549
13593
  return store;
13550
13594
  }
13551
13595
  async #initialize() {
13552
- await this.#pool.query(postgresStreamDDL(this.#schema));
13596
+ await this.#pool.query(
13597
+ lockSchemaDDL(postgresStreamDDL(this.#schema), this.#schema)
13598
+ );
13553
13599
  }
13554
13600
  async close() {
13555
13601
  if (this.#ownsPool && !this.#pool.ending) {
@@ -13842,7 +13888,10 @@ function assertIdentifier2(value, label) {
13842
13888
  }
13843
13889
 
13844
13890
  // packages/context/src/lib/stream/sqlite.stream-store.ts
13845
- import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
13891
+ import { transaction as transaction2 } from "@zukhruf/sqlite-transaction";
13892
+ import {
13893
+ DatabaseSync as DatabaseSync2
13894
+ } from "node:sqlite";
13846
13895
  import { z as z19 } from "zod";
13847
13896
 
13848
13897
  // packages/context/src/lib/stream/ddl.stream.sqlite.sql
@@ -13868,55 +13917,27 @@ var chunkRow2 = z19.object({
13868
13917
  });
13869
13918
  var SqliteStreamStore = class extends StreamStore {
13870
13919
  #db;
13871
- #statements = /* @__PURE__ */ new Map();
13872
- #stmt(sql) {
13873
- let stmt = this.#statements.get(sql);
13874
- if (!stmt) {
13875
- stmt = this.#db.prepare(sql);
13876
- this.#statements.set(sql, stmt);
13877
- }
13878
- return stmt;
13879
- }
13920
+ #sql;
13880
13921
  close() {
13881
13922
  if (!this.#db.isOpen) return;
13882
- this.#statements.clear();
13883
13923
  this.#db.close();
13884
13924
  }
13885
13925
  constructor(pathOrDb) {
13886
13926
  super();
13887
13927
  this.#db = typeof pathOrDb === "string" ? new DatabaseSync2(pathOrDb) : pathOrDb;
13888
13928
  this.#db.exec(ddl_stream_sqlite_default);
13929
+ this.#sql = this.#db.createTagStore();
13889
13930
  }
13890
13931
  async createStream(stream) {
13891
- this.#stmt(
13892
- `INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
13893
- VALUES (?, ?, ?, ?, ?, ?, ?)`
13894
- ).run(
13895
- stream.id,
13896
- stream.status,
13897
- stream.createdAt,
13898
- stream.startedAt,
13899
- stream.finishedAt,
13900
- stream.cancelRequestedAt,
13901
- stream.error
13902
- );
13932
+ this.#sql.run`INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
13933
+ VALUES (${stream.id}, ${stream.status}, ${stream.createdAt}, ${stream.startedAt}, ${stream.finishedAt}, ${stream.cancelRequestedAt}, ${stream.error})`;
13903
13934
  }
13904
13935
  async upsertStream(stream) {
13905
13936
  const created = streamRow.optional().parse(
13906
- this.#stmt(
13907
- `INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
13908
- VALUES (?, ?, ?, ?, ?, ?, ?)
13937
+ this.#sql.get`INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
13938
+ VALUES (${stream.id}, ${stream.status}, ${stream.createdAt}, ${stream.startedAt}, ${stream.finishedAt}, ${stream.cancelRequestedAt}, ${stream.error})
13909
13939
  ON CONFLICT(id) DO NOTHING
13910
13940
  RETURNING *`
13911
- ).get(
13912
- stream.id,
13913
- stream.status,
13914
- stream.createdAt,
13915
- stream.startedAt,
13916
- stream.finishedAt,
13917
- stream.cancelRequestedAt,
13918
- stream.error
13919
- )
13920
13941
  );
13921
13942
  if (created) {
13922
13943
  return { stream: created, created: true };
@@ -13930,137 +13951,107 @@ var SqliteStreamStore = class extends StreamStore {
13930
13951
  return { stream: existing, created: false };
13931
13952
  }
13932
13953
  async getStream(streamId) {
13933
- return streamRow.optional().parse(this.#stmt("SELECT * FROM streams WHERE id = ?").get(streamId));
13954
+ return streamRow.optional().parse(this.#sql.get`SELECT * FROM streams WHERE id = ${streamId}`);
13934
13955
  }
13935
13956
  async getStreamStatus(streamId) {
13936
- const row = statusRow2.optional().parse(
13937
- this.#stmt("SELECT status FROM streams WHERE id = ?").get(streamId)
13938
- );
13957
+ const row = statusRow2.optional().parse(this.#sql.get`SELECT status FROM streams WHERE id = ${streamId}`);
13939
13958
  return row?.status;
13940
13959
  }
13941
13960
  async listStreamIds(options) {
13942
- let sql = "SELECT id FROM streams";
13943
- const params = [];
13944
- if (options?.status) {
13945
- sql += " WHERE status = ?";
13946
- params.push(options.status);
13947
- }
13948
- sql += " ORDER BY createdAt ASC, id ASC";
13949
- const rows = z19.array(idRow5).parse(this.#stmt(sql).all(...params));
13961
+ const rows = z19.array(idRow5).parse(
13962
+ options?.status ? this.#sql.all`SELECT id FROM streams WHERE status = ${options.status} ORDER BY createdAt ASC, id ASC` : this.#sql.all`SELECT id FROM streams ORDER BY createdAt ASC, id ASC`
13963
+ );
13950
13964
  return rows.map((row) => row.id);
13951
13965
  }
13952
13966
  async updateStream(streamId, update) {
13953
- return this.#transaction(() => {
13954
- const stream = streamRow.optional().parse(this.#stmt("SELECT * FROM streams WHERE id = ?").get(streamId));
13955
- if (!stream) {
13956
- throw new Error(`updateStream: stream "${streamId}" not found`);
13957
- }
13958
- const updates = update(stream);
13959
- if (updates === void 0) return { stream, updated: false };
13960
- const setClauses = [];
13961
- const params = [];
13962
- const set = (column, value) => {
13963
- setClauses.push(`${column} = ?`);
13964
- params.push(value);
13965
- };
13966
- if (updates.status !== void 0) set("status", updates.status);
13967
- if (updates.startedAt !== void 0) set("startedAt", updates.startedAt);
13968
- if (updates.finishedAt !== void 0) {
13969
- set("finishedAt", updates.finishedAt);
13970
- }
13971
- if (updates.cancelRequestedAt !== void 0) {
13972
- set("cancelRequestedAt", updates.cancelRequestedAt);
13973
- }
13974
- if (updates.error !== void 0) set("error", updates.error);
13975
- if (setClauses.length === 0) return { stream, updated: false };
13976
- params.push(streamId);
13977
- const next = streamRow.parse(
13978
- this.#stmt(
13979
- `UPDATE streams SET ${setClauses.join(", ")} WHERE id = ? RETURNING *`
13980
- ).get(...params)
13981
- );
13982
- return { stream: next, updated: true };
13983
- });
13967
+ return transaction2(
13968
+ this.#db,
13969
+ () => {
13970
+ const stream = streamRow.optional().parse(this.#sql.get`SELECT * FROM streams WHERE id = ${streamId}`);
13971
+ if (!stream) {
13972
+ throw new Error(`updateStream: stream "${streamId}" not found`);
13973
+ }
13974
+ const updates = update(stream);
13975
+ if (updates === void 0) return { stream, updated: false };
13976
+ const setClauses = [];
13977
+ const params = [];
13978
+ const set = (column, value) => {
13979
+ setClauses.push(`${column} = ?`);
13980
+ params.push(value);
13981
+ };
13982
+ if (updates.status !== void 0) set("status", updates.status);
13983
+ if (updates.startedAt !== void 0)
13984
+ set("startedAt", updates.startedAt);
13985
+ if (updates.finishedAt !== void 0) {
13986
+ set("finishedAt", updates.finishedAt);
13987
+ }
13988
+ if (updates.cancelRequestedAt !== void 0) {
13989
+ set("cancelRequestedAt", updates.cancelRequestedAt);
13990
+ }
13991
+ if (updates.error !== void 0) set("error", updates.error);
13992
+ if (setClauses.length === 0) return { stream, updated: false };
13993
+ params.push(streamId);
13994
+ const next = streamRow.parse(
13995
+ this.#db.prepare(
13996
+ `UPDATE streams SET ${setClauses.join(", ")} WHERE id = ? RETURNING *`
13997
+ ).get(...params)
13998
+ );
13999
+ return { stream: next, updated: true };
14000
+ },
14001
+ { mode: "immediate" }
14002
+ );
13984
14003
  }
13985
14004
  async updateStreamStatus(streamId, status, options) {
13986
14005
  const now = Date.now();
13987
14006
  switch (status) {
13988
14007
  case "running":
13989
- this.#stmt(
13990
- `UPDATE streams SET status = ?, startedAt = ?
13991
- WHERE id = ? AND status = 'queued'`
13992
- ).run(status, now, streamId);
14008
+ this.#sql.run`UPDATE streams SET status = ${status}, startedAt = ${now}
14009
+ WHERE id = ${streamId} AND status = 'queued'`;
13993
14010
  break;
13994
14011
  case "completed":
13995
- this.#stmt(
13996
- `UPDATE streams SET status = ?, finishedAt = ?
13997
- WHERE id = ? AND status IN ('queued', 'running')`
13998
- ).run(status, now, streamId);
14012
+ this.#sql.run`UPDATE streams SET status = ${status}, finishedAt = ${now}
14013
+ WHERE id = ${streamId} AND status IN ('queued', 'running')`;
13999
14014
  break;
14000
14015
  case "failed":
14001
- this.#stmt(
14002
- `UPDATE streams SET status = ?, finishedAt = ?, error = ?
14003
- WHERE id = ? AND status IN ('queued', 'running')`
14004
- ).run(status, now, options?.error ?? null, streamId);
14016
+ this.#sql.run`UPDATE streams SET status = ${status}, finishedAt = ${now}, error = ${options?.error ?? null}
14017
+ WHERE id = ${streamId} AND status IN ('queued', 'running')`;
14005
14018
  break;
14006
14019
  case "cancelled":
14007
- this.#stmt(
14008
- `UPDATE streams SET status = ?, cancelRequestedAt = ?, finishedAt = ?
14009
- WHERE id = ? AND status IN ('queued', 'running')`
14010
- ).run(status, now, now, streamId);
14020
+ this.#sql.run`UPDATE streams SET status = ${status}, cancelRequestedAt = ${now}, finishedAt = ${now}
14021
+ WHERE id = ${streamId} AND status IN ('queued', 'running')`;
14011
14022
  break;
14012
14023
  default:
14013
- this.#stmt(
14014
- `UPDATE streams SET status = ?
14015
- WHERE id = ? AND status = 'queued'`
14016
- ).run(status, streamId);
14024
+ this.#sql.run`UPDATE streams SET status = ${status}
14025
+ WHERE id = ${streamId} AND status = 'queued'`;
14017
14026
  }
14018
14027
  }
14019
14028
  async appendChunks(chunks) {
14020
14029
  if (chunks.length === 0) return;
14021
14030
  const failures = collectStreamFailures(chunks);
14022
- this.#transaction(() => {
14023
- for (const chunk of chunks) {
14024
- this.#stmt(
14025
- `INSERT INTO stream_chunks (streamId, seq, data, createdAt)
14026
- VALUES (?, ?, ?, ?)`
14027
- ).run(
14028
- chunk.streamId,
14029
- chunk.seq,
14030
- JSON.stringify(chunk.data),
14031
- chunk.createdAt
14032
- );
14033
- }
14034
- const failedAt = Date.now();
14035
- for (const failure of failures) {
14036
- const result = this.#stmt(
14037
- `UPDATE streams SET status = ?, finishedAt = ?, error = ?
14038
- WHERE id = ? AND status IN ('queued', 'running')`
14039
- ).run("failed", failedAt, failure.error, failure.streamId);
14040
- if (result.changes !== 1) {
14041
- const existing = this.#stmt(
14042
- "SELECT id FROM streams WHERE id = ?"
14043
- ).get(failure.streamId);
14044
- if (!existing) {
14045
- throw new Error(`Stream "${failure.streamId}" not found`);
14031
+ transaction2(
14032
+ this.#db,
14033
+ () => {
14034
+ for (const chunk of chunks) {
14035
+ this.#sql.run`INSERT INTO stream_chunks (streamId, seq, data, createdAt)
14036
+ VALUES (${chunk.streamId}, ${chunk.seq}, ${JSON.stringify(chunk.data)}, ${chunk.createdAt})`;
14037
+ }
14038
+ const failedAt = Date.now();
14039
+ for (const failure of failures) {
14040
+ const result = this.#sql.run`UPDATE streams SET status = 'failed', finishedAt = ${failedAt}, error = ${failure.error}
14041
+ WHERE id = ${failure.streamId} AND status IN ('queued', 'running')`;
14042
+ if (result.changes !== 1) {
14043
+ const existing = this.#sql.get`SELECT id FROM streams WHERE id = ${failure.streamId}`;
14044
+ if (!existing) {
14045
+ throw new Error(`Stream "${failure.streamId}" not found`);
14046
+ }
14046
14047
  }
14047
14048
  }
14048
- }
14049
- });
14049
+ },
14050
+ { mode: "immediate" }
14051
+ );
14050
14052
  }
14051
14053
  async getChunks(streamId, fromSeq, limit) {
14052
- let sql = "SELECT * FROM stream_chunks WHERE streamId = ?";
14053
- const params = [streamId];
14054
- if (fromSeq !== void 0) {
14055
- sql += " AND seq >= ?";
14056
- params.push(fromSeq);
14057
- }
14058
- sql += " ORDER BY seq ASC";
14059
- if (limit !== void 0) {
14060
- sql += " LIMIT ?";
14061
- params.push(limit);
14062
- }
14063
- const rows = z19.array(chunkRow2).parse(this.#stmt(sql).all(...params));
14054
+ const rows = z19.array(chunkRow2).parse(this.#chunkRows(streamId, fromSeq, limit));
14064
14055
  return Promise.all(
14065
14056
  rows.map(async (row) => ({
14066
14057
  streamId: row.streamId,
@@ -14070,50 +14061,50 @@ var SqliteStreamStore = class extends StreamStore {
14070
14061
  }))
14071
14062
  );
14072
14063
  }
14064
+ #chunkRows(streamId, fromSeq, limit) {
14065
+ if (fromSeq !== void 0 && limit !== void 0) {
14066
+ return this.#sql.all`SELECT * FROM stream_chunks WHERE streamId = ${streamId} AND seq >= ${fromSeq} ORDER BY seq ASC LIMIT ${limit}`;
14067
+ }
14068
+ if (fromSeq !== void 0) {
14069
+ return this.#sql.all`SELECT * FROM stream_chunks WHERE streamId = ${streamId} AND seq >= ${fromSeq} ORDER BY seq ASC`;
14070
+ }
14071
+ if (limit !== void 0) {
14072
+ return this.#sql.all`SELECT * FROM stream_chunks WHERE streamId = ${streamId} ORDER BY seq ASC LIMIT ${limit}`;
14073
+ }
14074
+ return this.#sql.all`SELECT * FROM stream_chunks WHERE streamId = ${streamId} ORDER BY seq ASC`;
14075
+ }
14073
14076
  async deleteStream(streamId) {
14074
- this.#stmt("DELETE FROM streams WHERE id = ?").run(streamId);
14077
+ this.#sql.run`DELETE FROM streams WHERE id = ${streamId}`;
14075
14078
  }
14076
14079
  async reopenStream(streamId) {
14077
- return this.#transaction(() => {
14078
- const row = statusRow2.optional().parse(this.#stmt("SELECT * FROM streams WHERE id = ?").get(streamId));
14079
- if (!row) {
14080
- throw new Error(`Stream "${streamId}" not found`);
14081
- }
14082
- if (row.status !== "completed" && row.status !== "failed" && row.status !== "cancelled") {
14083
- throw new Error(
14084
- `Cannot reopen stream "${streamId}" with status "${row.status}". Only terminal streams can be reopened.`
14085
- );
14086
- }
14087
- this.#stmt("DELETE FROM streams WHERE id = ?").run(streamId);
14088
- const now = Date.now();
14089
- this.#stmt(
14090
- `INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
14091
- VALUES (?, ?, ?, ?, ?, ?, ?)`
14092
- ).run(streamId, "queued", now, null, null, null, null);
14093
- return {
14094
- id: streamId,
14095
- status: "queued",
14096
- createdAt: now,
14097
- startedAt: null,
14098
- finishedAt: null,
14099
- cancelRequestedAt: null,
14100
- error: null
14101
- };
14102
- });
14103
- }
14104
- #transaction(callback) {
14105
- this.#db.exec("BEGIN IMMEDIATE");
14106
- try {
14107
- const result = callback();
14108
- this.#db.exec("COMMIT");
14109
- return result;
14110
- } catch (error) {
14111
- try {
14112
- this.#db.exec("ROLLBACK");
14113
- } catch {
14114
- }
14115
- throw error;
14116
- }
14080
+ return transaction2(
14081
+ this.#db,
14082
+ () => {
14083
+ const row = statusRow2.optional().parse(this.#sql.get`SELECT * FROM streams WHERE id = ${streamId}`);
14084
+ if (!row) {
14085
+ throw new Error(`Stream "${streamId}" not found`);
14086
+ }
14087
+ if (row.status !== "completed" && row.status !== "failed" && row.status !== "cancelled") {
14088
+ throw new Error(
14089
+ `Cannot reopen stream "${streamId}" with status "${row.status}". Only terminal streams can be reopened.`
14090
+ );
14091
+ }
14092
+ this.#sql.run`DELETE FROM streams WHERE id = ${streamId}`;
14093
+ const now = Date.now();
14094
+ this.#sql.run`INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
14095
+ VALUES (${streamId}, 'queued', ${now}, NULL, NULL, NULL, NULL)`;
14096
+ return {
14097
+ id: streamId,
14098
+ status: "queued",
14099
+ createdAt: now,
14100
+ startedAt: null,
14101
+ finishedAt: null,
14102
+ cancelRequestedAt: null,
14103
+ error: null
14104
+ };
14105
+ },
14106
+ { mode: "immediate" }
14107
+ );
14117
14108
  }
14118
14109
  };
14119
14110
 
@@ -14580,6 +14571,7 @@ export {
14580
14571
  PostgresNotifyChangeSource,
14581
14572
  PostgresStreamStore,
14582
14573
  RuntimeStrategy,
14574
+ SearchQuerySyntaxError,
14583
14575
  SqlServerContextStore,
14584
14576
  SqliteContextStore,
14585
14577
  SqliteStreamStore,
@@ -14686,6 +14678,7 @@ export {
14686
14678
  isSyntheticReminderMessage,
14687
14679
  lastAssistantLength,
14688
14680
  localeReminder,
14681
+ lockSchemaDDL,
14689
14682
  mapGenerateErrorToCode,
14690
14683
  mergeMessageMetadata,
14691
14684
  mergeReminderMetadata,