@exulu/backend 0.2.0 → 0.2.1
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 +69 -89
- package/dist/index.js +69 -89
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -58,25 +58,19 @@ var redisServer = {
|
|
|
58
58
|
// src/redis/client.ts
|
|
59
59
|
var client = {};
|
|
60
60
|
async function redisClient() {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.error(`[EXULU] no redis server configured.`);
|
|
64
|
-
return {
|
|
65
|
-
client: null
|
|
66
|
-
};
|
|
61
|
+
if (!redisServer.host || !redisServer.port) {
|
|
62
|
+
return { client: null };
|
|
67
63
|
}
|
|
68
64
|
if (!client["exulu"]) {
|
|
69
65
|
try {
|
|
70
66
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
71
|
-
console.log(`[EXULU] connecting to redis.`);
|
|
72
67
|
client["exulu"] = (0, import_redis.createClient)({
|
|
73
|
-
// todo add password
|
|
74
68
|
url
|
|
75
69
|
});
|
|
76
70
|
await client["exulu"].connect();
|
|
77
71
|
} catch (error) {
|
|
78
|
-
console.error(`[EXULU] error connecting to redis
|
|
79
|
-
|
|
72
|
+
console.error(`[EXULU] error connecting to redis:`, error);
|
|
73
|
+
return { client: null };
|
|
80
74
|
}
|
|
81
75
|
}
|
|
82
76
|
return {
|
|
@@ -1436,30 +1430,38 @@ var import_express3 = require("express");
|
|
|
1436
1430
|
|
|
1437
1431
|
// src/registry/rate-limiter.ts
|
|
1438
1432
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1439
|
-
|
|
1440
|
-
|
|
1433
|
+
try {
|
|
1434
|
+
const { client: client2 } = await redisClient();
|
|
1435
|
+
if (!client2) {
|
|
1436
|
+
console.warn("[EXULU] Rate limiting disabled - Redis not available");
|
|
1437
|
+
return {
|
|
1438
|
+
status: true,
|
|
1439
|
+
retryAfter: null
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
const redisKey = `exulu/${key}`;
|
|
1443
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1444
|
+
if (current === points) {
|
|
1445
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1446
|
+
}
|
|
1447
|
+
if (current > limit) {
|
|
1448
|
+
const ttl = await client2.ttl(redisKey);
|
|
1449
|
+
return {
|
|
1450
|
+
status: false,
|
|
1451
|
+
retryAfter: ttl
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1441
1454
|
return {
|
|
1442
|
-
status:
|
|
1443
|
-
retryAfter:
|
|
1444
|
-
// 10 seconds
|
|
1455
|
+
status: true,
|
|
1456
|
+
retryAfter: null
|
|
1445
1457
|
};
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
const current = await client2.incrBy(redisKey, points);
|
|
1449
|
-
if (current === points) {
|
|
1450
|
-
await client2.expire(redisKey, windowSeconds);
|
|
1451
|
-
}
|
|
1452
|
-
if (current > limit) {
|
|
1453
|
-
const ttl = await client2.ttl(redisKey);
|
|
1458
|
+
} catch (error) {
|
|
1459
|
+
console.error("[EXULU] Rate limiting error:", error);
|
|
1454
1460
|
return {
|
|
1455
|
-
status:
|
|
1456
|
-
retryAfter:
|
|
1461
|
+
status: true,
|
|
1462
|
+
retryAfter: null
|
|
1457
1463
|
};
|
|
1458
1464
|
}
|
|
1459
|
-
return {
|
|
1460
|
-
status: true,
|
|
1461
|
-
retryAfter: null
|
|
1462
|
-
};
|
|
1463
1465
|
};
|
|
1464
1466
|
|
|
1465
1467
|
// src/registry/route-validators/index.ts
|
|
@@ -2509,6 +2511,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2509
2511
|
};
|
|
2510
2512
|
|
|
2511
2513
|
// src/registry/routes.ts
|
|
2514
|
+
var import_utils = require("@apollo/utils.keyvaluecache");
|
|
2512
2515
|
var Papa = require("papaparse");
|
|
2513
2516
|
var global_queues = {
|
|
2514
2517
|
logs_cleaner: "logs-cleaner"
|
|
@@ -2608,8 +2611,15 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2608
2611
|
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
2609
2612
|
}
|
|
2610
2613
|
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema]);
|
|
2611
|
-
|
|
2614
|
+
console.log("[EXULU] graphql server");
|
|
2615
|
+
const server = new import_server3.ApolloServer({
|
|
2616
|
+
cache: new import_utils.InMemoryLRUCache(),
|
|
2617
|
+
schema,
|
|
2618
|
+
introspection: true
|
|
2619
|
+
});
|
|
2620
|
+
console.log("[EXULU] starting graphql server");
|
|
2612
2621
|
await server.start();
|
|
2622
|
+
console.log("[EXULU] graphql server started");
|
|
2613
2623
|
app.use(
|
|
2614
2624
|
"/graphql",
|
|
2615
2625
|
(0, import_cors.default)(),
|
|
@@ -2942,6 +2952,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2942
2952
|
method: "DELETE",
|
|
2943
2953
|
note: `Delete specific embedding for a context.`
|
|
2944
2954
|
});
|
|
2955
|
+
console.log("[EXULU] delete embedding by id");
|
|
2945
2956
|
app.delete(`items/:context/:id`, async (req, res) => {
|
|
2946
2957
|
const id = req.params.id;
|
|
2947
2958
|
if (!req.params.context) {
|
|
@@ -2973,6 +2984,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2973
2984
|
message: "Embedding deleted."
|
|
2974
2985
|
});
|
|
2975
2986
|
});
|
|
2987
|
+
console.log("[EXULU] statistics timeseries");
|
|
2976
2988
|
app.post("/statistics/timeseries", async (req, res) => {
|
|
2977
2989
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
2978
2990
|
if (!authenticationResult.user?.id) {
|
|
@@ -3021,6 +3033,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3021
3033
|
}
|
|
3022
3034
|
});
|
|
3023
3035
|
});
|
|
3036
|
+
console.log("[EXULU] statistics totals");
|
|
3024
3037
|
app.post("/statistics/totals", async (req, res) => {
|
|
3025
3038
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3026
3039
|
if (!authenticationResult.user?.id) {
|
|
@@ -3049,6 +3062,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3049
3062
|
}
|
|
3050
3063
|
});
|
|
3051
3064
|
});
|
|
3065
|
+
console.log("[EXULU] contexts statistics");
|
|
3052
3066
|
app.get("/contexts/statistics", async (req, res) => {
|
|
3053
3067
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3054
3068
|
if (!authenticationResult.user?.id) {
|
|
@@ -3080,6 +3094,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3080
3094
|
}
|
|
3081
3095
|
});
|
|
3082
3096
|
});
|
|
3097
|
+
console.log("[EXULU] context by id");
|
|
3083
3098
|
app.get(`/contexts/:id`, async (req, res) => {
|
|
3084
3099
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3085
3100
|
if (!authenticationResult.user?.id) {
|
|
@@ -3125,6 +3140,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3125
3140
|
// todo
|
|
3126
3141
|
});
|
|
3127
3142
|
});
|
|
3143
|
+
console.log("[EXULU] items export by context");
|
|
3128
3144
|
app.get(`/items/export/:context`, async (req, res) => {
|
|
3129
3145
|
if (!req.params.context) {
|
|
3130
3146
|
res.status(400).json({
|
|
@@ -3153,6 +3169,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3153
3169
|
const ISOTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
3154
3170
|
res.status(200).attachment(`${context.name}-items-export-${ISOTime}.csv`).send(csv);
|
|
3155
3171
|
});
|
|
3172
|
+
console.log("[EXULU] contexts get list");
|
|
3156
3173
|
app.get(`/contexts`, async (req, res) => {
|
|
3157
3174
|
console.log("contexts!!");
|
|
3158
3175
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
@@ -3182,6 +3199,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3182
3199
|
}))
|
|
3183
3200
|
})));
|
|
3184
3201
|
});
|
|
3202
|
+
console.log("[EXULU] workflows get list");
|
|
3185
3203
|
app.get(`/workflows`, async (req, res) => {
|
|
3186
3204
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3187
3205
|
if (!authenticationResult.user?.id) {
|
|
@@ -3197,6 +3215,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3197
3215
|
inputSchema: workflow.inputSchema ? (0, import_zodex.zerialize)(workflow.inputSchema) : null
|
|
3198
3216
|
})));
|
|
3199
3217
|
});
|
|
3218
|
+
console.log("[EXULU] workflow by id");
|
|
3200
3219
|
app.get(`/workflows/:id`, async (req, res) => {
|
|
3201
3220
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3202
3221
|
if (!authenticationResult.user?.id) {
|
|
@@ -3224,6 +3243,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3224
3243
|
workflow: void 0
|
|
3225
3244
|
});
|
|
3226
3245
|
});
|
|
3246
|
+
console.log("[EXULU] contexts");
|
|
3227
3247
|
contexts.forEach((context) => {
|
|
3228
3248
|
const sources = context.sources.get();
|
|
3229
3249
|
if (!Array.isArray(sources)) {
|
|
@@ -3239,66 +3259,14 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3239
3259
|
note: `Webhook updater for ${context.name}`
|
|
3240
3260
|
});
|
|
3241
3261
|
app.post(`${updater.slug}/${updater.type}/:context`, async (req, res) => {
|
|
3242
|
-
|
|
3243
|
-
if (!id) {
|
|
3244
|
-
res.status(400).json({
|
|
3245
|
-
message: "Missing context id in request."
|
|
3246
|
-
});
|
|
3247
|
-
return;
|
|
3248
|
-
}
|
|
3249
|
-
const context2 = contexts.find((context3) => context3.id === id);
|
|
3250
|
-
if (!context2) {
|
|
3251
|
-
res.status(400).json({
|
|
3252
|
-
message: `Context for provided id: ${id} not found.`
|
|
3253
|
-
});
|
|
3254
|
-
return;
|
|
3255
|
-
}
|
|
3256
|
-
if (!context2.embedder.queue) {
|
|
3257
|
-
res.status(500).json({ detail: "No queue set for embedder." });
|
|
3258
|
-
return;
|
|
3259
|
-
}
|
|
3260
|
-
const authenticationResult = await requestValidators.authenticate(req);
|
|
3261
|
-
if (!authenticationResult.user?.id) {
|
|
3262
|
-
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3263
|
-
return;
|
|
3264
|
-
}
|
|
3265
|
-
const requestValidationResult = requestValidators.embedders(req, updater.configuration);
|
|
3266
|
-
if (requestValidationResult.error) {
|
|
3267
|
-
res.status(requestValidationResult.code || 500).json({ detail: `${requestValidationResult.message}` });
|
|
3268
|
-
return;
|
|
3269
|
-
}
|
|
3270
|
-
const documents = await updater.fn(req.body.configuration);
|
|
3271
|
-
const batches = [];
|
|
3272
|
-
for (let i = 0; i < documents.length; i += context2.embedder.batchSize) {
|
|
3273
|
-
batches.push(documents.slice(i, i + context2.embedder.batchSize));
|
|
3274
|
-
}
|
|
3275
|
-
let promises2 = [];
|
|
3276
|
-
if (batches.length > 0) {
|
|
3277
|
-
promises2 = batches.map((documents2) => {
|
|
3278
|
-
return bullmqDecorator({
|
|
3279
|
-
label: `Job running context '${context2.name}' with embedder '${context2.embedder.name}' for '${req.body.label}'`,
|
|
3280
|
-
type: "embedder",
|
|
3281
|
-
embedder: context2.embedder.id,
|
|
3282
|
-
updater: updater.id,
|
|
3283
|
-
context: context2.id,
|
|
3284
|
-
trigger: updater.type,
|
|
3285
|
-
source: source.id,
|
|
3286
|
-
inputs: req.body.inputs,
|
|
3287
|
-
...updater.configuration && { configuration: req.body.configuration },
|
|
3288
|
-
documents: documents2,
|
|
3289
|
-
queue: context2.embedder.queue,
|
|
3290
|
-
user: authenticationResult.user.id
|
|
3291
|
-
});
|
|
3292
|
-
});
|
|
3293
|
-
}
|
|
3294
|
-
const jobs = await Promise.all(promises2);
|
|
3295
|
-
res.status(200).json(jobs);
|
|
3262
|
+
res.status(200).json([]);
|
|
3296
3263
|
return;
|
|
3297
3264
|
});
|
|
3298
3265
|
}
|
|
3299
3266
|
});
|
|
3300
3267
|
});
|
|
3301
3268
|
});
|
|
3269
|
+
console.log("[EXULU] agents");
|
|
3302
3270
|
agents.forEach((agent) => {
|
|
3303
3271
|
const slug = agent.slug;
|
|
3304
3272
|
if (!slug) return;
|
|
@@ -3399,6 +3367,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3399
3367
|
}
|
|
3400
3368
|
});
|
|
3401
3369
|
});
|
|
3370
|
+
console.log("[EXULU] workflows");
|
|
3402
3371
|
workflows.forEach((workflow) => {
|
|
3403
3372
|
routeLogs.push({
|
|
3404
3373
|
route: workflow.slug,
|
|
@@ -3464,7 +3433,11 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3464
3433
|
return;
|
|
3465
3434
|
});
|
|
3466
3435
|
});
|
|
3467
|
-
|
|
3436
|
+
if (process.env.COMPANION_S3_REGION && process.env.COMPANION_S3_KEY && process.env.COMPANION_S3_SECRET) {
|
|
3437
|
+
await createUppyRoutes(app);
|
|
3438
|
+
} else {
|
|
3439
|
+
console.log("[EXULU] skipping uppy file upload routes, because no S3 compatible region, key or secret is set in the environment.");
|
|
3440
|
+
}
|
|
3468
3441
|
console.log("Routes:");
|
|
3469
3442
|
console.table(routeLogs);
|
|
3470
3443
|
};
|
|
@@ -3564,11 +3537,18 @@ var bullmq = {
|
|
|
3564
3537
|
var fs2 = __toESM(require("fs"), 1);
|
|
3565
3538
|
var import_path = __toESM(require("path"), 1);
|
|
3566
3539
|
var defaultLogsDir = import_path.default.join(process.cwd(), "logs");
|
|
3567
|
-
var redisConnection
|
|
3568
|
-
...redisServer,
|
|
3569
|
-
maxRetriesPerRequest: null
|
|
3570
|
-
});
|
|
3540
|
+
var redisConnection;
|
|
3571
3541
|
var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) => {
|
|
3542
|
+
if (!redisServer.host || !redisServer.port) {
|
|
3543
|
+
console.error("[EXULU] you are trying to start workers, but no redis server is configured in the environment.");
|
|
3544
|
+
throw new Error("No redis server configured in the environment, so cannot start workers.");
|
|
3545
|
+
}
|
|
3546
|
+
if (!redisConnection) {
|
|
3547
|
+
redisConnection = new import_ioredis.default({
|
|
3548
|
+
...redisServer,
|
|
3549
|
+
maxRetriesPerRequest: null
|
|
3550
|
+
});
|
|
3551
|
+
}
|
|
3572
3552
|
const logsDir = _logsDir || defaultLogsDir;
|
|
3573
3553
|
const workers = queues2.map((queue) => {
|
|
3574
3554
|
console.log(`[EXULU] creating worker for queue ${queue}.`);
|
package/dist/index.js
CHANGED
|
@@ -17,25 +17,19 @@ var redisServer = {
|
|
|
17
17
|
// src/redis/client.ts
|
|
18
18
|
var client = {};
|
|
19
19
|
async function redisClient() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.error(`[EXULU] no redis server configured.`);
|
|
23
|
-
return {
|
|
24
|
-
client: null
|
|
25
|
-
};
|
|
20
|
+
if (!redisServer.host || !redisServer.port) {
|
|
21
|
+
return { client: null };
|
|
26
22
|
}
|
|
27
23
|
if (!client["exulu"]) {
|
|
28
24
|
try {
|
|
29
25
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
30
|
-
console.log(`[EXULU] connecting to redis.`);
|
|
31
26
|
client["exulu"] = createClient({
|
|
32
|
-
// todo add password
|
|
33
27
|
url
|
|
34
28
|
});
|
|
35
29
|
await client["exulu"].connect();
|
|
36
30
|
} catch (error) {
|
|
37
|
-
console.error(`[EXULU] error connecting to redis
|
|
38
|
-
|
|
31
|
+
console.error(`[EXULU] error connecting to redis:`, error);
|
|
32
|
+
return { client: null };
|
|
39
33
|
}
|
|
40
34
|
}
|
|
41
35
|
return {
|
|
@@ -1395,30 +1389,38 @@ import "express";
|
|
|
1395
1389
|
|
|
1396
1390
|
// src/registry/rate-limiter.ts
|
|
1397
1391
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1398
|
-
|
|
1399
|
-
|
|
1392
|
+
try {
|
|
1393
|
+
const { client: client2 } = await redisClient();
|
|
1394
|
+
if (!client2) {
|
|
1395
|
+
console.warn("[EXULU] Rate limiting disabled - Redis not available");
|
|
1396
|
+
return {
|
|
1397
|
+
status: true,
|
|
1398
|
+
retryAfter: null
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
const redisKey = `exulu/${key}`;
|
|
1402
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1403
|
+
if (current === points) {
|
|
1404
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1405
|
+
}
|
|
1406
|
+
if (current > limit) {
|
|
1407
|
+
const ttl = await client2.ttl(redisKey);
|
|
1408
|
+
return {
|
|
1409
|
+
status: false,
|
|
1410
|
+
retryAfter: ttl
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1400
1413
|
return {
|
|
1401
|
-
status:
|
|
1402
|
-
retryAfter:
|
|
1403
|
-
// 10 seconds
|
|
1414
|
+
status: true,
|
|
1415
|
+
retryAfter: null
|
|
1404
1416
|
};
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
const current = await client2.incrBy(redisKey, points);
|
|
1408
|
-
if (current === points) {
|
|
1409
|
-
await client2.expire(redisKey, windowSeconds);
|
|
1410
|
-
}
|
|
1411
|
-
if (current > limit) {
|
|
1412
|
-
const ttl = await client2.ttl(redisKey);
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
console.error("[EXULU] Rate limiting error:", error);
|
|
1413
1419
|
return {
|
|
1414
|
-
status:
|
|
1415
|
-
retryAfter:
|
|
1420
|
+
status: true,
|
|
1421
|
+
retryAfter: null
|
|
1416
1422
|
};
|
|
1417
1423
|
}
|
|
1418
|
-
return {
|
|
1419
|
-
status: true,
|
|
1420
|
-
retryAfter: null
|
|
1421
|
-
};
|
|
1422
1424
|
};
|
|
1423
1425
|
|
|
1424
1426
|
// src/registry/route-validators/index.ts
|
|
@@ -2468,6 +2470,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2468
2470
|
};
|
|
2469
2471
|
|
|
2470
2472
|
// src/registry/routes.ts
|
|
2473
|
+
import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
|
|
2471
2474
|
var Papa = __require("papaparse");
|
|
2472
2475
|
var global_queues = {
|
|
2473
2476
|
logs_cleaner: "logs-cleaner"
|
|
@@ -2567,8 +2570,15 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2567
2570
|
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
2568
2571
|
}
|
|
2569
2572
|
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema]);
|
|
2570
|
-
|
|
2573
|
+
console.log("[EXULU] graphql server");
|
|
2574
|
+
const server = new ApolloServer({
|
|
2575
|
+
cache: new InMemoryLRUCache(),
|
|
2576
|
+
schema,
|
|
2577
|
+
introspection: true
|
|
2578
|
+
});
|
|
2579
|
+
console.log("[EXULU] starting graphql server");
|
|
2571
2580
|
await server.start();
|
|
2581
|
+
console.log("[EXULU] graphql server started");
|
|
2572
2582
|
app.use(
|
|
2573
2583
|
"/graphql",
|
|
2574
2584
|
cors(),
|
|
@@ -2901,6 +2911,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2901
2911
|
method: "DELETE",
|
|
2902
2912
|
note: `Delete specific embedding for a context.`
|
|
2903
2913
|
});
|
|
2914
|
+
console.log("[EXULU] delete embedding by id");
|
|
2904
2915
|
app.delete(`items/:context/:id`, async (req, res) => {
|
|
2905
2916
|
const id = req.params.id;
|
|
2906
2917
|
if (!req.params.context) {
|
|
@@ -2932,6 +2943,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2932
2943
|
message: "Embedding deleted."
|
|
2933
2944
|
});
|
|
2934
2945
|
});
|
|
2946
|
+
console.log("[EXULU] statistics timeseries");
|
|
2935
2947
|
app.post("/statistics/timeseries", async (req, res) => {
|
|
2936
2948
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
2937
2949
|
if (!authenticationResult.user?.id) {
|
|
@@ -2980,6 +2992,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2980
2992
|
}
|
|
2981
2993
|
});
|
|
2982
2994
|
});
|
|
2995
|
+
console.log("[EXULU] statistics totals");
|
|
2983
2996
|
app.post("/statistics/totals", async (req, res) => {
|
|
2984
2997
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
2985
2998
|
if (!authenticationResult.user?.id) {
|
|
@@ -3008,6 +3021,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3008
3021
|
}
|
|
3009
3022
|
});
|
|
3010
3023
|
});
|
|
3024
|
+
console.log("[EXULU] contexts statistics");
|
|
3011
3025
|
app.get("/contexts/statistics", async (req, res) => {
|
|
3012
3026
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3013
3027
|
if (!authenticationResult.user?.id) {
|
|
@@ -3039,6 +3053,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3039
3053
|
}
|
|
3040
3054
|
});
|
|
3041
3055
|
});
|
|
3056
|
+
console.log("[EXULU] context by id");
|
|
3042
3057
|
app.get(`/contexts/:id`, async (req, res) => {
|
|
3043
3058
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3044
3059
|
if (!authenticationResult.user?.id) {
|
|
@@ -3084,6 +3099,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3084
3099
|
// todo
|
|
3085
3100
|
});
|
|
3086
3101
|
});
|
|
3102
|
+
console.log("[EXULU] items export by context");
|
|
3087
3103
|
app.get(`/items/export/:context`, async (req, res) => {
|
|
3088
3104
|
if (!req.params.context) {
|
|
3089
3105
|
res.status(400).json({
|
|
@@ -3112,6 +3128,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3112
3128
|
const ISOTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
3113
3129
|
res.status(200).attachment(`${context.name}-items-export-${ISOTime}.csv`).send(csv);
|
|
3114
3130
|
});
|
|
3131
|
+
console.log("[EXULU] contexts get list");
|
|
3115
3132
|
app.get(`/contexts`, async (req, res) => {
|
|
3116
3133
|
console.log("contexts!!");
|
|
3117
3134
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
@@ -3141,6 +3158,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3141
3158
|
}))
|
|
3142
3159
|
})));
|
|
3143
3160
|
});
|
|
3161
|
+
console.log("[EXULU] workflows get list");
|
|
3144
3162
|
app.get(`/workflows`, async (req, res) => {
|
|
3145
3163
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3146
3164
|
if (!authenticationResult.user?.id) {
|
|
@@ -3156,6 +3174,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3156
3174
|
inputSchema: workflow.inputSchema ? zerialize(workflow.inputSchema) : null
|
|
3157
3175
|
})));
|
|
3158
3176
|
});
|
|
3177
|
+
console.log("[EXULU] workflow by id");
|
|
3159
3178
|
app.get(`/workflows/:id`, async (req, res) => {
|
|
3160
3179
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3161
3180
|
if (!authenticationResult.user?.id) {
|
|
@@ -3183,6 +3202,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3183
3202
|
workflow: void 0
|
|
3184
3203
|
});
|
|
3185
3204
|
});
|
|
3205
|
+
console.log("[EXULU] contexts");
|
|
3186
3206
|
contexts.forEach((context) => {
|
|
3187
3207
|
const sources = context.sources.get();
|
|
3188
3208
|
if (!Array.isArray(sources)) {
|
|
@@ -3198,66 +3218,14 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3198
3218
|
note: `Webhook updater for ${context.name}`
|
|
3199
3219
|
});
|
|
3200
3220
|
app.post(`${updater.slug}/${updater.type}/:context`, async (req, res) => {
|
|
3201
|
-
|
|
3202
|
-
if (!id) {
|
|
3203
|
-
res.status(400).json({
|
|
3204
|
-
message: "Missing context id in request."
|
|
3205
|
-
});
|
|
3206
|
-
return;
|
|
3207
|
-
}
|
|
3208
|
-
const context2 = contexts.find((context3) => context3.id === id);
|
|
3209
|
-
if (!context2) {
|
|
3210
|
-
res.status(400).json({
|
|
3211
|
-
message: `Context for provided id: ${id} not found.`
|
|
3212
|
-
});
|
|
3213
|
-
return;
|
|
3214
|
-
}
|
|
3215
|
-
if (!context2.embedder.queue) {
|
|
3216
|
-
res.status(500).json({ detail: "No queue set for embedder." });
|
|
3217
|
-
return;
|
|
3218
|
-
}
|
|
3219
|
-
const authenticationResult = await requestValidators.authenticate(req);
|
|
3220
|
-
if (!authenticationResult.user?.id) {
|
|
3221
|
-
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3222
|
-
return;
|
|
3223
|
-
}
|
|
3224
|
-
const requestValidationResult = requestValidators.embedders(req, updater.configuration);
|
|
3225
|
-
if (requestValidationResult.error) {
|
|
3226
|
-
res.status(requestValidationResult.code || 500).json({ detail: `${requestValidationResult.message}` });
|
|
3227
|
-
return;
|
|
3228
|
-
}
|
|
3229
|
-
const documents = await updater.fn(req.body.configuration);
|
|
3230
|
-
const batches = [];
|
|
3231
|
-
for (let i = 0; i < documents.length; i += context2.embedder.batchSize) {
|
|
3232
|
-
batches.push(documents.slice(i, i + context2.embedder.batchSize));
|
|
3233
|
-
}
|
|
3234
|
-
let promises2 = [];
|
|
3235
|
-
if (batches.length > 0) {
|
|
3236
|
-
promises2 = batches.map((documents2) => {
|
|
3237
|
-
return bullmqDecorator({
|
|
3238
|
-
label: `Job running context '${context2.name}' with embedder '${context2.embedder.name}' for '${req.body.label}'`,
|
|
3239
|
-
type: "embedder",
|
|
3240
|
-
embedder: context2.embedder.id,
|
|
3241
|
-
updater: updater.id,
|
|
3242
|
-
context: context2.id,
|
|
3243
|
-
trigger: updater.type,
|
|
3244
|
-
source: source.id,
|
|
3245
|
-
inputs: req.body.inputs,
|
|
3246
|
-
...updater.configuration && { configuration: req.body.configuration },
|
|
3247
|
-
documents: documents2,
|
|
3248
|
-
queue: context2.embedder.queue,
|
|
3249
|
-
user: authenticationResult.user.id
|
|
3250
|
-
});
|
|
3251
|
-
});
|
|
3252
|
-
}
|
|
3253
|
-
const jobs = await Promise.all(promises2);
|
|
3254
|
-
res.status(200).json(jobs);
|
|
3221
|
+
res.status(200).json([]);
|
|
3255
3222
|
return;
|
|
3256
3223
|
});
|
|
3257
3224
|
}
|
|
3258
3225
|
});
|
|
3259
3226
|
});
|
|
3260
3227
|
});
|
|
3228
|
+
console.log("[EXULU] agents");
|
|
3261
3229
|
agents.forEach((agent) => {
|
|
3262
3230
|
const slug = agent.slug;
|
|
3263
3231
|
if (!slug) return;
|
|
@@ -3358,6 +3326,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3358
3326
|
}
|
|
3359
3327
|
});
|
|
3360
3328
|
});
|
|
3329
|
+
console.log("[EXULU] workflows");
|
|
3361
3330
|
workflows.forEach((workflow) => {
|
|
3362
3331
|
routeLogs.push({
|
|
3363
3332
|
route: workflow.slug,
|
|
@@ -3423,7 +3392,11 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3423
3392
|
return;
|
|
3424
3393
|
});
|
|
3425
3394
|
});
|
|
3426
|
-
|
|
3395
|
+
if (process.env.COMPANION_S3_REGION && process.env.COMPANION_S3_KEY && process.env.COMPANION_S3_SECRET) {
|
|
3396
|
+
await createUppyRoutes(app);
|
|
3397
|
+
} else {
|
|
3398
|
+
console.log("[EXULU] skipping uppy file upload routes, because no S3 compatible region, key or secret is set in the environment.");
|
|
3399
|
+
}
|
|
3427
3400
|
console.log("Routes:");
|
|
3428
3401
|
console.table(routeLogs);
|
|
3429
3402
|
};
|
|
@@ -3523,11 +3496,18 @@ var bullmq = {
|
|
|
3523
3496
|
import * as fs2 from "fs";
|
|
3524
3497
|
import path2 from "path";
|
|
3525
3498
|
var defaultLogsDir = path2.join(process.cwd(), "logs");
|
|
3526
|
-
var redisConnection
|
|
3527
|
-
...redisServer,
|
|
3528
|
-
maxRetriesPerRequest: null
|
|
3529
|
-
});
|
|
3499
|
+
var redisConnection;
|
|
3530
3500
|
var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) => {
|
|
3501
|
+
if (!redisServer.host || !redisServer.port) {
|
|
3502
|
+
console.error("[EXULU] you are trying to start workers, but no redis server is configured in the environment.");
|
|
3503
|
+
throw new Error("No redis server configured in the environment, so cannot start workers.");
|
|
3504
|
+
}
|
|
3505
|
+
if (!redisConnection) {
|
|
3506
|
+
redisConnection = new IORedis({
|
|
3507
|
+
...redisServer,
|
|
3508
|
+
maxRetriesPerRequest: null
|
|
3509
|
+
});
|
|
3510
|
+
}
|
|
3531
3511
|
const logsDir = _logsDir || defaultLogsDir;
|
|
3532
3512
|
const workers = queues2.map((queue) => {
|
|
3533
3513
|
console.log(`[EXULU] creating worker for queue ${queue}.`);
|