@deepagents/context 0.16.0 → 0.17.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/dist/index.js CHANGED
@@ -3916,18 +3916,113 @@ var InMemoryContextStore = class extends SqliteContextStore {
3916
3916
  // packages/context/src/lib/store/postgres.store.ts
3917
3917
  import { createRequire } from "node:module";
3918
3918
 
3919
- // packages/context/src/lib/store/ddl.postgres.sql
3920
- var ddl_postgres_default = "-- Context Store DDL for PostgreSQL\n-- This schema implements a DAG-based message history with branching and checkpoints.\n\n-- Chats table\n-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates\nCREATE TABLE IF NOT EXISTS chats (\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n title TEXT,\n metadata JSONB,\n createdAt BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT,\n updatedAt BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT\n);\n\nCREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);\nCREATE INDEX IF NOT EXISTS idx_chats_userId ON chats(userId);\nCREATE INDEX IF NOT EXISTS idx_chats_metadata ON chats USING GIN (metadata);\n\n-- Messages table (nodes in the DAG)\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n parentId TEXT,\n name TEXT NOT NULL,\n type TEXT,\n data JSONB NOT NULL,\n createdAt BIGINT NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (parentId) REFERENCES messages(id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_messages_chatId ON messages(chatId);\nCREATE INDEX IF NOT EXISTS idx_messages_parentId ON messages(parentId);\n\n-- Branches table (pointers to head messages)\nCREATE TABLE IF NOT EXISTS branches (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n headMessageId TEXT,\n isActive BOOLEAN NOT NULL DEFAULT FALSE,\n createdAt BIGINT NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (headMessageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_branches_chatId ON branches(chatId);\n\n-- Checkpoints table (pointers to message nodes)\nCREATE TABLE IF NOT EXISTS checkpoints (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n messageId TEXT NOT NULL,\n createdAt BIGINT NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (messageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_checkpoints_chatId ON checkpoints(chatId);\n\n-- Full-text search using tsvector + GIN index\nCREATE TABLE IF NOT EXISTS messages_fts (\n messageId TEXT PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n content TEXT NOT NULL,\n content_vector TSVECTOR\n);\n\nCREATE INDEX IF NOT EXISTS idx_messages_fts_vector ON messages_fts USING GIN(content_vector);\nCREATE INDEX IF NOT EXISTS idx_messages_fts_chatId ON messages_fts(chatId);\n\n-- Trigger to automatically update tsvector on insert/update\nCREATE OR REPLACE FUNCTION messages_fts_update_vector() RETURNS TRIGGER AS $$\nBEGIN\n NEW.content_vector := to_tsvector('english', NEW.content);\n RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nDROP TRIGGER IF EXISTS messages_fts_vector_update ON messages_fts;\nCREATE TRIGGER messages_fts_vector_update\n BEFORE INSERT OR UPDATE ON messages_fts\n FOR EACH ROW\n EXECUTE FUNCTION messages_fts_update_vector();\n";
3919
+ // packages/context/src/lib/store/ddl.postgres.ts
3920
+ function storeDDL(schema) {
3921
+ return `
3922
+ CREATE SCHEMA IF NOT EXISTS "${schema}";
3923
+
3924
+ CREATE TABLE IF NOT EXISTS "${schema}"."chats" (
3925
+ id TEXT PRIMARY KEY,
3926
+ userId TEXT NOT NULL,
3927
+ title TEXT,
3928
+ metadata JSONB,
3929
+ createdAt BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT,
3930
+ updatedAt BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT
3931
+ );
3932
+
3933
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_chats_updatedAt" ON "${schema}"."chats"(updatedAt);
3934
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_chats_userId" ON "${schema}"."chats"(userId);
3935
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_chats_metadata" ON "${schema}"."chats" USING GIN (metadata);
3936
+
3937
+ CREATE TABLE IF NOT EXISTS "${schema}"."messages" (
3938
+ id TEXT PRIMARY KEY,
3939
+ chatId TEXT NOT NULL,
3940
+ parentId TEXT,
3941
+ name TEXT NOT NULL,
3942
+ type TEXT,
3943
+ data JSONB NOT NULL,
3944
+ createdAt BIGINT NOT NULL,
3945
+ FOREIGN KEY (chatId) REFERENCES "${schema}"."chats"(id) ON DELETE CASCADE,
3946
+ FOREIGN KEY (parentId) REFERENCES "${schema}"."messages"(id)
3947
+ );
3948
+
3949
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_messages_chatId" ON "${schema}"."messages"(chatId);
3950
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_messages_parentId" ON "${schema}"."messages"(parentId);
3951
+
3952
+ CREATE TABLE IF NOT EXISTS "${schema}"."branches" (
3953
+ id TEXT PRIMARY KEY,
3954
+ chatId TEXT NOT NULL,
3955
+ name TEXT NOT NULL,
3956
+ headMessageId TEXT,
3957
+ isActive BOOLEAN NOT NULL DEFAULT FALSE,
3958
+ createdAt BIGINT NOT NULL,
3959
+ FOREIGN KEY (chatId) REFERENCES "${schema}"."chats"(id) ON DELETE CASCADE,
3960
+ FOREIGN KEY (headMessageId) REFERENCES "${schema}"."messages"(id),
3961
+ UNIQUE(chatId, name)
3962
+ );
3963
+
3964
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_branches_chatId" ON "${schema}"."branches"(chatId);
3965
+
3966
+ CREATE TABLE IF NOT EXISTS "${schema}"."checkpoints" (
3967
+ id TEXT PRIMARY KEY,
3968
+ chatId TEXT NOT NULL,
3969
+ name TEXT NOT NULL,
3970
+ messageId TEXT NOT NULL,
3971
+ createdAt BIGINT NOT NULL,
3972
+ FOREIGN KEY (chatId) REFERENCES "${schema}"."chats"(id) ON DELETE CASCADE,
3973
+ FOREIGN KEY (messageId) REFERENCES "${schema}"."messages"(id),
3974
+ UNIQUE(chatId, name)
3975
+ );
3976
+
3977
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_checkpoints_chatId" ON "${schema}"."checkpoints"(chatId);
3978
+
3979
+ CREATE TABLE IF NOT EXISTS "${schema}"."messages_fts" (
3980
+ messageId TEXT PRIMARY KEY REFERENCES "${schema}"."messages"(id) ON DELETE CASCADE,
3981
+ chatId TEXT NOT NULL,
3982
+ name TEXT NOT NULL,
3983
+ content TEXT NOT NULL,
3984
+ content_vector TSVECTOR
3985
+ );
3986
+
3987
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_messages_fts_vector" ON "${schema}"."messages_fts" USING GIN(content_vector);
3988
+ CREATE INDEX IF NOT EXISTS "idx_${schema}_messages_fts_chatId" ON "${schema}"."messages_fts"(chatId);
3989
+
3990
+ CREATE OR REPLACE FUNCTION "${schema}"."messages_fts_update_vector"() RETURNS TRIGGER AS $$
3991
+ BEGIN
3992
+ NEW.content_vector := to_tsvector('english', NEW.content);
3993
+ RETURN NEW;
3994
+ END;
3995
+ $$ LANGUAGE plpgsql;
3996
+
3997
+ DROP TRIGGER IF EXISTS "${schema}_messages_fts_vector_update" ON "${schema}"."messages_fts";
3998
+ CREATE TRIGGER "${schema}_messages_fts_vector_update"
3999
+ BEFORE INSERT OR UPDATE ON "${schema}"."messages_fts"
4000
+ FOR EACH ROW
4001
+ EXECUTE FUNCTION "${schema}"."messages_fts_update_vector"();
4002
+ `;
4003
+ }
3921
4004
 
3922
4005
  // packages/context/src/lib/store/postgres.store.ts
3923
4006
  var PostgresContextStore = class _PostgresContextStore extends ContextStore {
3924
4007
  #pool;
3925
- #initialized;
4008
+ #schema;
4009
+ #ownsPool;
4010
+ #isInitialized = false;
3926
4011
  constructor(options) {
3927
4012
  super();
4013
+ const schema = options.schema ?? "public";
4014
+ if (!/^[a-zA-Z_]\w*$/.test(schema)) {
4015
+ throw new Error(`Invalid schema name: "${schema}"`);
4016
+ }
4017
+ this.#schema = schema;
3928
4018
  const pg = _PostgresContextStore.#requirePg();
3929
- this.#pool = typeof options.pool === "string" ? new pg.Pool({ connectionString: options.pool }) : new pg.Pool(options.pool);
3930
- this.#initialized = this.#initialize();
4019
+ if (options.pool instanceof pg.Pool) {
4020
+ this.#pool = options.pool;
4021
+ this.#ownsPool = false;
4022
+ } else {
4023
+ this.#pool = typeof options.pool === "string" ? new pg.Pool({ connectionString: options.pool }) : new pg.Pool(options.pool);
4024
+ this.#ownsPool = true;
4025
+ }
3931
4026
  }
3932
4027
  static #requirePg() {
3933
4028
  try {
@@ -3939,21 +4034,27 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
3939
4034
  );
3940
4035
  }
3941
4036
  }
