@exulu/backend 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -2
- package/dist/index.cjs +394 -403
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +392 -402
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,8 @@ __export(index_exports, {
|
|
|
45
45
|
ExuluSource: () => ExuluSource,
|
|
46
46
|
ExuluTool: () => ExuluTool,
|
|
47
47
|
ExuluWorkflow: () => ExuluWorkflow,
|
|
48
|
-
ExuluZodFileType: () => ExuluZodFileType
|
|
48
|
+
ExuluZodFileType: () => ExuluZodFileType,
|
|
49
|
+
db: () => db2
|
|
49
50
|
});
|
|
50
51
|
module.exports = __toCommonJS(index_exports);
|
|
51
52
|
var import_config = require("dotenv/config");
|
|
@@ -224,7 +225,7 @@ var bullmqDecorator = async ({
|
|
|
224
225
|
jobId: redisId
|
|
225
226
|
}
|
|
226
227
|
);
|
|
227
|
-
const { db:
|
|
228
|
+
const { db: db3 } = await postgresClient();
|
|
228
229
|
const now = /* @__PURE__ */ new Date();
|
|
229
230
|
console.log("[EXULU] scheduling new job", inputs);
|
|
230
231
|
const insertData = {
|
|
@@ -249,12 +250,12 @@ var bullmqDecorator = async ({
|
|
|
249
250
|
...documents && { documents: documents.map((doc2) => doc2.id) },
|
|
250
251
|
...trigger && { trigger }
|
|
251
252
|
};
|
|
252
|
-
await
|
|
253
|
+
await db3("jobs").insert(insertData).onConflict("redis").merge({
|
|
253
254
|
...insertData,
|
|
254
255
|
updatedAt: now
|
|
255
256
|
// Only updatedAt changes on updates
|
|
256
257
|
});
|
|
257
|
-
const doc = await
|
|
258
|
+
const doc = await db3.from("jobs").where({ redis: job.id }).first();
|
|
258
259
|
if (!doc?.id) {
|
|
259
260
|
throw new Error("Failed to get job ID after insert/update");
|
|
260
261
|
}
|
|
@@ -657,10 +658,10 @@ var ExuluWorkflow = class {
|
|
|
657
658
|
label
|
|
658
659
|
}) => {
|
|
659
660
|
let inputs;
|
|
660
|
-
const { db:
|
|
661
|
+
const { db: db3 } = await postgresClient();
|
|
661
662
|
if (!job?.id) {
|
|
662
663
|
logger.write(`Creating new job for workflow ${this.name} with inputs: ${JSON.stringify(initialInputs)}`, "INFO");
|
|
663
|
-
const result = await
|
|
664
|
+
const result = await db3("jobs").insert({
|
|
664
665
|
status: JOB_STATUS_ENUM.active,
|
|
665
666
|
name: `Job running '${this.name}' for '${label}'`,
|
|
666
667
|
agent,
|
|
@@ -678,7 +679,7 @@ var ExuluWorkflow = class {
|
|
|
678
679
|
throw new Error("Job not found, or failed to be created.");
|
|
679
680
|
}
|
|
680
681
|
if (job.status !== JOB_STATUS_ENUM.active) {
|
|
681
|
-
await
|
|
682
|
+
await db3("jobs").update({
|
|
682
683
|
status: JOB_STATUS_ENUM.active,
|
|
683
684
|
inputs: initialInputs
|
|
684
685
|
}).where({ id: job?.id }).returning("id");
|
|
@@ -721,15 +722,15 @@ var ExuluWorkflow = class {
|
|
|
721
722
|
logger.write(`Step ${step.name} output: ${JSON.stringify(result)}`, "INFO");
|
|
722
723
|
final = result;
|
|
723
724
|
}
|
|
724
|
-
await
|
|
725
|
+
await db3("jobs").update({
|
|
725
726
|
status: JOB_STATUS_ENUM.completed,
|
|
726
727
|
result: JSON.stringify(final),
|
|
727
|
-
finished_at:
|
|
728
|
+
finished_at: db3.fn.now()
|
|
728
729
|
}).where({ id: job?.id }).returning("id");
|
|
729
730
|
return final;
|
|
730
731
|
} catch (error) {
|
|
731
732
|
logger.write(`Workflow ${this.name} failed with error: ${error.message} for job ${job?.id}`, "ERROR");
|
|
732
|
-
await
|
|
733
|
+
await db3("jobs").update({
|
|
733
734
|
status: JOB_STATUS_ENUM.failed,
|
|
734
735
|
result: JSON.stringify({
|
|
735
736
|
error: error.message || error,
|
|
@@ -842,8 +843,8 @@ var ExuluEval = class {
|
|
|
842
843
|
</correct_answers>`
|
|
843
844
|
});
|
|
844
845
|
console.log("[EXULU] eval result", object);
|
|
845
|
-
const { db:
|
|
846
|
-
await
|
|
846
|
+
const { db: db3 } = await postgresClient();
|
|
847
|
+
await db3("eval_results").insert({
|
|
847
848
|
input: data.prompt,
|
|
848
849
|
output: data.result,
|
|
849
850
|
duration: data.duration,
|
|
@@ -854,8 +855,8 @@ var ExuluEval = class {
|
|
|
854
855
|
comment: object.comment,
|
|
855
856
|
category: data.category,
|
|
856
857
|
metadata: data.metadata,
|
|
857
|
-
createdAt:
|
|
858
|
-
updatedAt:
|
|
858
|
+
createdAt: db3.fn.now(),
|
|
859
|
+
updatedAt: db3.fn.now()
|
|
859
860
|
});
|
|
860
861
|
return {
|
|
861
862
|
score: object.correctnessScore,
|
|
@@ -959,15 +960,15 @@ var ExuluContext = class {
|
|
|
959
960
|
return sanitizeName(this.name) + "_chunks";
|
|
960
961
|
};
|
|
961
962
|
tableExists = async () => {
|
|
962
|
-
const { db:
|
|
963
|
-
const tableExists = await
|
|
963
|
+
const { db: db3 } = await postgresClient();
|
|
964
|
+
const tableExists = await db3.schema.hasTable(this.getTableName());
|
|
964
965
|
return tableExists;
|
|
965
966
|
};
|
|
966
967
|
async updateItem(user, id, item) {
|
|
967
968
|
if (!id) {
|
|
968
969
|
throw new Error("Id is required for updating an item.");
|
|
969
970
|
}
|
|
970
|
-
const { db:
|
|
971
|
+
const { db: db3 } = await postgresClient();
|
|
971
972
|
Object.keys(item).forEach((key) => {
|
|
972
973
|
if (key === "name" || key === "description" || key === "external_id" || key === "tags" || key === "source" || key === "textLength" || key === "upsert" || key === "archived") {
|
|
973
974
|
return;
|
|
@@ -980,8 +981,8 @@ var ExuluContext = class {
|
|
|
980
981
|
delete item.id;
|
|
981
982
|
delete item.created_at;
|
|
982
983
|
delete item.upsert;
|
|
983
|
-
item.updated_at =
|
|
984
|
-
const result = await
|
|
984
|
+
item.updated_at = db3.fn.now();
|
|
985
|
+
const result = await db3.from(this.getTableName()).where({ id }).update(item).returning("id");
|
|
985
986
|
if (this.configuration.calculateVectors === "onUpdate" || this.configuration.calculateVectors === "always") {
|
|
986
987
|
if (this.embedder.queue?.name) {
|
|
987
988
|
console.log("[EXULU] embedder is in queue mode, scheduling job.");
|
|
@@ -1005,18 +1006,18 @@ var ExuluContext = class {
|
|
|
1005
1006
|
label: this.name,
|
|
1006
1007
|
trigger: "agent"
|
|
1007
1008
|
});
|
|
1008
|
-
const exists = await
|
|
1009
|
+
const exists = await db3.schema.hasTable(this.getChunksTableName());
|
|
1009
1010
|
if (!exists) {
|
|
1010
1011
|
await this.createChunksTable();
|
|
1011
1012
|
}
|
|
1012
|
-
await
|
|
1013
|
-
await
|
|
1013
|
+
await db3.from(this.getChunksTableName()).where({ source }).delete();
|
|
1014
|
+
await db3.from(this.getChunksTableName()).insert(chunks.map((chunk) => ({
|
|
1014
1015
|
source,
|
|
1015
1016
|
content: chunk.content,
|
|
1016
1017
|
chunk_index: chunk.index,
|
|
1017
1018
|
embedding: import_knex4.default.toSql(chunk.vector)
|
|
1018
1019
|
})));
|
|
1019
|
-
await
|
|
1020
|
+
await db3.from(this.getTableName()).where({ id }).update({
|
|
1020
1021
|
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1021
1022
|
}).returning("id");
|
|
1022
1023
|
}
|
|
@@ -1029,9 +1030,9 @@ var ExuluContext = class {
|
|
|
1029
1030
|
if (!item.name) {
|
|
1030
1031
|
throw new Error("Name field is required.");
|
|
1031
1032
|
}
|
|
1032
|
-
const { db:
|
|
1033
|
+
const { db: db3 } = await postgresClient();
|
|
1033
1034
|
if (item.external_id) {
|
|
1034
|
-
const existingItem = await
|
|
1035
|
+
const existingItem = await db3.from(this.getTableName()).where({ external_id: item.external_id }).first();
|
|
1035
1036
|
if (existingItem && !upsert) {
|
|
1036
1037
|
throw new Error("Item with external id " + item.external_id + " already exists.");
|
|
1037
1038
|
}
|
|
@@ -1041,7 +1042,7 @@ var ExuluContext = class {
|
|
|
1041
1042
|
}
|
|
1042
1043
|
}
|
|
1043
1044
|
if (upsert && item.id) {
|
|
1044
|
-
const existingItem = await
|
|
1045
|
+
const existingItem = await db3.from(this.getTableName()).where({ id: item.id }).first();
|
|
1045
1046
|
if (existingItem && upsert) {
|
|
1046
1047
|
await this.updateItem(user, existingItem.id, item);
|
|
1047
1048
|
return existingItem.id;
|
|
@@ -1058,11 +1059,11 @@ var ExuluContext = class {
|
|
|
1058
1059
|
});
|
|
1059
1060
|
delete item.id;
|
|
1060
1061
|
delete item.upsert;
|
|
1061
|
-
const result = await
|
|
1062
|
+
const result = await db3.from(this.getTableName()).insert({
|
|
1062
1063
|
...item,
|
|
1063
|
-
id:
|
|
1064
|
-
created_at:
|
|
1065
|
-
updated_at:
|
|
1064
|
+
id: db3.fn.uuid(),
|
|
1065
|
+
created_at: db3.fn.now(),
|
|
1066
|
+
updated_at: db3.fn.now()
|
|
1066
1067
|
}).returning("id");
|
|
1067
1068
|
if (this.configuration.calculateVectors === "onInsert" || this.configuration.calculateVectors === "always") {
|
|
1068
1069
|
if (this.embedder.queue?.name) {
|
|
@@ -1088,18 +1089,18 @@ var ExuluContext = class {
|
|
|
1088
1089
|
label: this.name,
|
|
1089
1090
|
trigger: "agent"
|
|
1090
1091
|
});
|
|
1091
|
-
const exists = await
|
|
1092
|
+
const exists = await db3.schema.hasTable(this.getChunksTableName());
|
|
1092
1093
|
if (!exists) {
|
|
1093
1094
|
await this.createChunksTable();
|
|
1094
1095
|
}
|
|
1095
1096
|
console.log("[EXULU] Inserting chunks.");
|
|
1096
|
-
await
|
|
1097
|
+
await db3.from(this.getChunksTableName()).insert(chunks.map((chunk) => ({
|
|
1097
1098
|
source,
|
|
1098
1099
|
content: chunk.content,
|
|
1099
1100
|
chunk_index: chunk.index,
|
|
1100
1101
|
embedding: import_knex4.default.toSql(chunk.vector)
|
|
1101
1102
|
})));
|
|
1102
|
-
await
|
|
1103
|
+
await db3.from(this.getTableName()).where({ id: result[0].id }).update({
|
|
1103
1104
|
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1104
1105
|
}).returning("id");
|
|
1105
1106
|
}
|
|
@@ -1129,10 +1130,10 @@ var ExuluContext = class {
|
|
|
1129
1130
|
if (limit < 1) limit = 10;
|
|
1130
1131
|
let offset = (page - 1) * limit;
|
|
1131
1132
|
const mainTable = this.getTableName();
|
|
1132
|
-
const { db:
|
|
1133
|
-
const columns = await
|
|
1134
|
-
const totalQuery =
|
|
1135
|
-
const itemsQuery =
|
|
1133
|
+
const { db: db3 } = await postgresClient();
|
|
1134
|
+
const columns = await db3(mainTable).columnInfo();
|
|
1135
|
+
const totalQuery = db3.count("* as count").from(mainTable).first();
|
|
1136
|
+
const itemsQuery = db3.select(Object.keys(columns).map((column) => mainTable + "." + column)).from(mainTable).offset(offset).limit(limit);
|
|
1136
1137
|
if (sort) {
|
|
1137
1138
|
itemsQuery.orderBy(sort, order === "desc" ? "desc" : "asc");
|
|
1138
1139
|
}
|
|
@@ -1208,29 +1209,29 @@ var ExuluContext = class {
|
|
|
1208
1209
|
const vectorExpr = `${vectorStr}::vector`;
|
|
1209
1210
|
switch (method) {
|
|
1210
1211
|
case "l1Distance":
|
|
1211
|
-
itemsQuery.select(
|
|
1212
|
-
itemsQuery.orderByRaw(
|
|
1212
|
+
itemsQuery.select(db3.raw(`?? <-> ${vectorExpr} as l1_distance`, [`${chunksTable}.embedding`]));
|
|
1213
|
+
itemsQuery.orderByRaw(db3.raw(`?? <-> ${vectorExpr} ASC`, [`${chunksTable}.embedding`]));
|
|
1213
1214
|
break;
|
|
1214
1215
|
case "l2Distance":
|
|
1215
|
-
itemsQuery.select(
|
|
1216
|
-
itemsQuery.orderByRaw(
|
|
1216
|
+
itemsQuery.select(db3.raw(`?? <-> ${vectorExpr} as l2_distance`, [`${chunksTable}.embedding`]));
|
|
1217
|
+
itemsQuery.orderByRaw(db3.raw(`?? <-> ${vectorExpr} ASC`, [`${chunksTable}.embedding`]));
|
|
1217
1218
|
break;
|
|
1218
1219
|
case "hammingDistance":
|
|
1219
|
-
itemsQuery.select(
|
|
1220
|
-
itemsQuery.orderByRaw(
|
|
1220
|
+
itemsQuery.select(db3.raw(`?? <#> ${vectorExpr} as hamming_distance`, [`${chunksTable}.embedding`]));
|
|
1221
|
+
itemsQuery.orderByRaw(db3.raw(`?? <#> ${vectorExpr} ASC`, [`${chunksTable}.embedding`]));
|
|
1221
1222
|
break;
|
|
1222
1223
|
case "jaccardDistance":
|
|
1223
|
-
itemsQuery.select(
|
|
1224
|
-
itemsQuery.orderByRaw(
|
|
1224
|
+
itemsQuery.select(db3.raw(`?? <#> ${vectorExpr} as jaccard_distance`, [`${chunksTable}.embedding`]));
|
|
1225
|
+
itemsQuery.orderByRaw(db3.raw(`?? <#> ${vectorExpr} ASC`, [`${chunksTable}.embedding`]));
|
|
1225
1226
|
break;
|
|
1226
1227
|
case "maxInnerProduct":
|
|
1227
|
-
itemsQuery.select(
|
|
1228
|
-
itemsQuery.orderByRaw(
|
|
1228
|
+
itemsQuery.select(db3.raw(`?? <#> ${vectorExpr} as inner_product`, [`${chunksTable}.embedding`]));
|
|
1229
|
+
itemsQuery.orderByRaw(db3.raw(`?? <#> ${vectorExpr} ASC`, [`${chunksTable}.embedding`]));
|
|
1229
1230
|
break;
|
|
1230
1231
|
case "cosineDistance":
|
|
1231
1232
|
default:
|
|
1232
|
-
itemsQuery.select(
|
|
1233
|
-
itemsQuery.orderByRaw(
|
|
1233
|
+
itemsQuery.select(db3.raw(`1 - (?? <#> ${vectorExpr}) as cosine_distance`, [`${chunksTable}.embedding`]));
|
|
1234
|
+
itemsQuery.orderByRaw(db3.raw(`1 - (?? <#> ${vectorExpr}) DESC`, [`${chunksTable}.embedding`]));
|
|
1234
1235
|
break;
|
|
1235
1236
|
}
|
|
1236
1237
|
let items = await itemsQuery;
|
|
@@ -1299,12 +1300,12 @@ var ExuluContext = class {
|
|
|
1299
1300
|
}
|
|
1300
1301
|
};
|
|
1301
1302
|
createItemsTable = async () => {
|
|
1302
|
-
const { db:
|
|
1303
|
+
const { db: db3 } = await postgresClient();
|
|
1303
1304
|
const tableName = this.getTableName();
|
|
1304
1305
|
console.log("[EXULU] Creating table: " + tableName);
|
|
1305
|
-
return await
|
|
1306
|
+
return await db3.schema.createTable(tableName, (table) => {
|
|
1306
1307
|
console.log("[EXULU] Creating fields for table.", this.fields);
|
|
1307
|
-
table.uuid("id").primary().defaultTo(
|
|
1308
|
+
table.uuid("id").primary().defaultTo(db3.fn.uuid());
|
|
1308
1309
|
table.text("name");
|
|
1309
1310
|
table.text("description");
|
|
1310
1311
|
table.text("tags");
|
|
@@ -1324,11 +1325,11 @@ var ExuluContext = class {
|
|
|
1324
1325
|
});
|
|
1325
1326
|
};
|
|
1326
1327
|
createChunksTable = async () => {
|
|
1327
|
-
const { db:
|
|
1328
|
+
const { db: db3 } = await postgresClient();
|
|
1328
1329
|
const tableName = this.getChunksTableName();
|
|
1329
1330
|
console.log("[EXULU] Creating table: " + tableName);
|
|
1330
|
-
return await
|
|
1331
|
-
table.uuid("id").primary().defaultTo(
|
|
1331
|
+
return await db3.schema.createTable(tableName, (table) => {
|
|
1332
|
+
table.uuid("id").primary().defaultTo(db3.fn.uuid());
|
|
1332
1333
|
table.uuid("source").references("id").inTable(this.getTableName());
|
|
1333
1334
|
table.text("content");
|
|
1334
1335
|
table.integer("chunk_index");
|
|
@@ -1400,15 +1401,15 @@ var ExuluSource = class {
|
|
|
1400
1401
|
};
|
|
1401
1402
|
var updateStatistic = async (statistic) => {
|
|
1402
1403
|
const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1403
|
-
const { db:
|
|
1404
|
-
const existing = await
|
|
1404
|
+
const { db: db3 } = await postgresClient();
|
|
1405
|
+
const existing = await db3.from("statistics").where({
|
|
1405
1406
|
name: statistic.name,
|
|
1406
1407
|
label: statistic.label,
|
|
1407
1408
|
type: statistic.type,
|
|
1408
1409
|
createdAt: currentDate
|
|
1409
1410
|
}).first();
|
|
1410
1411
|
if (!existing) {
|
|
1411
|
-
await
|
|
1412
|
+
await db3.from("statistics").insert({
|
|
1412
1413
|
name: statistic.name,
|
|
1413
1414
|
label: statistic.label,
|
|
1414
1415
|
type: statistic.type,
|
|
@@ -1416,8 +1417,8 @@ var updateStatistic = async (statistic) => {
|
|
|
1416
1417
|
createdAt: currentDate
|
|
1417
1418
|
});
|
|
1418
1419
|
} else {
|
|
1419
|
-
await
|
|
1420
|
-
total:
|
|
1420
|
+
await db3.from("statistics").update({
|
|
1421
|
+
total: db3.raw("total + ?", [statistic.count ?? 1])
|
|
1421
1422
|
}).where({
|
|
1422
1423
|
name: statistic.name,
|
|
1423
1424
|
label: statistic.label,
|
|
@@ -1495,7 +1496,7 @@ var authentication = async ({
|
|
|
1495
1496
|
apikey,
|
|
1496
1497
|
authtoken,
|
|
1497
1498
|
internalkey,
|
|
1498
|
-
db:
|
|
1499
|
+
db: db3
|
|
1499
1500
|
}) => {
|
|
1500
1501
|
if (internalkey) {
|
|
1501
1502
|
if (!process.env.INTERNAL_SECRET) {
|
|
@@ -1532,7 +1533,7 @@ var authentication = async ({
|
|
|
1532
1533
|
code: 401
|
|
1533
1534
|
};
|
|
1534
1535
|
}
|
|
1535
|
-
const user = await
|
|
1536
|
+
const user = await db3.from("users").select("*").where("email", authtoken?.email).first();
|
|
1536
1537
|
if (!user) {
|
|
1537
1538
|
return {
|
|
1538
1539
|
error: true,
|
|
@@ -1555,7 +1556,7 @@ var authentication = async ({
|
|
|
1555
1556
|
}
|
|
1556
1557
|
}
|
|
1557
1558
|
if (apikey) {
|
|
1558
|
-
const users = await
|
|
1559
|
+
const users = await db3.from("users").select("*").where("type", "api");
|
|
1559
1560
|
if (!users || users.length === 0) {
|
|
1560
1561
|
return {
|
|
1561
1562
|
error: true,
|
|
@@ -1587,7 +1588,7 @@ var authentication = async ({
|
|
|
1587
1588
|
const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
|
|
1588
1589
|
const isMatch = await import_bcryptjs.default.compare(request_key_compare_value, user_key_compare_value);
|
|
1589
1590
|
if (isMatch) {
|
|
1590
|
-
await
|
|
1591
|
+
await db3.from("users").where({ id: user.id }).update({
|
|
1591
1592
|
last_used: /* @__PURE__ */ new Date()
|
|
1592
1593
|
}).returning("id");
|
|
1593
1594
|
return {
|
|
@@ -1615,7 +1616,7 @@ var authentication = async ({
|
|
|
1615
1616
|
var requestValidators = {
|
|
1616
1617
|
authenticate: async (req) => {
|
|
1617
1618
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
1618
|
-
const { db:
|
|
1619
|
+
const { db: db3 } = await postgresClient();
|
|
1619
1620
|
let authtoken = null;
|
|
1620
1621
|
if (typeof apikey !== "string") {
|
|
1621
1622
|
authtoken = await getToken((req.headers["authorization"] || req.headers["x-api-key"]) ?? "");
|
|
@@ -1623,7 +1624,7 @@ var requestValidators = {
|
|
|
1623
1624
|
return await authentication({
|
|
1624
1625
|
authtoken,
|
|
1625
1626
|
apikey,
|
|
1626
|
-
db:
|
|
1627
|
+
db: db3
|
|
1627
1628
|
});
|
|
1628
1629
|
},
|
|
1629
1630
|
workflows: (req) => {
|
|
@@ -1966,11 +1967,11 @@ function createMutations(table) {
|
|
|
1966
1967
|
const tableNameSingular = table.name.singular.toLowerCase();
|
|
1967
1968
|
return {
|
|
1968
1969
|
[`${tableNamePlural}CreateOne`]: async (_, args, context, info) => {
|
|
1969
|
-
const { db:
|
|
1970
|
+
const { db: db3 } = context;
|
|
1970
1971
|
const requestedFields = getRequestedFields(info);
|
|
1971
1972
|
let { input } = args;
|
|
1972
1973
|
input = encryptSensitiveFields(input);
|
|
1973
|
-
const results = await
|
|
1974
|
+
const results = await db3(tableNamePlural).insert({
|
|
1974
1975
|
...input,
|
|
1975
1976
|
createdAt: /* @__PURE__ */ new Date(),
|
|
1976
1977
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -1978,43 +1979,43 @@ function createMutations(table) {
|
|
|
1978
1979
|
return results[0];
|
|
1979
1980
|
},
|
|
1980
1981
|
[`${tableNamePlural}UpdateOne`]: async (_, args, context, info) => {
|
|
1981
|
-
const { db:
|
|
1982
|
+
const { db: db3 } = context;
|
|
1982
1983
|
let { where, input } = args;
|
|
1983
1984
|
input = encryptSensitiveFields(input);
|
|
1984
|
-
await
|
|
1985
|
+
await db3(tableNamePlural).where(where).update({
|
|
1985
1986
|
...input,
|
|
1986
1987
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1987
1988
|
});
|
|
1988
1989
|
const requestedFields = getRequestedFields(info);
|
|
1989
|
-
const result = await
|
|
1990
|
+
const result = await db3.from(tableNamePlural).select(requestedFields).where(where).first();
|
|
1990
1991
|
return result;
|
|
1991
1992
|
},
|
|
1992
1993
|
[`${tableNamePlural}UpdateOneById`]: async (_, args, context, info) => {
|
|
1993
1994
|
let { id, input } = args;
|
|
1994
1995
|
input = encryptSensitiveFields(input);
|
|
1995
|
-
const { db:
|
|
1996
|
-
await
|
|
1996
|
+
const { db: db3 } = context;
|
|
1997
|
+
await db3(tableNamePlural).where({ id }).update({
|
|
1997
1998
|
...input,
|
|
1998
1999
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1999
2000
|
});
|
|
2000
2001
|
const requestedFields = getRequestedFields(info);
|
|
2001
|
-
const result = await
|
|
2002
|
+
const result = await db3.from(tableNamePlural).select(requestedFields).where({ id }).first();
|
|
2002
2003
|
return result;
|
|
2003
2004
|
},
|
|
2004
2005
|
[`${tableNamePlural}RemoveOne`]: async (_, args, context, info) => {
|
|
2005
|
-
const { db:
|
|
2006
|
+
const { db: db3 } = context;
|
|
2006
2007
|
const { where } = args;
|
|
2007
2008
|
const requestedFields = getRequestedFields(info);
|
|
2008
|
-
const result = await
|
|
2009
|
-
await
|
|
2009
|
+
const result = await db3.from(tableNamePlural).select(requestedFields).where(where).first();
|
|
2010
|
+
await db3(tableNamePlural).where(where).del();
|
|
2010
2011
|
return result;
|
|
2011
2012
|
},
|
|
2012
2013
|
[`${tableNamePlural}RemoveOneById`]: async (_, args, context, info) => {
|
|
2013
2014
|
const { id } = args;
|
|
2014
|
-
const { db:
|
|
2015
|
+
const { db: db3 } = context;
|
|
2015
2016
|
const requestedFields = getRequestedFields(info);
|
|
2016
|
-
const result = await
|
|
2017
|
-
await
|
|
2017
|
+
const result = await db3.from(tableNamePlural).select(requestedFields).where({ id }).first();
|
|
2018
|
+
await db3(tableNamePlural).where({ id }).del();
|
|
2018
2019
|
return result;
|
|
2019
2020
|
}
|
|
2020
2021
|
};
|
|
@@ -2051,16 +2052,16 @@ function createQueries(table) {
|
|
|
2051
2052
|
};
|
|
2052
2053
|
return {
|
|
2053
2054
|
[`${tableNameSingular}ById`]: async (_, args, context, info) => {
|
|
2054
|
-
const { db:
|
|
2055
|
+
const { db: db3 } = context;
|
|
2055
2056
|
const requestedFields = getRequestedFields(info);
|
|
2056
|
-
const result = await
|
|
2057
|
+
const result = await db3.from(tableNamePlural).select(requestedFields).where({ id: args.id }).first();
|
|
2057
2058
|
return result;
|
|
2058
2059
|
},
|
|
2059
2060
|
[`${tableNameSingular}One`]: async (_, args, context, info) => {
|
|
2060
2061
|
const { filters = [], sort } = args;
|
|
2061
|
-
const { db:
|
|
2062
|
+
const { db: db3 } = context;
|
|
2062
2063
|
const requestedFields = getRequestedFields(info);
|
|
2063
|
-
let query =
|
|
2064
|
+
let query = db3.from(tableNamePlural).select(requestedFields);
|
|
2064
2065
|
query = applyFilters(query, filters);
|
|
2065
2066
|
query = applySorting(query, sort);
|
|
2066
2067
|
const result = await query.first();
|
|
@@ -2068,8 +2069,8 @@ function createQueries(table) {
|
|
|
2068
2069
|
},
|
|
2069
2070
|
[`${tableNamePlural}Pagination`]: async (_, args, context, info) => {
|
|
2070
2071
|
const { limit = 10, page = 0, filters = [], sort } = args;
|
|
2071
|
-
const { db:
|
|
2072
|
-
let baseQuery =
|
|
2072
|
+
const { db: db3 } = context;
|
|
2073
|
+
let baseQuery = db3(tableNamePlural);
|
|
2073
2074
|
baseQuery = applyFilters(baseQuery, filters);
|
|
2074
2075
|
const [{ count }] = await baseQuery.clone().count("* as count");
|
|
2075
2076
|
const itemCount = Number(count);
|
|
@@ -2099,8 +2100,8 @@ function createQueries(table) {
|
|
|
2099
2100
|
...tableNamePlural === "jobs" ? {
|
|
2100
2101
|
jobStatistics: async (_, args, context, info) => {
|
|
2101
2102
|
const { user, agent, from, to } = args;
|
|
2102
|
-
const { db:
|
|
2103
|
-
let query =
|
|
2103
|
+
const { db: db3 } = context;
|
|
2104
|
+
let query = db3("jobs");
|
|
2104
2105
|
if (user) {
|
|
2105
2106
|
query = query.where("user", user);
|
|
2106
2107
|
}
|
|
@@ -2117,7 +2118,7 @@ function createQueries(table) {
|
|
|
2117
2118
|
const [{ completedCount }] = await completedQuery.count("* as completedCount");
|
|
2118
2119
|
const failedQuery = query.clone().where("status", "failed");
|
|
2119
2120
|
const [{ failedCount }] = await failedQuery.count("* as failedCount");
|
|
2120
|
-
const durationQuery = query.clone().where("status", "completed").whereNotNull("duration").select(
|
|
2121
|
+
const durationQuery = query.clone().where("status", "completed").whereNotNull("duration").select(db3.raw('AVG("duration") as averageDuration'));
|
|
2121
2122
|
const [{ averageDuration }] = await durationQuery;
|
|
2122
2123
|
return {
|
|
2123
2124
|
completedCount: Number(completedCount),
|
|
@@ -2634,11 +2635,11 @@ var createUppyRoutes = async (app) => {
|
|
|
2634
2635
|
if (typeof apikey !== "string") {
|
|
2635
2636
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
2636
2637
|
}
|
|
2637
|
-
const { db:
|
|
2638
|
+
const { db: db3 } = await postgresClient();
|
|
2638
2639
|
const authenticationResult = await authentication({
|
|
2639
2640
|
authtoken,
|
|
2640
2641
|
apikey,
|
|
2641
|
-
db:
|
|
2642
|
+
db: db3
|
|
2642
2643
|
});
|
|
2643
2644
|
if (!authenticationResult.user?.id) {
|
|
2644
2645
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -2679,7 +2680,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2679
2680
|
app.get("/s3/download", async (req, res, next) => {
|
|
2680
2681
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
2681
2682
|
const internalkey = req.headers["internal-key"] || null;
|
|
2682
|
-
const { db:
|
|
2683
|
+
const { db: db3 } = await postgresClient();
|
|
2683
2684
|
let authtoken = null;
|
|
2684
2685
|
if (typeof apikey !== "string" && typeof internalkey !== "string") {
|
|
2685
2686
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -2688,7 +2689,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2688
2689
|
authtoken,
|
|
2689
2690
|
apikey,
|
|
2690
2691
|
internalkey,
|
|
2691
|
-
db:
|
|
2692
|
+
db: db3
|
|
2692
2693
|
});
|
|
2693
2694
|
if (!authenticationResult.user?.id) {
|
|
2694
2695
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -2752,7 +2753,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2752
2753
|
const generateS3Key = (filename) => `${crypto.randomUUID()}-${filename}`;
|
|
2753
2754
|
const signOnServer = async (req, res, next) => {
|
|
2754
2755
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
2755
|
-
const { db:
|
|
2756
|
+
const { db: db3 } = await postgresClient();
|
|
2756
2757
|
let authtoken = null;
|
|
2757
2758
|
if (typeof apikey !== "string") {
|
|
2758
2759
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -2760,7 +2761,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2760
2761
|
const authenticationResult = await authentication({
|
|
2761
2762
|
authtoken,
|
|
2762
2763
|
apikey,
|
|
2763
|
-
db:
|
|
2764
|
+
db: db3
|
|
2764
2765
|
});
|
|
2765
2766
|
if (!authenticationResult.user?.id) {
|
|
2766
2767
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -2800,7 +2801,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2800
2801
|
});
|
|
2801
2802
|
app.post("/s3/multipart", async (req, res, next) => {
|
|
2802
2803
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
2803
|
-
const { db:
|
|
2804
|
+
const { db: db3 } = await postgresClient();
|
|
2804
2805
|
let authtoken = null;
|
|
2805
2806
|
if (typeof apikey !== "string") {
|
|
2806
2807
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -2808,7 +2809,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2808
2809
|
const authenticationResult = await authentication({
|
|
2809
2810
|
authtoken,
|
|
2810
2811
|
apikey,
|
|
2811
|
-
db:
|
|
2812
|
+
db: db3
|
|
2812
2813
|
});
|
|
2813
2814
|
if (!authenticationResult.user?.id) {
|
|
2814
2815
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3112,10 +3113,10 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3112
3113
|
if (!authenticationResult.user?.id) {
|
|
3113
3114
|
throw new Error(authenticationResult.message);
|
|
3114
3115
|
}
|
|
3115
|
-
const { db:
|
|
3116
|
+
const { db: db3 } = await postgresClient();
|
|
3116
3117
|
return {
|
|
3117
3118
|
req,
|
|
3118
|
-
db:
|
|
3119
|
+
db: db3
|
|
3119
3120
|
};
|
|
3120
3121
|
}
|
|
3121
3122
|
})
|
|
@@ -3134,8 +3135,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3134
3135
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3135
3136
|
return;
|
|
3136
3137
|
}
|
|
3137
|
-
const { db:
|
|
3138
|
-
const agentsFromDb = await
|
|
3138
|
+
const { db: db3 } = await postgresClient();
|
|
3139
|
+
const agentsFromDb = await db3.from("agents").select("*");
|
|
3139
3140
|
res.status(200).json(agentsFromDb.map((agent) => {
|
|
3140
3141
|
const backend = agents.find((a) => a.id === agent.backend);
|
|
3141
3142
|
if (!backend) {
|
|
@@ -3166,7 +3167,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3166
3167
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3167
3168
|
return;
|
|
3168
3169
|
}
|
|
3169
|
-
const { db:
|
|
3170
|
+
const { db: db3 } = await postgresClient();
|
|
3170
3171
|
const id = req.params.id;
|
|
3171
3172
|
if (!id) {
|
|
3172
3173
|
res.status(400).json({
|
|
@@ -3174,7 +3175,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3174
3175
|
});
|
|
3175
3176
|
return;
|
|
3176
3177
|
}
|
|
3177
|
-
const agent = await
|
|
3178
|
+
const agent = await db3.from("agents").where({ id }).first();
|
|
3178
3179
|
if (!agent) {
|
|
3179
3180
|
res.status(400).json({
|
|
3180
3181
|
message: "Agent not found in database."
|
|
@@ -3240,7 +3241,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3240
3241
|
if (!id && !external_id) {
|
|
3241
3242
|
throw new Error("Missing id or external_id in request.");
|
|
3242
3243
|
}
|
|
3243
|
-
const { db:
|
|
3244
|
+
const { db: db3 } = await postgresClient();
|
|
3244
3245
|
const context = contexts.find((context2) => context2.id === contextId);
|
|
3245
3246
|
if (!context) {
|
|
3246
3247
|
throw new Error("Context not found in registry.");
|
|
@@ -3249,7 +3250,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3249
3250
|
if (!exists) {
|
|
3250
3251
|
throw new Error("Table with name " + context.getTableName() + " does not exist.");
|
|
3251
3252
|
}
|
|
3252
|
-
const query =
|
|
3253
|
+
const query = db3.from(context.getTableName()).select("id");
|
|
3253
3254
|
if (id) {
|
|
3254
3255
|
query.where({ id });
|
|
3255
3256
|
}
|
|
@@ -3260,11 +3261,11 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3260
3261
|
if (!item) {
|
|
3261
3262
|
return null;
|
|
3262
3263
|
}
|
|
3263
|
-
const chunks = await
|
|
3264
|
+
const chunks = await db3.from(context.getChunksTableName()).where({ source: item.id }).select("id");
|
|
3264
3265
|
if (chunks.length > 0) {
|
|
3265
|
-
await
|
|
3266
|
+
await db3.from(context.getChunksTableName()).where({ source: item.id }).delete();
|
|
3266
3267
|
}
|
|
3267
|
-
const mutation =
|
|
3268
|
+
const mutation = db3.from(context.getTableName()).where({ id: item.id }).delete().returning("id");
|
|
3268
3269
|
const result = await mutation;
|
|
3269
3270
|
return result;
|
|
3270
3271
|
};
|
|
@@ -3319,7 +3320,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3319
3320
|
});
|
|
3320
3321
|
return;
|
|
3321
3322
|
}
|
|
3322
|
-
const { db:
|
|
3323
|
+
const { db: db3 } = await postgresClient();
|
|
3323
3324
|
const context = contexts.find((context2) => context2.id === req.params.context);
|
|
3324
3325
|
if (!context) {
|
|
3325
3326
|
res.status(400).json({
|
|
@@ -3331,11 +3332,11 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3331
3332
|
if (!itemsTableExists) {
|
|
3332
3333
|
await context.createItemsTable();
|
|
3333
3334
|
}
|
|
3334
|
-
const chunksTableExists = await
|
|
3335
|
+
const chunksTableExists = await db3.schema.hasTable(context.getChunksTableName());
|
|
3335
3336
|
if (!chunksTableExists) {
|
|
3336
3337
|
await context.createChunksTable();
|
|
3337
3338
|
}
|
|
3338
|
-
const item = await
|
|
3339
|
+
const item = await db3.from(context.getTableName()).where({ id: req.params.id }).select("*").first();
|
|
3339
3340
|
if (!item) {
|
|
3340
3341
|
res.status(404).json({
|
|
3341
3342
|
message: "Item not found."
|
|
@@ -3343,7 +3344,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3343
3344
|
return;
|
|
3344
3345
|
}
|
|
3345
3346
|
console.log("[EXULU] chunks table name.", context.getChunksTableName());
|
|
3346
|
-
const chunks = await
|
|
3347
|
+
const chunks = await db3.from(context.getChunksTableName()).where({ source: req.params.id }).select("id", "content", "source", "embedding", "chunk_index", "created_at", "updated_at");
|
|
3347
3348
|
console.log("[EXULU] chunks", chunks);
|
|
3348
3349
|
res.status(200).json({
|
|
3349
3350
|
...item,
|
|
@@ -3593,7 +3594,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3593
3594
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3594
3595
|
return;
|
|
3595
3596
|
}
|
|
3596
|
-
const { db:
|
|
3597
|
+
const { db: db3 } = await postgresClient();
|
|
3597
3598
|
const type = req.body.type;
|
|
3598
3599
|
if (!Object.values(STATISTICS_TYPE_ENUM).includes(type)) {
|
|
3599
3600
|
res.status(400).json({
|
|
@@ -3607,7 +3608,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3607
3608
|
from = new Date(Date.now() - 7 * 24 * 60 * 60 * 1e3);
|
|
3608
3609
|
to = /* @__PURE__ */ new Date();
|
|
3609
3610
|
}
|
|
3610
|
-
const query =
|
|
3611
|
+
const query = db3.from("statistics").select("*");
|
|
3611
3612
|
query.where("name", "count");
|
|
3612
3613
|
query.andWhere("type", type);
|
|
3613
3614
|
query.andWhere("createdAt", ">=", from);
|
|
@@ -3642,7 +3643,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3642
3643
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3643
3644
|
return;
|
|
3644
3645
|
}
|
|
3645
|
-
const { db:
|
|
3646
|
+
const { db: db3 } = await postgresClient();
|
|
3646
3647
|
let from = new Date(req.body.from);
|
|
3647
3648
|
let to = new Date(req.body.to);
|
|
3648
3649
|
if (!from || !to) {
|
|
@@ -3650,7 +3651,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3650
3651
|
to = /* @__PURE__ */ new Date();
|
|
3651
3652
|
}
|
|
3652
3653
|
let promises2 = Object.values(STATISTICS_TYPE_ENUM).map(async (type) => {
|
|
3653
|
-
const result = await
|
|
3654
|
+
const result = await db3.from("statistics").where("name", "count").andWhere("type", type).andWhere("createdAt", ">=", from).andWhere("createdAt", "<=", to).sum("total as total");
|
|
3654
3655
|
return {
|
|
3655
3656
|
[type]: result[0]?.total || 0
|
|
3656
3657
|
};
|
|
@@ -3671,9 +3672,9 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3671
3672
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3672
3673
|
return;
|
|
3673
3674
|
}
|
|
3674
|
-
const { db:
|
|
3675
|
-
const statistics = await
|
|
3676
|
-
const response = await
|
|
3675
|
+
const { db: db3 } = await postgresClient();
|
|
3676
|
+
const statistics = await db3("statistics").where("name", "count").andWhere("type", "context.retrieve").sum("total as total").first();
|
|
3677
|
+
const response = await db3("jobs").select(db3.raw(`to_char("createdAt", 'YYYY-MM-DD') as date`)).count("* as count").where("type", "embedder").groupByRaw(`to_char("createdAt", 'YYYY-MM-DD')`).then((rows) => ({
|
|
3677
3678
|
jobs: rows
|
|
3678
3679
|
}));
|
|
3679
3680
|
let jobs = [];
|
|
@@ -3683,7 +3684,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3683
3684
|
count: job.count
|
|
3684
3685
|
}));
|
|
3685
3686
|
}
|
|
3686
|
-
const embeddingsCountResult = await
|
|
3687
|
+
const embeddingsCountResult = await db3("jobs").where("type", "embedder").count("* as count").first();
|
|
3687
3688
|
res.status(200).json({
|
|
3688
3689
|
active: contexts.filter((context) => context.active).length,
|
|
3689
3690
|
inactive: contexts.filter((context) => !context.active).length,
|
|
@@ -3883,8 +3884,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3883
3884
|
});
|
|
3884
3885
|
return;
|
|
3885
3886
|
}
|
|
3886
|
-
const { db:
|
|
3887
|
-
const agentInstance = await
|
|
3887
|
+
const { db: db3 } = await postgresClient();
|
|
3888
|
+
const agentInstance = await db3.from("agents").where({
|
|
3888
3889
|
id: instance
|
|
3889
3890
|
}).first();
|
|
3890
3891
|
if (!agentInstance) {
|
|
@@ -4019,26 +4020,18 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4019
4020
|
app.use("/gateway/anthropic/:id", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
|
|
4020
4021
|
const path3 = req.url;
|
|
4021
4022
|
const url = `${TARGET_API}${path3}`;
|
|
4022
|
-
console.log("[PROXY] Manual proxy to:", url);
|
|
4023
|
-
console.log("[PROXY] Method:", req.method);
|
|
4024
|
-
console.log("[PROXY] Headers:", Object.keys(req.headers));
|
|
4025
|
-
console.log("[PROXY] Request body length:", req.body ? req.body.length : 0);
|
|
4026
|
-
console.log("[PROXY] Request model name:", req.body.model);
|
|
4027
|
-
console.log("[PROXY] Request stream:", req.body.stream);
|
|
4028
|
-
console.log("[PROXY] Request messages:", req.body.messages?.length);
|
|
4029
4023
|
try {
|
|
4030
|
-
console.log("[PROXY] Request body tools array length:", req.body.tools?.length);
|
|
4031
4024
|
if (!req.body.tools) {
|
|
4032
4025
|
req.body.tools = [];
|
|
4033
4026
|
}
|
|
4034
4027
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
4035
4028
|
if (!authenticationResult.user?.id) {
|
|
4029
|
+
console.log("[EXULU] failed authentication result", authenticationResult);
|
|
4036
4030
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
4037
4031
|
return;
|
|
4038
4032
|
}
|
|
4039
|
-
|
|
4040
|
-
const
|
|
4041
|
-
const agent = await db2.from("agents").where({
|
|
4033
|
+
const { db: db3 } = await postgresClient();
|
|
4034
|
+
const agent = await db3.from("agents").where({
|
|
4042
4035
|
id: req.params.id
|
|
4043
4036
|
}).first();
|
|
4044
4037
|
if (!agent) {
|
|
@@ -4049,7 +4042,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4049
4042
|
res.end(Buffer.from(arrayBuffer));
|
|
4050
4043
|
return;
|
|
4051
4044
|
}
|
|
4052
|
-
console.log("[EXULU] agent", agent?.name);
|
|
4045
|
+
console.log("[EXULU] anthropic proxy called for agent:", agent?.name);
|
|
4053
4046
|
if (!process.env.NEXTAUTH_SECRET) {
|
|
4054
4047
|
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.missing_nextauth_secret);
|
|
4055
4048
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -4071,14 +4064,11 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4071
4064
|
};
|
|
4072
4065
|
if (req.headers["accept"]) headers["accept"] = req.headers["accept"];
|
|
4073
4066
|
if (req.headers["user-agent"]) headers["user-agent"] = req.headers["user-agent"];
|
|
4074
|
-
console.log("[EXULU] anthropic api key", anthropicApiKey);
|
|
4075
4067
|
const response = await fetch(url, {
|
|
4076
4068
|
method: req.method,
|
|
4077
4069
|
headers,
|
|
4078
4070
|
body: req.method !== "GET" ? JSON.stringify(req.body) : void 0
|
|
4079
4071
|
});
|
|
4080
|
-
console.log("[PROXY] Response:", response);
|
|
4081
|
-
console.log("[PROXY] Response:", response.body);
|
|
4082
4072
|
await updateStatistic({
|
|
4083
4073
|
name: "count",
|
|
4084
4074
|
label: "Claude Code",
|
|
@@ -4104,14 +4094,12 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4104
4094
|
const { done, value } = await reader.read();
|
|
4105
4095
|
if (done) break;
|
|
4106
4096
|
const chunk = decoder.decode(value, { stream: true });
|
|
4107
|
-
console.log("[PROXY] Chunk:", chunk);
|
|
4108
4097
|
res.write(chunk);
|
|
4109
4098
|
}
|
|
4110
4099
|
res.end();
|
|
4111
4100
|
return;
|
|
4112
4101
|
}
|
|
4113
4102
|
const data = await response.arrayBuffer();
|
|
4114
|
-
console.log("[PROXY] Data:", data);
|
|
4115
4103
|
res.end(Buffer.from(data));
|
|
4116
4104
|
} catch (error) {
|
|
4117
4105
|
console.error("[PROXY] Manual proxy error:", error);
|
|
@@ -4236,8 +4224,8 @@ var defaultLogsDir = import_path.default.join(process.cwd(), "logs");
|
|
|
4236
4224
|
var redisConnection;
|
|
4237
4225
|
var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
4238
4226
|
if (!redisServer.host || !redisServer.port) {
|
|
4239
|
-
console.error("[EXULU] you are trying to start
|
|
4240
|
-
throw new Error("No redis server configured in the environment, so cannot start
|
|
4227
|
+
console.error("[EXULU] you are trying to start worker, but no redis server is configured in the environment.");
|
|
4228
|
+
throw new Error("No redis server configured in the environment, so cannot start worker.");
|
|
4241
4229
|
}
|
|
4242
4230
|
if (!redisConnection) {
|
|
4243
4231
|
redisConnection = new import_ioredis.default({
|
|
@@ -4251,7 +4239,7 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
|
4251
4239
|
const worker = new import_bullmq7.Worker(
|
|
4252
4240
|
`${queue}`,
|
|
4253
4241
|
async (bullmqJob) => {
|
|
4254
|
-
const { db:
|
|
4242
|
+
const { db: db3 } = await postgresClient();
|
|
4255
4243
|
try {
|
|
4256
4244
|
bullmq.validate(bullmqJob);
|
|
4257
4245
|
if (bullmqJob.data.type === "embedder") {
|
|
@@ -4293,19 +4281,19 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
|
4293
4281
|
label: context.name,
|
|
4294
4282
|
trigger: bullmqJob.data.trigger || "unknown"
|
|
4295
4283
|
});
|
|
4296
|
-
const mongoRecord = await
|
|
4284
|
+
const mongoRecord = await db3.from("jobs").where({ redis: bullmqJob.id }).first();
|
|
4297
4285
|
if (!mongoRecord) {
|
|
4298
4286
|
throw new Error("Job not found in the database.");
|
|
4299
4287
|
}
|
|
4300
4288
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
4301
4289
|
const duration = (finishedAt.getTime() - new Date(mongoRecord.createdAt).getTime()) / 1e3;
|
|
4302
|
-
await
|
|
4290
|
+
await db3.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
4303
4291
|
status: "completed",
|
|
4304
4292
|
finishedAt,
|
|
4305
4293
|
duration,
|
|
4306
4294
|
result: JSON.stringify(result)
|
|
4307
4295
|
});
|
|
4308
|
-
await
|
|
4296
|
+
await db3.from((void 0).getTableName()).where({ id: result[0].id }).update({
|
|
4309
4297
|
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4310
4298
|
}).returning("id");
|
|
4311
4299
|
return result;
|
|
@@ -4315,14 +4303,14 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
|
4315
4303
|
if (!workflow) {
|
|
4316
4304
|
throw new Error(`Workflow ${bullmqJob.data.workflow} not found in the registry.`);
|
|
4317
4305
|
}
|
|
4318
|
-
const exuluJob = await
|
|
4306
|
+
const exuluJob = await db3.from("jobs").where({ redis: bullmqJob.id }).first();
|
|
4319
4307
|
if (!exuluJob) {
|
|
4320
4308
|
throw new Error("Job not found in the database.");
|
|
4321
4309
|
}
|
|
4322
4310
|
const result = await bullmq.process.workflow(bullmqJob, exuluJob, workflow, logsDir);
|
|
4323
4311
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
4324
4312
|
const duration = (finishedAt.getTime() - new Date(exuluJob.createdAt).getTime()) / 1e3;
|
|
4325
|
-
await
|
|
4313
|
+
await db3.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
4326
4314
|
status: "completed",
|
|
4327
4315
|
finishedAt,
|
|
4328
4316
|
duration,
|
|
@@ -4331,7 +4319,7 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
|
4331
4319
|
return result;
|
|
4332
4320
|
}
|
|
4333
4321
|
} catch (error) {
|
|
4334
|
-
await
|
|
4322
|
+
await db3.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
4335
4323
|
status: "failed",
|
|
4336
4324
|
finishedAt: /* @__PURE__ */ new Date(),
|
|
4337
4325
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -4703,259 +4691,6 @@ var getTicket = new ExuluTool({
|
|
|
4703
4691
|
}
|
|
4704
4692
|
});
|
|
4705
4693
|
|
|
4706
|
-
// src/auth/generate-key.ts
|
|
4707
|
-
var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
|
|
4708
|
-
var SALT_ROUNDS = 12;
|
|
4709
|
-
async function encryptString(string) {
|
|
4710
|
-
const hash = await import_bcryptjs2.default.hash(string, SALT_ROUNDS);
|
|
4711
|
-
return hash;
|
|
4712
|
-
}
|
|
4713
|
-
var generateApiKey = async (name, email) => {
|
|
4714
|
-
const { db: db2 } = await postgresClient();
|
|
4715
|
-
console.log("[EXULU] Inserting default user and admin role.");
|
|
4716
|
-
const existingRole = await db2.from("roles").where({ name: "admin" }).first();
|
|
4717
|
-
let roleId;
|
|
4718
|
-
if (!existingRole) {
|
|
4719
|
-
console.log("[EXULU] Creating default admin role.");
|
|
4720
|
-
const role = await db2.from("roles").insert({
|
|
4721
|
-
name: "admin",
|
|
4722
|
-
is_admin: true,
|
|
4723
|
-
agents: []
|
|
4724
|
-
}).returning("id");
|
|
4725
|
-
roleId = role[0].id;
|
|
4726
|
-
} else {
|
|
4727
|
-
roleId = existingRole.id;
|
|
4728
|
-
}
|
|
4729
|
-
const newKeyName = name;
|
|
4730
|
-
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
4731
|
-
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
4732
|
-
const encryptedKey = await encryptString(plainKey);
|
|
4733
|
-
const existingApiUser = await db2.from("users").where({ email }).first();
|
|
4734
|
-
if (!existingApiUser) {
|
|
4735
|
-
console.log("[EXULU] Creating default api user.");
|
|
4736
|
-
await db2.from("users").insert({
|
|
4737
|
-
name,
|
|
4738
|
-
email,
|
|
4739
|
-
super_admin: true,
|
|
4740
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
4741
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
4742
|
-
type: "api",
|
|
4743
|
-
emailVerified: /* @__PURE__ */ new Date(),
|
|
4744
|
-
apikey: `${encryptedKey}${postFix}`,
|
|
4745
|
-
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
4746
|
-
role: roleId
|
|
4747
|
-
});
|
|
4748
|
-
console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
|
|
4749
|
-
} else {
|
|
4750
|
-
console.log("[EXULU] API user with that name already exists.");
|
|
4751
|
-
}
|
|
4752
|
-
console.log("[EXULU] Key generated, copy and use the plain key from here, you will not be able to access it again.");
|
|
4753
|
-
console.log("[EXULU] Key: ", `${plainKey}${postFix}`);
|
|
4754
|
-
return {
|
|
4755
|
-
key: `${plainKey}${postFix}`
|
|
4756
|
-
};
|
|
4757
|
-
};
|
|
4758
|
-
|
|
4759
|
-
// src/postgres/init-db.ts
|
|
4760
|
-
var up = async function(knex) {
|
|
4761
|
-
if (!await knex.schema.hasTable("agent_sessions")) {
|
|
4762
|
-
console.log("[EXULU] Creating agent_sessions table.");
|
|
4763
|
-
await knex.schema.createTable("agent_sessions", (table) => {
|
|
4764
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4765
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4766
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4767
|
-
for (const field of agentSessionsSchema.fields) {
|
|
4768
|
-
const { type, name, default: defaultValue } = field;
|
|
4769
|
-
if (!type || !name) {
|
|
4770
|
-
continue;
|
|
4771
|
-
}
|
|
4772
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4773
|
-
}
|
|
4774
|
-
});
|
|
4775
|
-
}
|
|
4776
|
-
if (!await knex.schema.hasTable("agent_messages")) {
|
|
4777
|
-
console.log("[EXULU] Creating agent_messages table.");
|
|
4778
|
-
await knex.schema.createTable("agent_messages", (table) => {
|
|
4779
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4780
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4781
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4782
|
-
for (const field of agentMessagesSchema.fields) {
|
|
4783
|
-
const { type, name, default: defaultValue } = field;
|
|
4784
|
-
if (!type || !name) {
|
|
4785
|
-
continue;
|
|
4786
|
-
}
|
|
4787
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4788
|
-
}
|
|
4789
|
-
});
|
|
4790
|
-
}
|
|
4791
|
-
if (!await knex.schema.hasTable("roles")) {
|
|
4792
|
-
console.log("[EXULU] Creating roles table.");
|
|
4793
|
-
await knex.schema.createTable("roles", (table) => {
|
|
4794
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4795
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4796
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4797
|
-
for (const field of rolesSchema.fields) {
|
|
4798
|
-
const { type, name, default: defaultValue } = field;
|
|
4799
|
-
if (!type || !name) {
|
|
4800
|
-
continue;
|
|
4801
|
-
}
|
|
4802
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4803
|
-
}
|
|
4804
|
-
});
|
|
4805
|
-
}
|
|
4806
|
-
if (!await knex.schema.hasTable("eval_results")) {
|
|
4807
|
-
console.log("[EXULU] Creating eval_results table.");
|
|
4808
|
-
await knex.schema.createTable("eval_results", (table) => {
|
|
4809
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4810
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4811
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4812
|
-
for (const field of evalResultsSchema.fields) {
|
|
4813
|
-
const { type, name, default: defaultValue } = field;
|
|
4814
|
-
if (!type || !name) {
|
|
4815
|
-
continue;
|
|
4816
|
-
}
|
|
4817
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4818
|
-
}
|
|
4819
|
-
});
|
|
4820
|
-
}
|
|
4821
|
-
if (!await knex.schema.hasTable("statistics")) {
|
|
4822
|
-
console.log("[EXULU] Creating statistics table.");
|
|
4823
|
-
await knex.schema.createTable("statistics", (table) => {
|
|
4824
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4825
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4826
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4827
|
-
for (const field of statisticsSchema.fields) {
|
|
4828
|
-
const { type, name, default: defaultValue } = field;
|
|
4829
|
-
if (!type || !name) {
|
|
4830
|
-
continue;
|
|
4831
|
-
}
|
|
4832
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4833
|
-
}
|
|
4834
|
-
});
|
|
4835
|
-
}
|
|
4836
|
-
if (!await knex.schema.hasTable("jobs")) {
|
|
4837
|
-
console.log("[EXULU] Creating jobs table.");
|
|
4838
|
-
await knex.schema.createTable("jobs", (table) => {
|
|
4839
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4840
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4841
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4842
|
-
for (const field of jobsSchema.fields) {
|
|
4843
|
-
const { type, name, default: defaultValue } = field;
|
|
4844
|
-
if (!type || !name) {
|
|
4845
|
-
continue;
|
|
4846
|
-
}
|
|
4847
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4848
|
-
}
|
|
4849
|
-
});
|
|
4850
|
-
}
|
|
4851
|
-
if (!await knex.schema.hasTable("agents")) {
|
|
4852
|
-
console.log("[EXULU] Creating agents table.");
|
|
4853
|
-
await knex.schema.createTable("agents", (table) => {
|
|
4854
|
-
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
4855
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4856
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4857
|
-
for (const field of agentsSchema.fields) {
|
|
4858
|
-
const { type, name, default: defaultValue } = field;
|
|
4859
|
-
if (!type || !name) {
|
|
4860
|
-
continue;
|
|
4861
|
-
}
|
|
4862
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4863
|
-
}
|
|
4864
|
-
});
|
|
4865
|
-
}
|
|
4866
|
-
if (!await knex.schema.hasTable("verification_token")) {
|
|
4867
|
-
console.log("[EXULU] Creating verification_token table.");
|
|
4868
|
-
await knex.schema.createTable("verification_token", (table) => {
|
|
4869
|
-
table.text("identifier").notNullable();
|
|
4870
|
-
table.timestamp("expires", { useTz: true }).notNullable();
|
|
4871
|
-
table.text("token").notNullable();
|
|
4872
|
-
table.primary(["identifier", "token"]);
|
|
4873
|
-
});
|
|
4874
|
-
}
|
|
4875
|
-
if (!await knex.schema.hasTable("users")) {
|
|
4876
|
-
console.log("[EXULU] Creating users table.");
|
|
4877
|
-
await knex.schema.createTable("users", (table) => {
|
|
4878
|
-
table.increments("id").primary();
|
|
4879
|
-
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
4880
|
-
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
4881
|
-
table.string("name", 255);
|
|
4882
|
-
table.string("password", 255);
|
|
4883
|
-
table.string("email", 255);
|
|
4884
|
-
table.timestamp("emailVerified", { useTz: true });
|
|
4885
|
-
table.text("image");
|
|
4886
|
-
for (const field of usersSchema.fields) {
|
|
4887
|
-
console.log("[EXULU] field", field);
|
|
4888
|
-
const { type, name, default: defaultValue } = field;
|
|
4889
|
-
if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
|
|
4890
|
-
continue;
|
|
4891
|
-
}
|
|
4892
|
-
if (!type || !name) {
|
|
4893
|
-
continue;
|
|
4894
|
-
}
|
|
4895
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
4896
|
-
}
|
|
4897
|
-
});
|
|
4898
|
-
}
|
|
4899
|
-
if (!await knex.schema.hasTable("accounts")) {
|
|
4900
|
-
console.log("[EXULU] Creating accounts table.");
|
|
4901
|
-
await knex.schema.createTable("accounts", (table) => {
|
|
4902
|
-
table.increments("id").primary();
|
|
4903
|
-
table.integer("userId").notNullable();
|
|
4904
|
-
table.string("type", 255).notNullable();
|
|
4905
|
-
table.string("provider", 255).notNullable();
|
|
4906
|
-
table.string("providerAccountId", 255).notNullable();
|
|
4907
|
-
table.text("refresh_token");
|
|
4908
|
-
table.text("access_token");
|
|
4909
|
-
table.bigInteger("expires_at");
|
|
4910
|
-
table.text("id_token");
|
|
4911
|
-
table.text("scope");
|
|
4912
|
-
table.text("session_state");
|
|
4913
|
-
table.text("token_type");
|
|
4914
|
-
});
|
|
4915
|
-
}
|
|
4916
|
-
};
|
|
4917
|
-
var execute = async () => {
|
|
4918
|
-
const { db: db2 } = await postgresClient();
|
|
4919
|
-
console.log("[EXULU] Checking Exulu IMP database status.");
|
|
4920
|
-
await up(db2);
|
|
4921
|
-
console.log("[EXULU] Inserting default user and admin role.");
|
|
4922
|
-
const existingRole = await db2.from("roles").where({ name: "admin" }).first();
|
|
4923
|
-
let roleId;
|
|
4924
|
-
if (!existingRole) {
|
|
4925
|
-
console.log("[EXULU] Creating default admin role.");
|
|
4926
|
-
const role = await db2.from("roles").insert({
|
|
4927
|
-
name: "admin",
|
|
4928
|
-
is_admin: true,
|
|
4929
|
-
agents: JSON.stringify([])
|
|
4930
|
-
}).returning("id");
|
|
4931
|
-
roleId = role[0].id;
|
|
4932
|
-
} else {
|
|
4933
|
-
roleId = existingRole.id;
|
|
4934
|
-
}
|
|
4935
|
-
const existingUser = await db2.from("users").where({ email: "admin@exulu.com" }).first();
|
|
4936
|
-
if (!existingUser) {
|
|
4937
|
-
const password = await encryptString("admin");
|
|
4938
|
-
console.log("[EXULU] Creating default admin user.");
|
|
4939
|
-
await db2.from("users").insert({
|
|
4940
|
-
name: "exulu",
|
|
4941
|
-
email: "admin@exulu.com",
|
|
4942
|
-
super_admin: true,
|
|
4943
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
4944
|
-
emailVerified: /* @__PURE__ */ new Date(),
|
|
4945
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
4946
|
-
password,
|
|
4947
|
-
type: "user",
|
|
4948
|
-
role: roleId
|
|
4949
|
-
});
|
|
4950
|
-
}
|
|
4951
|
-
const { key } = await generateApiKey("exulu", "api@exulu.com");
|
|
4952
|
-
console.log("[EXULU] Database initialized.");
|
|
4953
|
-
console.log("[EXULU] Default api key: ", `${key}`);
|
|
4954
|
-
console.log("[EXULU] Default password if using password auth: ", `admin`);
|
|
4955
|
-
console.log("[EXULU] Default email if using password auth: ", `admin@exulu.com`);
|
|
4956
|
-
return;
|
|
4957
|
-
};
|
|
4958
|
-
|
|
4959
4694
|
// src/registry/index.ts
|
|
4960
4695
|
var ExuluApp = class {
|
|
4961
4696
|
_agents = [];
|
|
@@ -4970,7 +4705,6 @@ var ExuluApp = class {
|
|
|
4970
4705
|
// Factory function so we can async
|
|
4971
4706
|
// initialize the MCP server if needed.
|
|
4972
4707
|
create = async ({ contexts, agents, workflows, config, tools }) => {
|
|
4973
|
-
await execute();
|
|
4974
4708
|
this._workflows = workflows ?? [];
|
|
4975
4709
|
this._contexts = contexts ?? {};
|
|
4976
4710
|
this._agents = [
|
|
@@ -6272,6 +6006,257 @@ var SentenceChunker = class _SentenceChunker extends BaseChunker {
|
|
|
6272
6006
|
}
|
|
6273
6007
|
};
|
|
6274
6008
|
|
|
6009
|
+
// src/auth/generate-key.ts
|
|
6010
|
+
var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
|
|
6011
|
+
var SALT_ROUNDS = 12;
|
|
6012
|
+
async function encryptString(string) {
|
|
6013
|
+
const hash = await import_bcryptjs2.default.hash(string, SALT_ROUNDS);
|
|
6014
|
+
return hash;
|
|
6015
|
+
}
|
|
6016
|
+
var generateApiKey = async (name, email) => {
|
|
6017
|
+
const { db: db3 } = await postgresClient();
|
|
6018
|
+
console.log("[EXULU] Inserting default user and admin role.");
|
|
6019
|
+
const existingRole = await db3.from("roles").where({ name: "admin" }).first();
|
|
6020
|
+
let roleId;
|
|
6021
|
+
if (!existingRole) {
|
|
6022
|
+
console.log("[EXULU] Creating default admin role.");
|
|
6023
|
+
const role = await db3.from("roles").insert({
|
|
6024
|
+
name: "admin",
|
|
6025
|
+
is_admin: true,
|
|
6026
|
+
agents: []
|
|
6027
|
+
}).returning("id");
|
|
6028
|
+
roleId = role[0].id;
|
|
6029
|
+
} else {
|
|
6030
|
+
roleId = existingRole.id;
|
|
6031
|
+
}
|
|
6032
|
+
const newKeyName = name;
|
|
6033
|
+
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
6034
|
+
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
6035
|
+
const encryptedKey = await encryptString(plainKey);
|
|
6036
|
+
const existingApiUser = await db3.from("users").where({ email }).first();
|
|
6037
|
+
if (!existingApiUser) {
|
|
6038
|
+
console.log("[EXULU] Creating default api user.");
|
|
6039
|
+
await db3.from("users").insert({
|
|
6040
|
+
name,
|
|
6041
|
+
email,
|
|
6042
|
+
super_admin: true,
|
|
6043
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6044
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
6045
|
+
type: "api",
|
|
6046
|
+
emailVerified: /* @__PURE__ */ new Date(),
|
|
6047
|
+
apikey: `${encryptedKey}${postFix}`,
|
|
6048
|
+
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
6049
|
+
role: roleId
|
|
6050
|
+
});
|
|
6051
|
+
console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
|
|
6052
|
+
} else {
|
|
6053
|
+
console.log("[EXULU] API user with that name already exists.");
|
|
6054
|
+
}
|
|
6055
|
+
return {
|
|
6056
|
+
key: `${plainKey}${postFix}`
|
|
6057
|
+
};
|
|
6058
|
+
};
|
|
6059
|
+
|
|
6060
|
+
// src/postgres/init-db.ts
|
|
6061
|
+
var up = async function(knex) {
|
|
6062
|
+
if (!await knex.schema.hasTable("agent_sessions")) {
|
|
6063
|
+
console.log("[EXULU] Creating agent_sessions table.");
|
|
6064
|
+
await knex.schema.createTable("agent_sessions", (table) => {
|
|
6065
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6066
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6067
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6068
|
+
for (const field of agentSessionsSchema.fields) {
|
|
6069
|
+
const { type, name, default: defaultValue } = field;
|
|
6070
|
+
if (!type || !name) {
|
|
6071
|
+
continue;
|
|
6072
|
+
}
|
|
6073
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6074
|
+
}
|
|
6075
|
+
});
|
|
6076
|
+
}
|
|
6077
|
+
if (!await knex.schema.hasTable("agent_messages")) {
|
|
6078
|
+
console.log("[EXULU] Creating agent_messages table.");
|
|
6079
|
+
await knex.schema.createTable("agent_messages", (table) => {
|
|
6080
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6081
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6082
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6083
|
+
for (const field of agentMessagesSchema.fields) {
|
|
6084
|
+
const { type, name, default: defaultValue } = field;
|
|
6085
|
+
if (!type || !name) {
|
|
6086
|
+
continue;
|
|
6087
|
+
}
|
|
6088
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6089
|
+
}
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
if (!await knex.schema.hasTable("roles")) {
|
|
6093
|
+
console.log("[EXULU] Creating roles table.");
|
|
6094
|
+
await knex.schema.createTable("roles", (table) => {
|
|
6095
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6096
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6097
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6098
|
+
for (const field of rolesSchema.fields) {
|
|
6099
|
+
const { type, name, default: defaultValue } = field;
|
|
6100
|
+
if (!type || !name) {
|
|
6101
|
+
continue;
|
|
6102
|
+
}
|
|
6103
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6104
|
+
}
|
|
6105
|
+
});
|
|
6106
|
+
}
|
|
6107
|
+
if (!await knex.schema.hasTable("eval_results")) {
|
|
6108
|
+
console.log("[EXULU] Creating eval_results table.");
|
|
6109
|
+
await knex.schema.createTable("eval_results", (table) => {
|
|
6110
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6111
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6112
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6113
|
+
for (const field of evalResultsSchema.fields) {
|
|
6114
|
+
const { type, name, default: defaultValue } = field;
|
|
6115
|
+
if (!type || !name) {
|
|
6116
|
+
continue;
|
|
6117
|
+
}
|
|
6118
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6119
|
+
}
|
|
6120
|
+
});
|
|
6121
|
+
}
|
|
6122
|
+
if (!await knex.schema.hasTable("statistics")) {
|
|
6123
|
+
console.log("[EXULU] Creating statistics table.");
|
|
6124
|
+
await knex.schema.createTable("statistics", (table) => {
|
|
6125
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6126
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6127
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6128
|
+
for (const field of statisticsSchema.fields) {
|
|
6129
|
+
const { type, name, default: defaultValue } = field;
|
|
6130
|
+
if (!type || !name) {
|
|
6131
|
+
continue;
|
|
6132
|
+
}
|
|
6133
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6134
|
+
}
|
|
6135
|
+
});
|
|
6136
|
+
}
|
|
6137
|
+
if (!await knex.schema.hasTable("jobs")) {
|
|
6138
|
+
console.log("[EXULU] Creating jobs table.");
|
|
6139
|
+
await knex.schema.createTable("jobs", (table) => {
|
|
6140
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6141
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6142
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6143
|
+
for (const field of jobsSchema.fields) {
|
|
6144
|
+
const { type, name, default: defaultValue } = field;
|
|
6145
|
+
if (!type || !name) {
|
|
6146
|
+
continue;
|
|
6147
|
+
}
|
|
6148
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6149
|
+
}
|
|
6150
|
+
});
|
|
6151
|
+
}
|
|
6152
|
+
if (!await knex.schema.hasTable("agents")) {
|
|
6153
|
+
console.log("[EXULU] Creating agents table.");
|
|
6154
|
+
await knex.schema.createTable("agents", (table) => {
|
|
6155
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6156
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6157
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6158
|
+
for (const field of agentsSchema.fields) {
|
|
6159
|
+
const { type, name, default: defaultValue } = field;
|
|
6160
|
+
if (!type || !name) {
|
|
6161
|
+
continue;
|
|
6162
|
+
}
|
|
6163
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6164
|
+
}
|
|
6165
|
+
});
|
|
6166
|
+
}
|
|
6167
|
+
if (!await knex.schema.hasTable("verification_token")) {
|
|
6168
|
+
console.log("[EXULU] Creating verification_token table.");
|
|
6169
|
+
await knex.schema.createTable("verification_token", (table) => {
|
|
6170
|
+
table.text("identifier").notNullable();
|
|
6171
|
+
table.timestamp("expires", { useTz: true }).notNullable();
|
|
6172
|
+
table.text("token").notNullable();
|
|
6173
|
+
table.primary(["identifier", "token"]);
|
|
6174
|
+
});
|
|
6175
|
+
}
|
|
6176
|
+
if (!await knex.schema.hasTable("users")) {
|
|
6177
|
+
console.log("[EXULU] Creating users table.");
|
|
6178
|
+
await knex.schema.createTable("users", (table) => {
|
|
6179
|
+
table.increments("id").primary();
|
|
6180
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6181
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6182
|
+
table.string("name", 255);
|
|
6183
|
+
table.string("password", 255);
|
|
6184
|
+
table.string("email", 255);
|
|
6185
|
+
table.timestamp("emailVerified", { useTz: true });
|
|
6186
|
+
table.text("image");
|
|
6187
|
+
for (const field of usersSchema.fields) {
|
|
6188
|
+
console.log("[EXULU] field", field);
|
|
6189
|
+
const { type, name, default: defaultValue } = field;
|
|
6190
|
+
if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
|
|
6191
|
+
continue;
|
|
6192
|
+
}
|
|
6193
|
+
if (!type || !name) {
|
|
6194
|
+
continue;
|
|
6195
|
+
}
|
|
6196
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6197
|
+
}
|
|
6198
|
+
});
|
|
6199
|
+
}
|
|
6200
|
+
if (!await knex.schema.hasTable("accounts")) {
|
|
6201
|
+
console.log("[EXULU] Creating accounts table.");
|
|
6202
|
+
await knex.schema.createTable("accounts", (table) => {
|
|
6203
|
+
table.increments("id").primary();
|
|
6204
|
+
table.integer("userId").notNullable();
|
|
6205
|
+
table.string("type", 255).notNullable();
|
|
6206
|
+
table.string("provider", 255).notNullable();
|
|
6207
|
+
table.string("providerAccountId", 255).notNullable();
|
|
6208
|
+
table.text("refresh_token");
|
|
6209
|
+
table.text("access_token");
|
|
6210
|
+
table.bigInteger("expires_at");
|
|
6211
|
+
table.text("id_token");
|
|
6212
|
+
table.text("scope");
|
|
6213
|
+
table.text("session_state");
|
|
6214
|
+
table.text("token_type");
|
|
6215
|
+
});
|
|
6216
|
+
}
|
|
6217
|
+
};
|
|
6218
|
+
var execute = async () => {
|
|
6219
|
+
const { db: db3 } = await postgresClient();
|
|
6220
|
+
console.log("[EXULU] Checking Exulu IMP database status.");
|
|
6221
|
+
await up(db3);
|
|
6222
|
+
console.log("[EXULU] Inserting default user and admin role.");
|
|
6223
|
+
const existingRole = await db3.from("roles").where({ name: "admin" }).first();
|
|
6224
|
+
let roleId;
|
|
6225
|
+
if (!existingRole) {
|
|
6226
|
+
console.log("[EXULU] Creating default admin role.");
|
|
6227
|
+
const role = await db3.from("roles").insert({
|
|
6228
|
+
name: "admin",
|
|
6229
|
+
is_admin: true,
|
|
6230
|
+
agents: JSON.stringify([])
|
|
6231
|
+
}).returning("id");
|
|
6232
|
+
roleId = role[0].id;
|
|
6233
|
+
} else {
|
|
6234
|
+
roleId = existingRole.id;
|
|
6235
|
+
}
|
|
6236
|
+
const existingUser = await db3.from("users").where({ email: "admin@exulu.com" }).first();
|
|
6237
|
+
if (!existingUser) {
|
|
6238
|
+
const password = await encryptString("admin");
|
|
6239
|
+
console.log("[EXULU] Creating default admin user.");
|
|
6240
|
+
await db3.from("users").insert({
|
|
6241
|
+
name: "exulu",
|
|
6242
|
+
email: "admin@exulu.com",
|
|
6243
|
+
super_admin: true,
|
|
6244
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6245
|
+
emailVerified: /* @__PURE__ */ new Date(),
|
|
6246
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
6247
|
+
password,
|
|
6248
|
+
type: "user",
|
|
6249
|
+
role: roleId
|
|
6250
|
+
});
|
|
6251
|
+
}
|
|
6252
|
+
const { key } = await generateApiKey("exulu", "api@exulu.com");
|
|
6253
|
+
console.log("[EXULU] Database initialized.");
|
|
6254
|
+
console.log("[EXULU] Default api key: ", `${key}`);
|
|
6255
|
+
console.log("[EXULU] Default password if using password auth: ", `admin`);
|
|
6256
|
+
console.log("[EXULU] Default email if using password auth: ", `admin@exulu.com`);
|
|
6257
|
+
return;
|
|
6258
|
+
};
|
|
6259
|
+
|
|
6275
6260
|
// src/index.ts
|
|
6276
6261
|
var ExuluJobs = {
|
|
6277
6262
|
redis: redisClient,
|
|
@@ -6279,6 +6264,11 @@ var ExuluJobs = {
|
|
|
6279
6264
|
validate: validateJob
|
|
6280
6265
|
}
|
|
6281
6266
|
};
|
|
6267
|
+
var db2 = {
|
|
6268
|
+
init: async () => {
|
|
6269
|
+
await execute();
|
|
6270
|
+
}
|
|
6271
|
+
};
|
|
6282
6272
|
var ExuluChunkers = {
|
|
6283
6273
|
sentence: SentenceChunker,
|
|
6284
6274
|
recursive: {
|
|
@@ -6303,5 +6293,6 @@ var ExuluChunkers = {
|
|
|
6303
6293
|
ExuluSource,
|
|
6304
6294
|
ExuluTool,
|
|
6305
6295
|
ExuluWorkflow,
|
|
6306
|
-
ExuluZodFileType
|
|
6296
|
+
ExuluZodFileType,
|
|
6297
|
+
db
|
|
6307
6298
|
});
|