aegra-hono 0.20.0 → 0.21.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/cli.js CHANGED
@@ -51,7 +51,7 @@ var __callDispose = (stack, error, hasError) => {
51
51
 
52
52
  // src/config/settings.ts
53
53
  import { z } from "zod";
54
- var DEFAULT_VERSION = "0.20.0", booleanFromEnv, positiveIntFromEnv = (fallback) => z.coerce.number().int().positive().default(fallback), environmentShape, environmentVariableNames, environmentSchema, raw, settings;
54
+ var DEFAULT_VERSION = "0.21.0", booleanFromEnv, positiveIntFromEnv = (fallback) => z.coerce.number().int().positive().default(fallback), environmentShape, environmentVariableNames, environmentSchema, raw, settings;
55
55
  var init_settings = __esm(() => {
56
56
  booleanFromEnv = z.stringbool().default(false);
57
57
  environmentShape = {
@@ -135,160 +135,6 @@ var init_settings = __esm(() => {
135
135
  };
136
136
  });
137
137
 
138
- // src/core/schema.ts
139
- var exports_schema = {};
140
- __export(exports_schema, {
141
- threads: () => threads,
142
- threadTtl: () => threadTtl,
143
- storeItems: () => storeItems,
144
- runs: () => runs,
145
- migrations: () => migrations,
146
- crons: () => crons,
147
- assistants: () => assistants,
148
- assistantVersions: () => assistantVersions
149
- });
150
- import { sql } from "drizzle-orm";
151
- import {
152
- boolean,
153
- doublePrecision,
154
- index,
155
- integer,
156
- jsonb,
157
- pgTable,
158
- primaryKey,
159
- text,
160
- timestamp,
161
- unique,
162
- uniqueIndex
163
- } from "drizzle-orm/pg-core";
164
- var timestamps, migrations, assistants, assistantVersions, threads, runs, crons, storeItems, threadTtl;
165
- var init_schema = __esm(() => {
166
- timestamps = {
167
- created_at: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
168
- updated_at: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
169
- };
170
- migrations = pgTable("aegra_migrations", {
171
- checksum: text("checksum"),
172
- version: integer("version").primaryKey(),
173
- applied_at: timestamp("applied_at", { withTimezone: true }).notNull().defaultNow()
174
- });
175
- assistants = pgTable("assistant", {
176
- assistant_id: text("assistant_id").primaryKey().default(sql`gen_random_uuid()::text`),
177
- name: text("name").notNull(),
178
- description: text("description"),
179
- graph_id: text("graph_id").notNull(),
180
- config: jsonb("config").$type().notNull().default({}),
181
- context: jsonb("context").$type().notNull().default({}),
182
- user_id: text("user_id").notNull(),
183
- version: integer("version").notNull().default(1),
184
- metadata: jsonb("metadata").$type().notNull().default({}),
185
- ...timestamps
186
- }, (table) => [
187
- index("idx_assistant_user").on(table.user_id),
188
- unique("assistant_user_id_unique").on(table.user_id, table.assistant_id),
189
- uniqueIndex("idx_assistant_user_graph_config").on(table.user_id, table.graph_id, sql`md5(${table.config}::text)`),
190
- index("idx_assistant_metadata_gin").using("gin", sql`${table.metadata} jsonb_path_ops`)
191
- ]);
192
- assistantVersions = pgTable("assistant_versions", {
193
- assistant_id: text("assistant_id").notNull().references(() => assistants.assistant_id, { onDelete: "cascade" }),
194
- version: integer("version").notNull(),
195
- graph_id: text("graph_id").notNull(),
196
- config: jsonb("config").$type(),
197
- context: jsonb("context").$type(),
198
- metadata: jsonb("metadata").$type().notNull().default({}),
199
- name: text("name"),
200
- description: text("description"),
201
- created_at: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
202
- }, (table) => [primaryKey({ columns: [table.assistant_id, table.version] })]);
203
- threads = pgTable("thread", {
204
- thread_id: text("thread_id").primaryKey(),
205
- status: text("status").notNull().default("idle"),
206
- metadata_json: jsonb("metadata_json").$type().notNull().default({}),
207
- user_id: text("user_id").notNull(),
208
- ...timestamps
209
- }, (table) => [
210
- index("idx_thread_user").on(table.user_id),
211
- index("idx_thread_metadata_gin").using("gin", sql`${table.metadata_json} jsonb_path_ops`)
212
- ]);
213
- runs = pgTable("runs", {
214
- run_id: text("run_id").primaryKey().default(sql`gen_random_uuid()::text`),
215
- thread_id: text("thread_id").notNull().references(() => threads.thread_id, { onDelete: "cascade" }),
216
- assistant_id: text("assistant_id").references(() => assistants.assistant_id, {
217
- onDelete: "cascade"
218
- }),
219
- status: text("status").notNull().default("pending"),
220
- input: jsonb("input").$type(),
221
- config: jsonb("config").$type(),
222
- context: jsonb("context").$type(),
223
- output: jsonb("output").$type(),
224
- error_message: text("error_message"),
225
- user_id: text("user_id").notNull(),
226
- execution_params: jsonb("execution_params").$type(),
227
- claimed_by: text("claimed_by"),
228
- lease_expires_at: timestamp("lease_expires_at", { withTimezone: true }),
229
- ...timestamps
230
- }, (table) => [
231
- index("idx_runs_thread_id").on(table.thread_id),
232
- index("idx_runs_status").on(table.status),
233
- index("idx_runs_user").on(table.user_id),
234
- index("idx_runs_assistant_id").on(table.assistant_id),
235
- index("idx_runs_created_at").on(table.created_at),
236
- index("idx_runs_lease_reaper").on(table.status, table.lease_expires_at).where(sql`${table.status} = 'running'`)
237
- ]);
238
- crons = pgTable("crons", {
239
- cron_id: text("cron_id").primaryKey().default(sql`gen_random_uuid()::text`),
240
- assistant_id: text("assistant_id").notNull().references(() => assistants.assistant_id, { onDelete: "cascade" }),
241
- thread_id: text("thread_id").references(() => threads.thread_id, { onDelete: "cascade" }),
242
- user_id: text("user_id").notNull(),
243
- schedule: text("schedule").notNull(),
244
- payload: jsonb("payload").$type().notNull().default({}),
245
- metadata: jsonb("metadata").$type().notNull().default({}),
246
- on_run_completed: text("on_run_completed"),
247
- enabled: boolean("enabled").notNull().default(true),
248
- end_time: timestamp("end_time", { withTimezone: true }),
249
- next_run_date: timestamp("next_run_date", { withTimezone: true }),
250
- claimed_until: timestamp("claimed_until", { withTimezone: true }),
251
- ...timestamps
252
- }, (table) => [
253
- index("idx_cron_user").on(table.user_id),
254
- index("idx_cron_assistant_id").on(table.assistant_id),
255
- index("idx_cron_thread_id").on(table.thread_id),
256
- index("idx_cron_next_run").on(table.enabled, table.next_run_date)
257
- ]);
258
- storeItems = pgTable("store_items", {
259
- user_id: text("user_id").notNull(),
260
- namespace: text("namespace").array().notNull(),
261
- key: text("key").notNull(),
262
- value: jsonb("value").$type().notNull(),
263
- ...timestamps
264
- }, (table) => [primaryKey({ columns: [table.namespace, table.key] })]);
265
- threadTtl = pgTable("thread_ttl", {
266
- thread_id: text("thread_id").primaryKey().references(() => threads.thread_id, { onDelete: "cascade" }),
267
- strategy: text("strategy").notNull().default("delete"),
268
- ttl_minutes: doublePrecision("ttl_minutes").notNull(),
269
- created_at: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
270
- expires_at: timestamp("expires_at", { withTimezone: true }).notNull()
271
- }, (table) => [index("idx_thread_ttl_expires_at").on(table.expires_at)]);
272
- });
273
-
274
- // src/core/langgraph-database.ts
275
- import pg from "pg";
276
- import { drizzle } from "drizzle-orm/node-postgres";
277
- async function closeLangGraphDatabase() {
278
- await langgraphPool.end();
279
- }
280
- var langgraphPool, storeDb;
281
- var init_langgraph_database = __esm(() => {
282
- init_settings();
283
- init_schema();
284
- langgraphPool = new pg.Pool({
285
- connectionString: settings.DATABASE_URL,
286
- min: settings.LANGGRAPH_POOL_MIN_SIZE,
287
- max: settings.LANGGRAPH_POOL_MAX_SIZE
288
- });
289
- storeDb = drizzle({ client: langgraphPool, schema: exports_schema });
290
- });
291
-
292
138
  // src/config/project.ts
293
139
  import { readFile } from "fs/promises";
294
140
  import { dirname, resolve } from "path";
@@ -343,6 +189,232 @@ var init_project = __esm(() => {
343
189
  });
344
190
  });
345
191
 
192
+ // src/core/optional-dependencies.ts
193
+ import { createRequire } from "module";
194
+ function installHint(specifier, feature) {
195
+ return `${feature} is enabled but the optional '${specifier}' package is not installed. Install it with: bun add ${specifier}`;
196
+ }
197
+ function isMissingModule(error, specifier) {
198
+ const code = error?.code;
199
+ if (typeof code === "string" && code.includes("MODULE_NOT_FOUND"))
200
+ return true;
201
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED")
202
+ return true;
203
+ return error instanceof Error && error.message.includes(`'${specifier}'`);
204
+ }
205
+ async function optionalImport(specifier, feature) {
206
+ try {
207
+ return await import(specifier);
208
+ } catch (error) {
209
+ if (isMissingModule(error, specifier))
210
+ throw new Error(installHint(specifier, feature), { cause: error });
211
+ throw error;
212
+ }
213
+ }
214
+ function optionalRequire(specifier, feature) {
215
+ try {
216
+ return require2(specifier);
217
+ } catch (error) {
218
+ if (isMissingModule(error, specifier))
219
+ throw new Error(installHint(specifier, feature), { cause: error });
220
+ throw error;
221
+ }
222
+ }
223
+ var require2;
224
+ var init_optional_dependencies = __esm(() => {
225
+ require2 = createRequire(import.meta.url);
226
+ });
227
+
228
+ // src/core/langgraph-database.ts
229
+ import { AsyncLocalStorage } from "async_hooks";
230
+ import pg from "pg";
231
+ import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres/store";
232
+ function encodeNamespace(namespace) {
233
+ return namespace.map((segment) => `${Buffer.from(segment, "utf8").toString("hex")}g`);
234
+ }
235
+ function decodeNamespace(namespace) {
236
+ return namespace.map((segment) => {
237
+ if (!/^(?:[0-9a-f]{2})*g$/.test(segment))
238
+ throw new Error("Invalid encoded Store namespace");
239
+ return Buffer.from(segment.slice(0, -1), "hex").toString("utf8");
240
+ });
241
+ }
242
+ async function withStoreTransaction(operation) {
243
+ const current = transactionClient.getStore();
244
+ if (current)
245
+ return operation(current);
246
+ const client = await langgraphPool.connect();
247
+ try {
248
+ await client.query("BEGIN");
249
+ const result = await transactionClient.run(client, () => operation(client));
250
+ await client.query("COMMIT");
251
+ return result;
252
+ } catch (error) {
253
+ await client.query("ROLLBACK");
254
+ throw error;
255
+ } finally {
256
+ client.release();
257
+ }
258
+ }
259
+ async function createOfficialStore(index) {
260
+ const store = new PostgresStore({
261
+ connectionOptions: { connectionString: settings.DATABASE_URL },
262
+ schema: "aegra_store",
263
+ ensureTables: false,
264
+ ...index ? { index } : {}
265
+ });
266
+ const core = store.core;
267
+ if (!core?.pool || typeof core.withClient !== "function")
268
+ throw new Error("Unsupported PostgresStore internals; verify the pinned SDK compatibility bridge");
269
+ await core.pool.end();
270
+ core.pool = new Proxy(langgraphPool, {
271
+ get(target, property) {
272
+ if (property === "end")
273
+ return async () => {};
274
+ if (property === "connect")
275
+ return async () => {
276
+ const client = transactionClient.getStore();
277
+ if (!client)
278
+ return target.connect();
279
+ return new Proxy(client, {
280
+ get(connection, member) {
281
+ if (member === "release")
282
+ return () => {};
283
+ const value2 = Reflect.get(connection, member);
284
+ return typeof value2 === "function" ? value2.bind(connection) : value2;
285
+ }
286
+ });
287
+ };
288
+ const value = Reflect.get(target, property);
289
+ return typeof value === "function" ? value.bind(target) : value;
290
+ }
291
+ });
292
+ core.withClient = withStoreTransaction;
293
+ return store;
294
+ }
295
+ async function createEmbedder(provider, model, dims) {
296
+ if (provider === "openai") {
297
+ const { OpenAIEmbeddings } = await optionalImport("@langchain/openai", "the 'openai' store embedding provider");
298
+ return new OpenAIEmbeddings({ model, dimensions: dims });
299
+ }
300
+ if (provider === "bedrock") {
301
+ const { BedrockEmbeddings } = await optionalImport("@langchain/aws", "the 'bedrock' store embedding provider");
302
+ return new BedrockEmbeddings({ model, dimensions: dims });
303
+ }
304
+ if (provider === "cohere") {
305
+ const { CohereEmbeddings } = await optionalImport("@langchain/cohere", "the 'cohere' store embedding provider");
306
+ return new CohereEmbeddings({ model });
307
+ }
308
+ throw new Error(`Unsupported embedding provider '${provider}'`);
309
+ }
310
+ async function storeIndex() {
311
+ const index = (await loadConfig()).store?.index;
312
+ if (!index)
313
+ return;
314
+ const separator = index.embed.indexOf(":");
315
+ if (separator < 1 || separator === index.embed.length - 1)
316
+ throw new Error("store.index.embed must use provider:model format");
317
+ const model = await createEmbedder(index.embed.slice(0, separator), index.embed.slice(separator + 1), index.dims);
318
+ function validate(vectors, count) {
319
+ if (vectors.length !== count || vectors.some((vector) => vector.length !== index.dims || vector.some((number) => !Number.isFinite(number))))
320
+ throw new Error(`Embedding model returned invalid vectors; expected ${count} vectors of ${index.dims} dimensions`);
321
+ return vectors;
322
+ }
323
+ return {
324
+ dims: index.dims,
325
+ fields: index.fields ?? ["$"],
326
+ embed: {
327
+ embedDocuments: async (texts) => validate(await model.embedDocuments(texts), texts.length),
328
+ embedQuery: async (text) => validate([await model.embedQuery(text)], 1)[0]
329
+ }
330
+ };
331
+ }
332
+ async function migrateLegacyStore(client, legacySchema = "public", dims) {
333
+ if (!/^[a-z_][a-z0-9_]*$/.test(legacySchema))
334
+ throw new Error("Invalid migration schema");
335
+ const source = `"${legacySchema}"`;
336
+ const applied = await client.query(`SELECT 1 FROM ${source}.aegra_migrations WHERE version = 10001`);
337
+ if (applied.rowCount)
338
+ return;
339
+ await client.query(`LOCK TABLE ${source}.store_items IN SHARE MODE`);
340
+ const vectorTable = await client.query("SELECT to_regclass($1) AS name", [
341
+ `${legacySchema}.store_embeddings`
342
+ ]);
343
+ if (vectorTable.rows[0]?.name) {
344
+ await client.query(`LOCK TABLE ${source}.store_embeddings IN SHARE MODE`);
345
+ const dimensions = await client.query(`SELECT DISTINCT vector_dims(embedding) AS dims FROM ${source}.store_embeddings`);
346
+ if (dimensions.rows.length > 1 || dims && dimensions.rows.some((row) => row.dims !== dims))
347
+ throw new Error("Legacy Store embedding dimensions do not match store.index.dims; migration aborted without changing data");
348
+ if (!dims && dimensions.rows[0]) {
349
+ const setupStore = await createOfficialStore({
350
+ dims: dimensions.rows[0].dims,
351
+ embed: async () => {
352
+ throw new Error("Migration-only embedder");
353
+ }
354
+ });
355
+ try {
356
+ await setupStore.setup();
357
+ } finally {
358
+ await setupStore.stop();
359
+ }
360
+ }
361
+ }
362
+ const encoded = `(SELECT string_agg(encode(convert_to(part, 'UTF8'), 'hex') || 'g', ':' ORDER BY ordinal)
363
+ FROM unnest(namespace) WITH ORDINALITY AS labels(part, ordinal))`;
364
+ const collision = await client.query(`SELECT 1 FROM ${source}.store_items old
365
+ JOIN aegra_store.store target ON target.namespace_path = ${encoded} AND target.key = old.key LIMIT 1`);
366
+ if (collision.rowCount)
367
+ throw new Error("Official Store already contains legacy keys; migration aborted to avoid overwriting data");
368
+ await client.query(`INSERT INTO aegra_store.store(namespace_path, key, value, created_at, updated_at)
369
+ SELECT ${encoded}, key, value, created_at, updated_at FROM ${source}.store_items`);
370
+ if (vectorTable.rows[0]?.name) {
371
+ const count = await client.query(`SELECT count(*)::int AS count FROM ${source}.store_embeddings`);
372
+ if (count.rows[0].count)
373
+ await client.query(`INSERT INTO aegra_store.store_vectors(namespace_path, key, field_path, text_content, embedding)
374
+ SELECT ${encoded}, key, field_path, '', embedding FROM ${source}.store_embeddings`);
375
+ }
376
+ await client.query(`INSERT INTO ${source}.aegra_migrations(version, checksum) VALUES (10001, 'official-store-hexg-v1')`);
377
+ }
378
+ function getOfficialStore() {
379
+ storePromise ??= (async () => {
380
+ const index = await storeIndex();
381
+ const store = await createOfficialStore(index);
382
+ const lock = new pg.Client({ connectionString: settings.DATABASE_URL });
383
+ await lock.connect();
384
+ try {
385
+ await lock.query("SELECT pg_advisory_lock(1095067474)");
386
+ await store.setup();
387
+ await withStoreTransaction((client) => migrateLegacyStore(client, "public", index?.dims));
388
+ return store;
389
+ } catch (error) {
390
+ await store.stop();
391
+ throw error;
392
+ } finally {
393
+ await lock.end();
394
+ }
395
+ })();
396
+ return storePromise;
397
+ }
398
+ async function closeLangGraphDatabase() {
399
+ try {
400
+ await (await storePromise)?.stop();
401
+ } finally {
402
+ await langgraphPool.end();
403
+ }
404
+ }
405
+ var langgraphPool, transactionClient, storePromise;
406
+ var init_langgraph_database = __esm(() => {
407
+ init_settings();
408
+ init_project();
409
+ init_optional_dependencies();
410
+ langgraphPool = new pg.Pool({
411
+ connectionString: settings.DATABASE_URL,
412
+ min: settings.LANGGRAPH_POOL_MIN_SIZE,
413
+ max: settings.LANGGRAPH_POOL_MAX_SIZE
414
+ });
415
+ transactionClient = new AsyncLocalStorage;
416
+ });
417
+
346
418
  // src/core/logger.ts
347
419
  function startup(info) {
348
420
  if (production) {
@@ -398,14 +470,14 @@ function jsonValue(value) {
398
470
  return value;
399
471
  return { name: value.name, message: value.message, stack: value.stack };
400
472
  }
401
- function timestamp2(date = new Date) {
473
+ function timestamp(date = new Date) {
402
474
  const pad = (value, width = 2) => String(value).padStart(width, "0");
403
475
  const offset = -date.getTimezoneOffset();
404
476
  const sign = offset >= 0 ? "+" : "-";
405
477
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` + `T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}` + `${sign}${pad(Math.floor(Math.abs(offset) / 60))}:${pad(Math.abs(offset) % 60)}`;
406
478
  }
407
479
  function write(level, message, fields = {}) {
408
- const time = timestamp2();
480
+ const time = timestamp();
409
481
  let line;
410
482
  if (production) {
411
483
  line = JSON.stringify({
@@ -448,18 +520,147 @@ var init_logger = __esm(() => {
448
520
  };
449
521
  });
450
522
 
523
+ // src/core/schema.ts
524
+ var exports_schema = {};
525
+ __export(exports_schema, {
526
+ threads: () => threads,
527
+ threadTtl: () => threadTtl,
528
+ runs: () => runs,
529
+ migrations: () => migrations,
530
+ crons: () => crons,
531
+ assistants: () => assistants,
532
+ assistantVersions: () => assistantVersions
533
+ });
534
+ import { sql } from "drizzle-orm";
535
+ import {
536
+ boolean,
537
+ doublePrecision,
538
+ index,
539
+ integer,
540
+ jsonb,
541
+ pgTable,
542
+ primaryKey,
543
+ text,
544
+ timestamp as timestamp2,
545
+ unique,
546
+ uniqueIndex
547
+ } from "drizzle-orm/pg-core";
548
+ var timestamps, migrations, assistants, assistantVersions, threads, runs, crons, threadTtl;
549
+ var init_schema = __esm(() => {
550
+ timestamps = {
551
+ created_at: timestamp2("created_at", { withTimezone: true }).notNull().defaultNow(),
552
+ updated_at: timestamp2("updated_at", { withTimezone: true }).notNull().defaultNow()
553
+ };
554
+ migrations = pgTable("aegra_migrations", {
555
+ checksum: text("checksum"),
556
+ version: integer("version").primaryKey(),
557
+ applied_at: timestamp2("applied_at", { withTimezone: true }).notNull().defaultNow()
558
+ });
559
+ assistants = pgTable("assistant", {
560
+ assistant_id: text("assistant_id").primaryKey().default(sql`gen_random_uuid()::text`),
561
+ name: text("name").notNull(),
562
+ description: text("description"),
563
+ graph_id: text("graph_id").notNull(),
564
+ config: jsonb("config").$type().notNull().default({}),
565
+ context: jsonb("context").$type().notNull().default({}),
566
+ user_id: text("user_id").notNull(),
567
+ version: integer("version").notNull().default(1),
568
+ metadata: jsonb("metadata").$type().notNull().default({}),
569
+ ...timestamps
570
+ }, (table) => [
571
+ index("idx_assistant_user").on(table.user_id),
572
+ unique("assistant_user_id_unique").on(table.user_id, table.assistant_id),
573
+ uniqueIndex("idx_assistant_user_graph_config").on(table.user_id, table.graph_id, sql`md5(${table.config}::text)`),
574
+ index("idx_assistant_metadata_gin").using("gin", sql`${table.metadata} jsonb_path_ops`)
575
+ ]);
576
+ assistantVersions = pgTable("assistant_versions", {
577
+ assistant_id: text("assistant_id").notNull().references(() => assistants.assistant_id, { onDelete: "cascade" }),
578
+ version: integer("version").notNull(),
579
+ graph_id: text("graph_id").notNull(),
580
+ config: jsonb("config").$type(),
581
+ context: jsonb("context").$type(),
582
+ metadata: jsonb("metadata").$type().notNull().default({}),
583
+ name: text("name"),
584
+ description: text("description"),
585
+ created_at: timestamp2("created_at", { withTimezone: true }).notNull().defaultNow()
586
+ }, (table) => [primaryKey({ columns: [table.assistant_id, table.version] })]);
587
+ threads = pgTable("thread", {
588
+ thread_id: text("thread_id").primaryKey(),
589
+ status: text("status").notNull().default("idle"),
590
+ metadata_json: jsonb("metadata_json").$type().notNull().default({}),
591
+ user_id: text("user_id").notNull(),
592
+ ...timestamps
593
+ }, (table) => [
594
+ index("idx_thread_user").on(table.user_id),
595
+ index("idx_thread_metadata_gin").using("gin", sql`${table.metadata_json} jsonb_path_ops`)
596
+ ]);
597
+ runs = pgTable("runs", {
598
+ run_id: text("run_id").primaryKey().default(sql`gen_random_uuid()::text`),
599
+ thread_id: text("thread_id").notNull().references(() => threads.thread_id, { onDelete: "cascade" }),
600
+ assistant_id: text("assistant_id").references(() => assistants.assistant_id, {
601
+ onDelete: "cascade"
602
+ }),
603
+ status: text("status").notNull().default("pending"),
604
+ input: jsonb("input").$type(),
605
+ config: jsonb("config").$type(),
606
+ context: jsonb("context").$type(),
607
+ output: jsonb("output").$type(),
608
+ error_message: text("error_message"),
609
+ user_id: text("user_id").notNull(),
610
+ execution_params: jsonb("execution_params").$type(),
611
+ claimed_by: text("claimed_by"),
612
+ lease_expires_at: timestamp2("lease_expires_at", { withTimezone: true }),
613
+ ...timestamps
614
+ }, (table) => [
615
+ index("idx_runs_thread_id").on(table.thread_id),
616
+ index("idx_runs_status").on(table.status),
617
+ index("idx_runs_user").on(table.user_id),
618
+ index("idx_runs_assistant_id").on(table.assistant_id),
619
+ index("idx_runs_created_at").on(table.created_at),
620
+ index("idx_runs_lease_reaper").on(table.status, table.lease_expires_at).where(sql`${table.status} = 'running'`)
621
+ ]);
622
+ crons = pgTable("crons", {
623
+ cron_id: text("cron_id").primaryKey().default(sql`gen_random_uuid()::text`),
624
+ assistant_id: text("assistant_id").notNull().references(() => assistants.assistant_id, { onDelete: "cascade" }),
625
+ thread_id: text("thread_id").references(() => threads.thread_id, { onDelete: "cascade" }),
626
+ user_id: text("user_id").notNull(),
627
+ schedule: text("schedule").notNull(),
628
+ payload: jsonb("payload").$type().notNull().default({}),
629
+ metadata: jsonb("metadata").$type().notNull().default({}),
630
+ on_run_completed: text("on_run_completed"),
631
+ enabled: boolean("enabled").notNull().default(true),
632
+ end_time: timestamp2("end_time", { withTimezone: true }),
633
+ next_run_date: timestamp2("next_run_date", { withTimezone: true }),
634
+ claimed_until: timestamp2("claimed_until", { withTimezone: true }),
635
+ ...timestamps
636
+ }, (table) => [
637
+ index("idx_cron_user").on(table.user_id),
638
+ index("idx_cron_assistant_id").on(table.assistant_id),
639
+ index("idx_cron_thread_id").on(table.thread_id),
640
+ index("idx_cron_next_run").on(table.enabled, table.next_run_date)
641
+ ]);
642
+ threadTtl = pgTable("thread_ttl", {
643
+ thread_id: text("thread_id").primaryKey().references(() => threads.thread_id, { onDelete: "cascade" }),
644
+ strategy: text("strategy").notNull().default("delete"),
645
+ ttl_minutes: doublePrecision("ttl_minutes").notNull(),
646
+ created_at: timestamp2("created_at", { withTimezone: true }).notNull().defaultNow(),
647
+ expires_at: timestamp2("expires_at", { withTimezone: true }).notNull()
648
+ }, (table) => [index("idx_thread_ttl_expires_at").on(table.expires_at)]);
649
+ });
650
+
451
651
  // src/core/database.ts
452
652
  var exports_database = {};
453
653
  __export(exports_database, {
454
654
  pingDatabase: () => pingDatabase,
455
655
  migrate: () => migrate,
656
+ initializeStore: () => initializeStore,
456
657
  db: () => db,
457
658
  closeDatabase: () => closeDatabase,
458
659
  client: () => client
459
660
  });
460
661
  import { createHash } from "crypto";
461
662
  import postgres from "postgres";
462
- import { drizzle as drizzle2 } from "drizzle-orm/postgres-js";
663
+ import { drizzle } from "drizzle-orm/postgres-js";
463
664
  async function migrate(connection = client) {
464
665
  await connection.begin(async (sql2) => {
465
666
  await sql2.unsafe(`SELECT pg_advisory_xact_lock(${MIGRATION_LOCK_ID})`);
@@ -485,6 +686,9 @@ async function migrate(connection = client) {
485
686
  }
486
687
  });
487
688
  }
689
+ async function initializeStore() {
690
+ await getOfficialStore();
691
+ }
488
692
  async function pingDatabase() {
489
693
  try {
490
694
  await client`SELECT 1`;
@@ -494,8 +698,11 @@ async function pingDatabase() {
494
698
  }
495
699
  }
496
700
  async function closeDatabase() {
497
- await closeLangGraphDatabase();
498
- await client.end({ timeout: 5 });
701
+ try {
702
+ await closeLangGraphDatabase();
703
+ } finally {
704
+ await client.end({ timeout: 5 });
705
+ }
499
706
  }
500
707
  var client, db, migrations2, MIGRATION_LOCK_ID = 1095067474;
501
708
  var init_database = __esm(() => {
@@ -519,7 +726,7 @@ var init_database = __esm(() => {
519
726
  });
520
727
  }
521
728
  });
522
- db = drizzle2({ client, schema: exports_schema });
729
+ db = drizzle({ client, schema: exports_schema });
523
730
  migrations2 = [
524
731
  {
525
732
  version: 1,
@@ -1147,9 +1354,13 @@ async function main(argv = process.argv.slice(2)) {
1147
1354
  if (command === "db" && args[0] === "upgrade") {
1148
1355
  const { options } = parseOptions(args.slice(1));
1149
1356
  await serverEnvironment(options);
1150
- const { migrate: migrate2, closeDatabase: closeDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
1151
- await migrate2();
1152
- await closeDatabase2();
1357
+ const { migrate: migrate2, initializeStore: initializeStore2, closeDatabase: closeDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
1358
+ try {
1359
+ await migrate2();
1360
+ await initializeStore2();
1361
+ } finally {
1362
+ await closeDatabase2();
1363
+ }
1153
1364
  console.log("Database is up to date");
1154
1365
  return;
1155
1366
  }
@@ -1164,4 +1375,4 @@ export {
1164
1375
  main
1165
1376
  };
1166
1377
 
1167
- //# debugId=F0608CC7271E48CC64756E2164756E21
1378
+ //# debugId=9AF67AE5F33A402164756E2164756E21