3942
- async #initialize() {
3943
- await this.#pool.query(ddl_postgres_default);
4037
+ #t(name) {
4038
+ return `"${this.#schema}"."${name}"`;
3944
4039
  }
3945
- /**
3946
- * Ensure initialization is complete before any operation.
3947
- */
3948
- async #ensureInitialized() {
3949
- await this.#initialized;
4040
+ async initialize() {
4041
+ const ddl = storeDDL(this.#schema);
4042
+ await this.#pool.query(ddl);
4043
+ this.#isInitialized = true;
4044
+ }
4045
+ #ensureInitialized() {
4046
+ if (!this.#isInitialized) {
4047
+ throw new Error(
4048
+ "PostgresContextStore not initialized. Call await store.initialize() after construction."
4049
+ );
4050
+ }
3950
4051
  }
3951
4052
  /**
3952
4053
  * Execute a function within a transaction.
3953
4054
  * Automatically commits on success or rolls back on error.
3954
4055
  */
3955
4056
  async #useTransaction(fn) {
3956
- await this.#ensureInitialized();
4057
+ this.#ensureInitialized();
3957
4058
  const client = await this.#pool.connect();
3958
4059
  try {
3959
4060
  await client.query("BEGIN");
@@ -3971,7 +4072,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
3971
4072
  * Execute a query using the pool (no transaction).
3972
4073
  */
3973
4074
  async #query(sql, params) {
3974
- await this.#ensureInitialized();
4075
+ this.#ensureInitialized();
3975
4076
  const result = await this.#pool.query(sql, params);
3976
4077
  return result.rows;
3977
4078
  }
