@exulu/backend 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +55 -38
- package/dist/index.js +55 -38
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -58,19 +58,26 @@ var redisServer = {
|
|
|
58
58
|
// src/redis/client.ts
|
|
59
59
|
var client = {};
|
|
60
60
|
async function redisClient() {
|
|
61
|
-
|
|
61
|
+
console.log("[EXULU] redisClient", redisServer);
|
|
62
|
+
if (!redisServer.host?.length || !redisServer.port?.length) {
|
|
63
|
+
console.error(`[EXULU] no redis server configured.`);
|
|
62
64
|
return {
|
|
63
65
|
client: null
|
|
64
66
|
};
|
|
65
67
|
}
|
|
66
68
|
if (!client["exulu"]) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
try {
|
|
70
|
+
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
71
|
+
console.log(`[EXULU] connecting to redis.`);
|
|
72
|
+
client["exulu"] = (0, import_redis.createClient)({
|
|
73
|
+
// todo add password
|
|
74
|
+
url
|
|
75
|
+
});
|
|
76
|
+
await client["exulu"].connect();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error(`[EXULU] error connecting to redis.`, error);
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
74
81
|
}
|
|
75
82
|
return {
|
|
76
83
|
client: client["exulu"]
|
|
@@ -113,25 +120,30 @@ var import_knex3 = require("pgvector/knex");
|
|
|
113
120
|
var db = {};
|
|
114
121
|
async function postgresClient() {
|
|
115
122
|
if (!db["exulu"]) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
try {
|
|
124
|
+
console.log("[EXULU] Initializing exulu database.");
|
|
125
|
+
console.log(process.env.POSTGRES_DB_HOST);
|
|
126
|
+
console.log(process.env.POSTGRES_DB_PORT);
|
|
127
|
+
console.log(process.env.POSTGRES_DB_USER);
|
|
128
|
+
console.log(process.env.POSTGRES_DB_PASSWORD);
|
|
129
|
+
console.log(process.env.POSTGRES_DB_SSL);
|
|
130
|
+
const knex = (0, import_knex.default)({
|
|
131
|
+
client: "pg",
|
|
132
|
+
connection: {
|
|
133
|
+
host: process.env.POSTGRES_DB_HOST,
|
|
134
|
+
port: parseInt(process.env.POSTGRES_DB_PORT || "5432"),
|
|
135
|
+
user: process.env.POSTGRES_DB_USER,
|
|
136
|
+
database: "exulu",
|
|
137
|
+
password: process.env.POSTGRES_DB_PASSWORD,
|
|
138
|
+
ssl: process.env.POSTGRES_DB_SSL === "true" ? { rejectUnauthorized: false } : false
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
await knex.schema.createExtensionIfNotExists("vector");
|
|
142
|
+
db["exulu"] = knex;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error("[EXULU] Error initializing exulu database.", error);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
135
147
|
}
|
|
136
148
|
return {
|
|
137
149
|
db: db["exulu"]
|
|
@@ -547,8 +559,8 @@ var up = async function(knex) {
|
|
|
547
559
|
}
|
|
548
560
|
};
|
|
549
561
|
var SALT_ROUNDS = 12;
|
|
550
|
-
async function encryptApiKey(
|
|
551
|
-
const hash = await import_bcryptjs.default.hash(
|
|
562
|
+
async function encryptApiKey(apikey) {
|
|
563
|
+
const hash = await import_bcryptjs.default.hash(apikey, SALT_ROUNDS);
|
|
552
564
|
return hash;
|
|
553
565
|
}
|
|
554
566
|
var execute = async () => {
|
|
@@ -596,7 +608,7 @@ var execute = async () => {
|
|
|
596
608
|
super_admin: true,
|
|
597
609
|
createdAt: /* @__PURE__ */ new Date(),
|
|
598
610
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
599
|
-
type: "
|
|
611
|
+
type: "api",
|
|
600
612
|
apikey: `${encryptedKey}${postFix}`,
|
|
601
613
|
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
602
614
|
role: roleId
|
|
@@ -1546,10 +1558,10 @@ var authentication = async ({
|
|
|
1546
1558
|
code: 401
|
|
1547
1559
|
};
|
|
1548
1560
|
}
|
|
1549
|
-
const filtered = users.filter(({
|
|
1561
|
+
const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(keyName));
|
|
1550
1562
|
for (const user of filtered) {
|
|
1551
|
-
const lastSlashIndex = user.
|
|
1552
|
-
const compareValue = lastSlashIndex !== -1 ? user.
|
|
1563
|
+
const lastSlashIndex = user.apikey.lastIndexOf("/");
|
|
1564
|
+
const compareValue = lastSlashIndex !== -1 ? user.apikey.substring(0, lastSlashIndex) : user.apikey;
|
|
1553
1565
|
const isMatch = await import_bcryptjs2.default.compare(keyValue, compareValue);
|
|
1554
1566
|
if (isMatch) {
|
|
1555
1567
|
await db2.from("users").where({ id: user.id }).update({
|
|
@@ -1741,6 +1753,10 @@ var ExuluQueues = class {
|
|
|
1741
1753
|
if (existing) {
|
|
1742
1754
|
return existing;
|
|
1743
1755
|
}
|
|
1756
|
+
if (!redisServer.host?.length || !redisServer.port?.length) {
|
|
1757
|
+
console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or workflow (look for ExuluQueues.use() ).`);
|
|
1758
|
+
throw new Error(`[EXULU] no redis server configured.`);
|
|
1759
|
+
}
|
|
1744
1760
|
const newQueue = new import_bullmq5.Queue(`${name}`, { connection: redisServer });
|
|
1745
1761
|
this.queues.push(newQueue);
|
|
1746
1762
|
return newQueue;
|
|
@@ -2160,9 +2176,6 @@ var createUppyRoutes = async (app) => {
|
|
|
2160
2176
|
return stsClient;
|
|
2161
2177
|
}
|
|
2162
2178
|
app.use(bodyParser.urlencoded({ extended: true }), bodyParser.json());
|
|
2163
|
-
app.get("/", (req, res) => {
|
|
2164
|
-
res.json("Exulu upload server.");
|
|
2165
|
-
});
|
|
2166
2179
|
app.get("/s3/list", async (req, res, next) => {
|
|
2167
2180
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
2168
2181
|
let authtoken = null;
|
|
@@ -2589,7 +2602,11 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2589
2602
|
{ route: "/items/export/:context", method: "GET", note: "Export items from context" },
|
|
2590
2603
|
{ route: "/graphql", method: "POST", note: "GraphQL endpoint" }
|
|
2591
2604
|
);
|
|
2592
|
-
|
|
2605
|
+
if (redisServer.host?.length && redisServer.port?.length) {
|
|
2606
|
+
await createRecurringJobs();
|
|
2607
|
+
} else {
|
|
2608
|
+
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
2609
|
+
}
|
|
2593
2610
|
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema]);
|
|
2594
2611
|
const server = new import_server3.ApolloServer({ schema, introspection: true });
|
|
2595
2612
|
await server.start();
|
|
@@ -2649,7 +2666,6 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2649
2666
|
}
|
|
2650
2667
|
});
|
|
2651
2668
|
});
|
|
2652
|
-
console.log("tools", tools);
|
|
2653
2669
|
app.get("/tools", async (req, res) => {
|
|
2654
2670
|
res.status(200).json(tools.map((tool) => ({
|
|
2655
2671
|
id: tool.id,
|
|
@@ -3310,6 +3326,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3310
3326
|
return;
|
|
3311
3327
|
}
|
|
3312
3328
|
if (agent.rateLimit) {
|
|
3329
|
+
console.log("[EXULU] rate limiting agent.", agent.rateLimit);
|
|
3313
3330
|
const limit = await rateLimiter(
|
|
3314
3331
|
agent.rateLimit.name || agent.id,
|
|
3315
3332
|
agent.rateLimit.rate_limit.time,
|
package/dist/index.js
CHANGED
|
@@ -17,19 +17,26 @@ var redisServer = {
|
|
|
17
17
|
// src/redis/client.ts
|
|
18
18
|
var client = {};
|
|
19
19
|
async function redisClient() {
|
|
20
|
-
|
|
20
|
+
console.log("[EXULU] redisClient", redisServer);
|
|
21
|
+
if (!redisServer.host?.length || !redisServer.port?.length) {
|
|
22
|
+
console.error(`[EXULU] no redis server configured.`);
|
|
21
23
|
return {
|
|
22
24
|
client: null
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
if (!client["exulu"]) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
try {
|
|
29
|
+
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
30
|
+
console.log(`[EXULU] connecting to redis.`);
|
|
31
|
+
client["exulu"] = createClient({
|
|
32
|
+
// todo add password
|
|
33
|
+
url
|
|
34
|
+
});
|
|
35
|
+
await client["exulu"].connect();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error(`[EXULU] error connecting to redis.`, error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
33
40
|
}
|
|
34
41
|
return {
|
|
35
42
|
client: client["exulu"]
|
|
@@ -72,25 +79,30 @@ import "pgvector/knex";
|
|
|
72
79
|
var db = {};
|
|
73
80
|
async function postgresClient() {
|
|
74
81
|
if (!db["exulu"]) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
try {
|
|
83
|
+
console.log("[EXULU] Initializing exulu database.");
|
|
84
|
+
console.log(process.env.POSTGRES_DB_HOST);
|
|
85
|
+
console.log(process.env.POSTGRES_DB_PORT);
|
|
86
|
+
console.log(process.env.POSTGRES_DB_USER);
|
|
87
|
+
console.log(process.env.POSTGRES_DB_PASSWORD);
|
|
88
|
+
console.log(process.env.POSTGRES_DB_SSL);
|
|
89
|
+
const knex = Knex({
|
|
90
|
+
client: "pg",
|
|
91
|
+
connection: {
|
|
92
|
+
host: process.env.POSTGRES_DB_HOST,
|
|
93
|
+
port: parseInt(process.env.POSTGRES_DB_PORT || "5432"),
|
|
94
|
+
user: process.env.POSTGRES_DB_USER,
|
|
95
|
+
database: "exulu",
|
|
96
|
+
password: process.env.POSTGRES_DB_PASSWORD,
|
|
97
|
+
ssl: process.env.POSTGRES_DB_SSL === "true" ? { rejectUnauthorized: false } : false
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
await knex.schema.createExtensionIfNotExists("vector");
|
|
101
|
+
db["exulu"] = knex;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error("[EXULU] Error initializing exulu database.", error);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
94
106
|
}
|
|
95
107
|
return {
|
|
96
108
|
db: db["exulu"]
|
|
@@ -506,8 +518,8 @@ var up = async function(knex) {
|
|
|
506
518
|
}
|
|
507
519
|
};
|
|
508
520
|
var SALT_ROUNDS = 12;
|
|
509
|
-
async function encryptApiKey(
|
|
510
|
-
const hash = await bcrypt.hash(
|
|
521
|
+
async function encryptApiKey(apikey) {
|
|
522
|
+
const hash = await bcrypt.hash(apikey, SALT_ROUNDS);
|
|
511
523
|
return hash;
|
|
512
524
|
}
|
|
513
525
|
var execute = async () => {
|
|
@@ -555,7 +567,7 @@ var execute = async () => {
|
|
|
555
567
|
super_admin: true,
|
|
556
568
|
createdAt: /* @__PURE__ */ new Date(),
|
|
557
569
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
558
|
-
type: "
|
|
570
|
+
type: "api",
|
|
559
571
|
apikey: `${encryptedKey}${postFix}`,
|
|
560
572
|
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
561
573
|
role: roleId
|
|
@@ -1505,10 +1517,10 @@ var authentication = async ({
|
|
|
1505
1517
|
code: 401
|
|
1506
1518
|
};
|
|
1507
1519
|
}
|
|
1508
|
-
const filtered = users.filter(({
|
|
1520
|
+
const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(keyName));
|
|
1509
1521
|
for (const user of filtered) {
|
|
1510
|
-
const lastSlashIndex = user.
|
|
1511
|
-
const compareValue = lastSlashIndex !== -1 ? user.
|
|
1522
|
+
const lastSlashIndex = user.apikey.lastIndexOf("/");
|
|
1523
|
+
const compareValue = lastSlashIndex !== -1 ? user.apikey.substring(0, lastSlashIndex) : user.apikey;
|
|
1512
1524
|
const isMatch = await bcrypt2.compare(keyValue, compareValue);
|
|
1513
1525
|
if (isMatch) {
|
|
1514
1526
|
await db2.from("users").where({ id: user.id }).update({
|
|
@@ -1700,6 +1712,10 @@ var ExuluQueues = class {
|
|
|
1700
1712
|
if (existing) {
|
|
1701
1713
|
return existing;
|
|
1702
1714
|
}
|
|
1715
|
+
if (!redisServer.host?.length || !redisServer.port?.length) {
|
|
1716
|
+
console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or workflow (look for ExuluQueues.use() ).`);
|
|
1717
|
+
throw new Error(`[EXULU] no redis server configured.`);
|
|
1718
|
+
}
|
|
1703
1719
|
const newQueue = new Queue3(`${name}`, { connection: redisServer });
|
|
1704
1720
|
this.queues.push(newQueue);
|
|
1705
1721
|
return newQueue;
|
|
@@ -2119,9 +2135,6 @@ var createUppyRoutes = async (app) => {
|
|
|
2119
2135
|
return stsClient;
|
|
2120
2136
|
}
|
|
2121
2137
|
app.use(bodyParser.urlencoded({ extended: true }), bodyParser.json());
|
|
2122
|
-
app.get("/", (req, res) => {
|
|
2123
|
-
res.json("Exulu upload server.");
|
|
2124
|
-
});
|
|
2125
2138
|
app.get("/s3/list", async (req, res, next) => {
|
|
2126
2139
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
2127
2140
|
let authtoken = null;
|
|
@@ -2548,7 +2561,11 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2548
2561
|
{ route: "/items/export/:context", method: "GET", note: "Export items from context" },
|
|
2549
2562
|
{ route: "/graphql", method: "POST", note: "GraphQL endpoint" }
|
|
2550
2563
|
);
|
|
2551
|
-
|
|
2564
|
+
if (redisServer.host?.length && redisServer.port?.length) {
|
|
2565
|
+
await createRecurringJobs();
|
|
2566
|
+
} else {
|
|
2567
|
+
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
2568
|
+
}
|
|
2552
2569
|
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema]);
|
|
2553
2570
|
const server = new ApolloServer({ schema, introspection: true });
|
|
2554
2571
|
await server.start();
|
|
@@ -2608,7 +2625,6 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2608
2625
|
}
|
|
2609
2626
|
});
|
|
2610
2627
|
});
|
|
2611
|
-
console.log("tools", tools);
|
|
2612
2628
|
app.get("/tools", async (req, res) => {
|
|
2613
2629
|
res.status(200).json(tools.map((tool) => ({
|
|
2614
2630
|
id: tool.id,
|
|
@@ -3269,6 +3285,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3269
3285
|
return;
|
|
3270
3286
|
}
|
|
3271
3287
|
if (agent.rateLimit) {
|
|
3288
|
+
console.log("[EXULU] rate limiting agent.", agent.rateLimit);
|
|
3272
3289
|
const limit = await rateLimiter(
|
|
3273
3290
|
agent.rateLimit.name || agent.id,
|
|
3274
3291
|
agent.rateLimit.rate_limit.time,
|