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 +376 -165
- package/dist/cli.js.map +9 -8
- package/dist/config/settings.d.ts +1 -1
- package/dist/index.js +419 -366
- package/dist/index.js.map +11 -11
- package/dist/runtime.js +419 -366
- package/dist/runtime.js.map +11 -11
- package/dist/settings.js +2 -2
- package/dist/settings.js.map +2 -2
- package/package.json +2 -2
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.
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
498
|
-
|
|
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 =
|
|
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
|
-
|
|
1152
|
-
|
|
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=
|
|
1378
|
+
//# debugId=9AF67AE5F33A402164756E2164756E21
|