@@ -3980,7 +4081,9 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
3980
4081
  * Call this when done with the store.
3981
4082
  */
3982
4083
  async close() {
3983
- await this.#pool.end();
4084
+ if (this.#ownsPool) {
4085
+ await this.#pool.end();
4086
+ }
3984
4087
  }
3985
4088
  // ==========================================================================
3986
4089
  // Chat Operations
@@ -3988,7 +4091,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
3988
4091
  async createChat(chat) {
3989
4092
  return this.#useTransaction(async (client) => {
3990
4093
  const result = await client.query(
3991
- `INSERT INTO chats (id, userId, title, metadata)
4094
+ `INSERT INTO ${this.#t("chats")} (id, userId, title, metadata)
3992
4095
  VALUES ($1, $2, $3, $4)
3993
4096
  RETURNING *`,
3994
4097
  [
@@ -4000,7 +4103,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4000
4103
  );
4001
4104
  const row = result.rows[0];
4002
4105
  await client.query(
4003
- `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
4106
+ `INSERT INTO ${this.#t("branches")} (id, chatId, name, headMessageId, isActive, createdAt)
4004
4107
  VALUES ($1, $2, 'main', NULL, TRUE, $3)`,
4005
4108
  [crypto.randomUUID(), chat.id, Date.now()]
4006
4109
  );
@@ -4017,7 +4120,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4017
4120
  async upsertChat(chat) {
4018
4121
  return this.#useTransaction(async (client) => {
4019
4122
  const result = await client.query(
4020
- `INSERT INTO chats (id, userId, title, metadata)
4123
+ `INSERT INTO ${this.#t("chats")} (id, userId, title, metadata)
4021
4124
  VALUES ($1, $2, $3, $4)
4022
4125
  ON CONFLICT(id) DO UPDATE SET id = EXCLUDED.id
4023
4126
  RETURNING *`,
@@ -4030,7 +4133,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4030
4133
  );
4031
4134
  const row = result.rows[0];
4032
4135
  await client.query(
4033
- `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
4136
+ `INSERT INTO ${this.#t("branches")} (id, chatId, name, headMessageId, isActive, createdAt)
4034
4137
  VALUES ($1, $2, 'main', NULL, TRUE, $3)
4035
4138
  ON CONFLICT(chatId, name) DO NOTHING`,
4036
4139
  [crypto.randomUUID(), chat.id, Date.now()]
@@ -4046,7 +4149,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4046
4149
  });
4047
4150
  }
4048
4151
  async getChat(chatId) {
4049
- const rows = await this.#query("SELECT * FROM chats WHERE id = $1", [chatId]);
4152
+ const rows = await this.#query(`SELECT * FROM ${this.#t("chats")} WHERE id = $1`, [chatId]);
4050
4153
  if (rows.length === 0) {
4051
4154
  return void 0;
4052
4155
  }
@@ -4076,7 +4179,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4076
4179
  }
4077
4180
  params.push(chatId);
4078
4181
  const rows = await this.#query(
4079
- `UPDATE chats SET ${setClauses.join(", ")} WHERE id = $${paramIndex} RETURNING *`,
4182
+ `UPDATE ${this.#t("chats")} SET ${setClauses.join(", ")} WHERE id = $${paramIndex} RETURNING *`,
4080
4183
  params
4081
4184
  );
4082
4185
  const row = rows[0];
@@ -4124,9 +4227,9 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4124
4227
  c.updatedAt,
4125
4228
  COUNT(DISTINCT m.id) as messageCount,
4126
4229
  COUNT(DISTINCT b.id) as branchCount
4127
- FROM chats c
4128
- LEFT JOIN messages m ON m.chatId = c.id
4129
- LEFT JOIN branches b ON b.chatId = c.id
4230
+ FROM ${this.#t("chats")} c
4231
+ LEFT JOIN ${this.#t("messages")} m ON m.chatId = c.id
4232
+ LEFT JOIN ${this.#t("branches")} b ON b.chatId = c.id
4130
4233
  ${whereClause}
4131
4234
  GROUP BY c.id
4132
4235
  ORDER BY c.updatedAt DESC${limitClause}`,
@@ -4145,7 +4248,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4145
4248
  }
4146
4249
  async deleteChat(chatId, options) {
4147
4250
  return this.#useTransaction(async (client) => {
4148
- let sql = "DELETE FROM chats WHERE id = $1";
4251
+ let sql = `DELETE FROM ${this.#t("chats")} WHERE id = $1`;
4149
4252
  const params = [chatId];
4150
4253
  if (options?.userId !== void 0) {
4151
4254
  sql += " AND userId = $2";
@@ -4164,7 +4267,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4164
4267
  }
4165
4268
  await this.#useTransaction(async (client) => {
4166
4269
  await client.query(
4167
- `INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
4270
+ `INSERT INTO ${this.#t("messages")} (id, chatId, parentId, name, type, data, createdAt)
4168
4271
  VALUES ($1, $2, $3, $4, $5, $6, $7)
4169
4272
  ON CONFLICT(id) DO UPDATE SET
4170
4273
  name = EXCLUDED.name,
@@ -4182,7 +4285,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4182
4285
  );
4183
4286
  const content = typeof message2.data === "string" ? message2.data : JSON.stringify(message2.data);
4184
4287
  await client.query(
4185
- `INSERT INTO messages_fts (messageId, chatId, name, content)
4288
+ `INSERT INTO ${this.#t("messages_fts")} (messageId, chatId, name, content)
4186
4289
  VALUES ($1, $2, $3, $4)
4187
4290
  ON CONFLICT(messageId) DO UPDATE SET
4188
4291
  chatId = EXCLUDED.chatId,
@@ -4193,7 +4296,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4193
4296
  });
4194
4297
  }
4195
4298
  async getMessage(messageId) {
4196
- const rows = await this.#query("SELECT * FROM messages WHERE id = $1", [messageId]);
4299
+ const rows = await this.#query(`SELECT * FROM ${this.#t("messages")} WHERE id = $1`, [messageId]);
4197
4300
  if (rows.length === 0) {
4198
4301
  return void 0;
4199
4302
  }
@@ -4211,9 +4314,9 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4211
4314
  async getMessageChain(headId) {
4212
4315
  const rows = await this.#query(
4213
4316
  `WITH RECURSIVE chain AS (
4214
- SELECT *, 0 as depth FROM messages WHERE id = $1
4317
+ SELECT *, 0 as depth FROM ${this.#t("messages")} WHERE id = $1
4215
4318
  UNION ALL
4216
- SELECT m.*, c.depth + 1 FROM messages m
4319
+ SELECT m.*, c.depth + 1 FROM ${this.#t("messages")} m
4217
4320
  INNER JOIN chain c ON m.id = c.parentId
4218
4321
  WHERE c.depth < 10000
4219
4322
  )
@@ -4233,7 +4336,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4233
4336
  }
4234
4337
  async hasChildren(messageId) {
4235
4338
  const rows = await this.#query(
4236
- "SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = $1) as exists",
4339
+ `SELECT EXISTS(SELECT 1 FROM ${this.#t("messages")} WHERE parentId = $1) as exists`,
4237
4340
  [messageId]
4238
4341
  );
4239
4342
  return rows[0].exists;
@@ -4254,7 +4357,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4254
4357
  // ==========================================================================
4255
4358
  async createBranch(branch) {
4256
4359
  await this.#query(
4257
- `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
4360
+ `INSERT INTO ${this.#t("branches")} (id, chatId, name, headMessageId, isActive, createdAt)
4258
4361
  VALUES ($1, $2, $3, $4, $5, $6)`,
4259
4362
  [
4260
4363
  branch.id,
@@ -4267,7 +4370,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4267
4370
  );
4268
4371
  }
4269
4372
  async getBranch(chatId, name) {
4270
- const rows = await this.#query("SELECT * FROM branches WHERE chatId = $1 AND name = $2", [
4373
+ const rows = await this.#query(`SELECT * FROM ${this.#t("branches")} WHERE chatId = $1 AND name = $2`, [
4271
4374
  chatId,
4272
4375
  name
4273
4376
  ]);
@@ -4285,9 +4388,10 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4285
4388
  };
4286
4389
  }
4287
4390
  async getActiveBranch(chatId) {
4288
- const rows = await this.#query("SELECT * FROM branches WHERE chatId = $1 AND isActive = TRUE", [
4289
- chatId
4290
- ]);
4391
+ const rows = await this.#query(
4392
+ `SELECT * FROM ${this.#t("branches")} WHERE chatId = $1 AND isActive = TRUE`,
4393
+ [chatId]
4394
+ );
4291
4395
  if (rows.length === 0) {
4292
4396
  return void 0;
4293
4397
  }
@@ -4304,19 +4408,20 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4304
4408
  async setActiveBranch(chatId, branchId) {
4305
4409
  await this.#useTransaction(async (client) => {
4306
4410
  await client.query(
4307
- "UPDATE branches SET isActive = FALSE WHERE chatId = $1",
4411
+ `UPDATE ${this.#t("branches")} SET isActive = FALSE WHERE chatId = $1`,
4308
4412
  [chatId]
4309
4413
  );
4310
- await client.query("UPDATE branches SET isActive = TRUE WHERE id = $1", [
4311
- branchId
4312
- ]);
4414
+ await client.query(
4415
+ `UPDATE ${this.#t("branches")} SET isActive = TRUE WHERE id = $1`,
4416
+ [branchId]
4417
+ );
4313
4418
  });
4314
4419
  }
4315
4420
  async updateBranchHead(branchId, messageId) {
4316
- await this.#query("UPDATE branches SET headMessageId = $1 WHERE id = $2", [
4317
- messageId,
4318
- branchId
4319
- ]);
4421
+ await this.#query(
4422
+ `UPDATE ${this.#t("branches")} SET headMessageId = $1 WHERE id = $2`,
4423
+ [messageId, branchId]
4424
+ );
4320
4425
  }
4321
4426
  async listBranches(chatId) {
4322
4427
  const branches = await this.#query(
@@ -4326,7 +4431,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4326
4431
  headMessageId,
4327
4432
  isActive,
4328
4433
  createdAt
4329
- FROM branches
4434
+ FROM ${this.#t("branches")}
4330
4435
  WHERE chatId = $1
4331
4436
  ORDER BY createdAt ASC`,
4332
4437
  [chatId]
@@ -4337,9 +4442,9 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4337
4442
  if (branch.headmessageid) {
4338
4443
  const countRows = await this.#query(
4339
4444
  `WITH RECURSIVE chain AS (
4340
- SELECT id, parentId FROM messages WHERE id = $1
4445
+ SELECT id, parentId FROM ${this.#t("messages")} WHERE id = $1
4341
4446
  UNION ALL
4342
- SELECT m.id, m.parentId FROM messages m
4447
+ SELECT m.id, m.parentId FROM ${this.#t("messages")} m
4343
4448
  INNER JOIN chain c ON m.id = c.parentId
4344
4449
  )
4345
4450
  SELECT COUNT(*) as count FROM chain`,
@@ -4363,7 +4468,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4363
4468
  // ==========================================================================
4364
4469
  async createCheckpoint(checkpoint) {
4365
4470
  await this.#query(
4366
- `INSERT INTO checkpoints (id, chatId, name, messageId, createdAt)
4471
+ `INSERT INTO ${this.#t("checkpoints")} (id, chatId, name, messageId, createdAt)
4367
4472
  VALUES ($1, $2, $3, $4, $5)
4368
4473
  ON CONFLICT(chatId, name) DO UPDATE SET
4369
4474
  messageId = EXCLUDED.messageId,
@@ -4378,10 +4483,10 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4378
4483
  );
4379
4484
  }
4380
4485
  async getCheckpoint(chatId, name) {
4381
- const rows = await this.#query("SELECT * FROM checkpoints WHERE chatId = $1 AND name = $2", [
4382
- chatId,
4383
- name
4384
- ]);
4486
+ const rows = await this.#query(
4487
+ `SELECT * FROM ${this.#t("checkpoints")} WHERE chatId = $1 AND name = $2`,
4488
+ [chatId, name]
4489
+ );
4385
4490
  if (rows.length === 0) {
4386
4491
  return void 0;
4387
4492
  }
@@ -4397,7 +4502,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4397
4502
  async listCheckpoints(chatId) {
4398
4503
  const rows = await this.#query(
4399
4504
  `SELECT id, name, messageId, createdAt
4400
- FROM checkpoints
4505
+ FROM ${this.#t("checkpoints")}
4401
4506
  WHERE chatId = $1
4402
4507
  ORDER BY createdAt DESC`,
4403
4508
  [chatId]
@@ -4411,7 +4516,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4411
4516
  }
4412
4517
  async deleteCheckpoint(chatId, name) {
4413
4518
  await this.#query(
4414
- "DELETE FROM checkpoints WHERE chatId = $1 AND name = $2",
4519
+ `DELETE FROM ${this.#t("checkpoints")} WHERE chatId = $1 AND name = $2`,
4415
4520
  [chatId, name]
4416
4521
  );
4417
4522
  }
@@ -4433,8 +4538,8 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4433
4538
  ts_rank(fts.content_vector, plainto_tsquery('english', $2)) as rank,
4434
4539
  ts_headline('english', fts.content, plainto_tsquery('english', $2),
4435
4540
  'StartSel=<mark>, StopSel=</mark>, MaxWords=32, MinWords=5, MaxFragments=1') as snippet
4436
- FROM messages_fts fts
4437
- JOIN messages m ON m.id = fts.messageId
4541
+ FROM ${this.#t("messages_fts")} fts
4542
+ JOIN ${this.#t("messages")} m ON m.id = fts.messageId
4438
4543
  WHERE fts.content_vector @@ plainto_tsquery('english', $2)
4439
4544
  AND fts.chatId = $1
4440
4545
  `;
@@ -4468,7 +4573,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4468
4573
  async getGraph(chatId) {
4469
4574
  const messageRows = await this.#query(
4470
4575
  `SELECT id, parentId, name, data, createdAt
4471
- FROM messages
4576
+ FROM ${this.#t("messages")}
4472
4577
  WHERE chatId = $1
4473
4578
  ORDER BY createdAt ASC`,
4474
4579
  [chatId]
@@ -4486,7 +4591,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4486
4591
  });
4487
4592
  const branchRows = await this.#query(
4488
4593
  `SELECT name, headMessageId, isActive
4489
- FROM branches
4594
+ FROM ${this.#t("branches")}
4490
4595
  WHERE chatId = $1
4491
4596
  ORDER BY createdAt ASC`,
4492
4597
  [chatId]
@@ -4498,7 +4603,7 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4498
4603
  }));
4499
4604
  const checkpointRows = await this.#query(
4500
4605
  `SELECT name, messageId
4501
- FROM checkpoints
4606
+ FROM ${this.#t("checkpoints")}
4502
4607
  WHERE chatId = $1
4503
4608
  ORDER BY createdAt ASC`,
4504
4609
  [chatId]
@@ -4520,12 +4625,11 @@ var PostgresContextStore = class _PostgresContextStore extends ContextStore {
4520
4625
  import { createRequire as createRequire2 } from "node:module";
4521
4626
 
4522
4627
  // packages/context/src/lib/store/ddl.sqlserver.ts
4523
- function storeDDL(schema) {
4524
- const s = schema;
4628
+ function storeDDL2(schema) {
4525
4629
  return `
4526
- IF OBJECT_ID('[${s}].[chats]', 'U') IS NULL
4630
+ IF OBJECT_ID('[${schema}].[chats]', 'U') IS NULL
4527
4631
  BEGIN
4528
- CREATE TABLE [${s}].[chats] (
4632
+ CREATE TABLE [${schema}].[chats] (
4529
4633
  id NVARCHAR(255) PRIMARY KEY,
4530
4634
  userId NVARCHAR(255) NOT NULL,
4531
4635
  title NVARCHAR(MAX),
@@ -4535,15 +4639,15 @@ BEGIN
4535
4639
  );
4536
4640
  END;
4537
4641
 
4538
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_chats_updatedAt' AND object_id = OBJECT_ID('[${s}].[chats]'))
4539
- CREATE INDEX [idx_${s}_chats_updatedAt] ON [${s}].[chats](updatedAt);
4642
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_chats_updatedAt' AND object_id = OBJECT_ID('[${schema}].[chats]'))
4643
+ CREATE INDEX [idx_${schema}_chats_updatedAt] ON [${schema}].[chats](updatedAt);
4540
4644
 
4541
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_chats_userId' AND object_id = OBJECT_ID('[${s}].[chats]'))
4542
- CREATE INDEX [idx_${s}_chats_userId] ON [${s}].[chats](userId);
4645
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_chats_userId' AND object_id = OBJECT_ID('[${schema}].[chats]'))
4646
+ CREATE INDEX [idx_${schema}_chats_userId] ON [${schema}].[chats](userId);
4543
4647
 
4544
- IF OBJECT_ID('[${s}].[messages]', 'U') IS NULL
4648
+ IF OBJECT_ID('[${schema}].[messages]', 'U') IS NULL
4545
4649
  BEGIN
4546
- CREATE TABLE [${s}].[messages] (
4650
+ CREATE TABLE [${schema}].[messages] (
4547
4651
  id NVARCHAR(255) PRIMARY KEY,
4548
4652
  chatId NVARCHAR(255) NOT NULL,
4549
4653
  parentId NVARCHAR(255),
@@ -4551,85 +4655,85 @@ BEGIN
4551
4655
  type NVARCHAR(255),
4552
4656
  data NVARCHAR(MAX) NOT NULL,
4553
4657
  createdAt BIGINT NOT NULL,
4554
- FOREIGN KEY (chatId) REFERENCES [${s}].[chats](id) ON DELETE CASCADE,
4555
- FOREIGN KEY (parentId) REFERENCES [${s}].[messages](id)
4658
+ FOREIGN KEY (chatId) REFERENCES [${schema}].[chats](id) ON DELETE CASCADE,
4659
+ FOREIGN KEY (parentId) REFERENCES [${schema}].[messages](id)
4556
4660
  );
4557
4661
  END;
4558
4662
 
4559
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_messages_chatId' AND object_id = OBJECT_ID('[${s}].[messages]'))
4560
- CREATE INDEX [idx_${s}_messages_chatId] ON [${s}].[messages](chatId);
4663
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_messages_chatId' AND object_id = OBJECT_ID('[${schema}].[messages]'))
4664
+ CREATE INDEX [idx_${schema}_messages_chatId] ON [${schema}].[messages](chatId);
4561
4665
 
4562
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_messages_parentId' AND object_id = OBJECT_ID('[${s}].[messages]'))
4563
- CREATE INDEX [idx_${s}_messages_parentId] ON [${s}].[messages](parentId);
4666
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_messages_parentId' AND object_id = OBJECT_ID('[${schema}].[messages]'))
4667
+ CREATE INDEX [idx_${schema}_messages_parentId] ON [${schema}].[messages](parentId);
4564
4668
 
4565
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_messages_chatId_parentId' AND object_id = OBJECT_ID('[${s}].[messages]'))
4566
- CREATE INDEX [idx_${s}_messages_chatId_parentId] ON [${s}].[messages](chatId, parentId);
4669
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_messages_chatId_parentId' AND object_id = OBJECT_ID('[${schema}].[messages]'))
4670
+ CREATE INDEX [idx_${schema}_messages_chatId_parentId] ON [${schema}].[messages](chatId, parentId);
4567
4671
 
4568
- IF OBJECT_ID('[${s}].[branches]', 'U') IS NULL
4672
+ IF OBJECT_ID('[${schema}].[branches]', 'U') IS NULL
4569
4673
  BEGIN
4570
- CREATE TABLE [${s}].[branches] (
4674
+ CREATE TABLE [${schema}].[branches] (
4571
4675
  id NVARCHAR(255) PRIMARY KEY,
4572
4676
  chatId NVARCHAR(255) NOT NULL,
4573
4677
  name NVARCHAR(255) NOT NULL,
4574
4678
  headMessageId NVARCHAR(255),
4575
4679
  isActive BIT NOT NULL DEFAULT 0,
4576
4680
  createdAt BIGINT NOT NULL,
4577
- FOREIGN KEY (chatId) REFERENCES [${s}].[chats](id) ON DELETE CASCADE,
4578
- FOREIGN KEY (headMessageId) REFERENCES [${s}].[messages](id),
4579
- CONSTRAINT [UQ_${s}_branches_chatId_name] UNIQUE(chatId, name)
4681
+ FOREIGN KEY (chatId) REFERENCES [${schema}].[chats](id) ON DELETE CASCADE,
4682
+ FOREIGN KEY (headMessageId) REFERENCES [${schema}].[messages](id),
4683
+ CONSTRAINT [UQ_${schema}_branches_chatId_name] UNIQUE(chatId, name)
4580
4684
  );
4581
4685
  END;
4582
4686
 
4583
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_branches_chatId' AND object_id = OBJECT_ID('[${s}].[branches]'))
4584
- CREATE INDEX [idx_${s}_branches_chatId] ON [${s}].[branches](chatId);
4687
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_branches_chatId' AND object_id = OBJECT_ID('[${schema}].[branches]'))
4688
+ CREATE INDEX [idx_${schema}_branches_chatId] ON [${schema}].[branches](chatId);
4585
4689
 
4586
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_branches_chatId_isActive' AND object_id = OBJECT_ID('[${s}].[branches]'))
4587
- CREATE INDEX [idx_${s}_branches_chatId_isActive] ON [${s}].[branches](chatId, isActive);
4690
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_branches_chatId_isActive' AND object_id = OBJECT_ID('[${schema}].[branches]'))
4691
+ CREATE INDEX [idx_${schema}_branches_chatId_isActive] ON [${schema}].[branches](chatId, isActive);
4588
4692
 
4589
- IF OBJECT_ID('[${s}].[checkpoints]', 'U') IS NULL
4693
+ IF OBJECT_ID('[${schema}].[checkpoints]', 'U') IS NULL
4590
4694
  BEGIN
4591
- CREATE TABLE [${s}].[checkpoints] (
4695
+ CREATE TABLE [${schema}].[checkpoints] (
4592
4696
  id NVARCHAR(255) PRIMARY KEY,
4593
4697
  chatId NVARCHAR(255) NOT NULL,
4594
4698
  name NVARCHAR(255) NOT NULL,
4595
4699
  messageId NVARCHAR(255) NOT NULL,
4596
4700
  createdAt BIGINT NOT NULL,
4597
- FOREIGN KEY (chatId) REFERENCES [${s}].[chats](id) ON DELETE CASCADE,
4598
- FOREIGN KEY (messageId) REFERENCES [${s}].[messages](id),
4599
- CONSTRAINT [UQ_${s}_checkpoints_chatId_name] UNIQUE(chatId, name)
4701
+ FOREIGN KEY (chatId) REFERENCES [${schema}].[chats](id) ON DELETE CASCADE,
4702
+ FOREIGN KEY (messageId) REFERENCES [${schema}].[messages](id),
4703
+ CONSTRAINT [UQ_${schema}_checkpoints_chatId_name] UNIQUE(chatId, name)
4600
4704
  );
4601
4705
  END;
4602
4706
 
4603
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_checkpoints_chatId' AND object_id = OBJECT_ID('[${s}].[checkpoints]'))
4604
- CREATE INDEX [idx_${s}_checkpoints_chatId] ON [${s}].[checkpoints](chatId);
4707
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_checkpoints_chatId' AND object_id = OBJECT_ID('[${schema}].[checkpoints]'))
4708
+ CREATE INDEX [idx_${schema}_checkpoints_chatId] ON [${schema}].[checkpoints](chatId);
4605
4709
 
4606
- IF OBJECT_ID('[${s}].[messages_fts]', 'U') IS NULL
4710
+ IF OBJECT_ID('[${schema}].[messages_fts]', 'U') IS NULL
4607
4711
  BEGIN
4608
- CREATE TABLE [${s}].[messages_fts] (
4712
+ CREATE TABLE [${schema}].[messages_fts] (
4609
4713
  messageId NVARCHAR(255) NOT NULL,
4610
4714
  chatId NVARCHAR(255) NOT NULL,
4611
4715
  name NVARCHAR(255) NOT NULL,
4612
4716
  content NVARCHAR(MAX) NOT NULL,
4613
- CONSTRAINT [PK_${s}_messages_fts] PRIMARY KEY (messageId),
4614
- FOREIGN KEY (messageId) REFERENCES [${s}].[messages](id) ON DELETE CASCADE
4717
+ CONSTRAINT [PK_${schema}_messages_fts] PRIMARY KEY (messageId),
4718
+ FOREIGN KEY (messageId) REFERENCES [${schema}].[messages](id) ON DELETE CASCADE
4615
4719
  );
4616
4720
  END;
4617
4721
 
4618
- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${s}_messages_fts_chatId' AND object_id = OBJECT_ID('[${s}].[messages_fts]'))
4619
- CREATE INDEX [idx_${s}_messages_fts_chatId] ON [${s}].[messages_fts](chatId);
4722
+ IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_${schema}_messages_fts_chatId' AND object_id = OBJECT_ID('[${schema}].[messages_fts]'))
4723
+ CREATE INDEX [idx_${schema}_messages_fts_chatId] ON [${schema}].[messages_fts](chatId);
4620
4724
 
4621
4725
  GO
4622
4726
 
4623
4727
  IF SERVERPROPERTY('IsFullTextInstalled') = 1
4624
4728
  BEGIN
4625
- IF NOT EXISTS (SELECT * FROM sys.fulltext_catalogs WHERE name = '${s}_context_store_catalog')
4626
- CREATE FULLTEXT CATALOG [${s}_context_store_catalog];
4729
+ IF NOT EXISTS (SELECT * FROM sys.fulltext_catalogs WHERE name = '${schema}_context_store_catalog')
4730
+ CREATE FULLTEXT CATALOG [${schema}_context_store_catalog];
4627
4731
 
4628
- IF NOT EXISTS (SELECT * FROM sys.fulltext_indexes WHERE object_id = OBJECT_ID('[${s}].[messages_fts]'))
4732
+ IF NOT EXISTS (SELECT * FROM sys.fulltext_indexes WHERE object_id = OBJECT_ID('[${schema}].[messages_fts]'))
4629
4733
  BEGIN
4630
- CREATE FULLTEXT INDEX ON [${s}].[messages_fts](content)
4631
- KEY INDEX [PK_${s}_messages_fts]
4632
- ON [${s}_context_store_catalog]
4734
+ CREATE FULLTEXT INDEX ON [${schema}].[messages_fts](content)
4735
+ KEY INDEX [PK_${schema}_messages_fts]
4736
+ ON [${schema}_context_store_catalog]
4633
4737
  WITH STOPLIST = SYSTEM;
4634
4738
  END;
4635
4739
  END;
@@ -4684,7 +4788,7 @@ var SqlServerContextStore = class _SqlServerContextStore extends ContextStore {
4684
4788
  EXEC sp_executesql @sql;
4685
4789
  END
4686
4790
  `);
4687
- const ddl = storeDDL(this.#schema);
4791
+ const ddl = storeDDL2(this.#schema);
4688
4792
  const batches = ddl.split(/\bGO\b/i).filter((b) => b.trim());
4689
4793
  for (const batch of batches) {
4690
4794
  if (batch.trim()) {
@@ -5469,6 +5573,43 @@ var SqliteStreamStore = class extends StreamStore {
5469
5573
  stream.error
5470
5574
  );
5471
5575
  }
5576
+ async upsertStream(stream) {
5577
+ const row = this.#stmt(
5578
+ `INSERT INTO streams (id, status, createdAt, startedAt, finishedAt, cancelRequestedAt, error)
5579
+ VALUES (?, ?, ?, ?, ?, ?, ?)
5580
+ ON CONFLICT(id) DO NOTHING
5581
+ RETURNING *`
5582
+ ).get(
5583
+ stream.id,
5584
+ stream.status,
5585
+ stream.createdAt,
5586
+ stream.startedAt,
5587
+ stream.finishedAt,
5588
+ stream.cancelRequestedAt,
5589
+ stream.error
5590
+ );
5591
+ if (row) {
5592
+ return {
5593
+ stream: {
5594
+ id: row.id,
5595
+ status: row.status,
5596
+ createdAt: row.createdAt,
5597
+ startedAt: row.startedAt,
5598
+ finishedAt: row.finishedAt,
5599
+ cancelRequestedAt: row.cancelRequestedAt,
5600
+ error: row.error
5601
+ },
5602
+ created: true
5603
+ };
5604
+ }
5605
+ const existing = await this.getStream(stream.id);
5606
+ if (!existing) {
5607
+ throw new Error(
5608
+ `Stream "${stream.id}" disappeared between upsert and fetch`
5609
+ );
5610
+ }
5611
+ return { stream: existing, created: false };
5612
+ }
5472
5613
  async getStream(streamId) {
5473
5614
  const row = this.#stmt("SELECT * FROM streams WHERE id = ?").get(
5474
5615
  streamId
@@ -5575,7 +5716,7 @@ var StreamManager = class {
5575
5716
  return this.#store;
5576
5717
  }
5577
5718
  async register(streamId) {
5578
- await this.#store.createStream({
5719
+ return this.#store.upsertStream({
5579
5720
  id: streamId,
5580
5721
  status: "queued",
5581
5722
  createdAt: Date.now(),