@exulu/backend 0.1.6 → 0.1.8
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 +34 -18
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +34 -18
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -56,18 +56,26 @@ var redisServer = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// src/redis/client.ts
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
if (!
|
|
59
|
+
var client = {};
|
|
60
|
+
async function redisClient() {
|
|
61
|
+
if (!redisServer.host || !redisServer.port) {
|
|
62
|
+
return {
|
|
63
|
+
client: null
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (!client["exulu"]) {
|
|
62
67
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
63
68
|
console.log(`[EXULU] connecting to redis.`);
|
|
64
|
-
|
|
69
|
+
client["exulu"] = (0, import_redis.createClient)({
|
|
65
70
|
// todo add password
|
|
66
71
|
url
|
|
67
72
|
});
|
|
68
|
-
await
|
|
73
|
+
await client["exulu"].connect();
|
|
69
74
|
}
|
|
70
|
-
|
|
75
|
+
return {
|
|
76
|
+
client: client["exulu"]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
71
79
|
|
|
72
80
|
// src/bullmq/validators.ts
|
|
73
81
|
var validateJob = (job) => {
|
|
@@ -105,6 +113,12 @@ var import_knex3 = require("pgvector/knex");
|
|
|
105
113
|
var db = {};
|
|
106
114
|
async function postgresClient() {
|
|
107
115
|
if (!db["exulu"]) {
|
|
116
|
+
console.log("[EXULU] Initializing exulu database.");
|
|
117
|
+
console.log(process.env.POSTGRES_DB_HOST);
|
|
118
|
+
console.log(process.env.POSTGRES_DB_PORT);
|
|
119
|
+
console.log(process.env.POSTGRES_DB_USER);
|
|
120
|
+
console.log(process.env.POSTGRES_DB_PASSWORD);
|
|
121
|
+
console.log(process.env.POSTGRES_DB_SSL);
|
|
108
122
|
const knex = (0, import_knex.default)({
|
|
109
123
|
client: "pg",
|
|
110
124
|
connection: {
|
|
@@ -725,6 +739,7 @@ var ExuluAgent = class {
|
|
|
725
739
|
this.capabilities = capabilities;
|
|
726
740
|
this.slug = `/agents/${generateSlug(this.name)}/run`;
|
|
727
741
|
if (config?.memory) {
|
|
742
|
+
console.log("[EXULU] Initializing memory for agent " + this.name);
|
|
728
743
|
const connectionString = `postgresql://${process.env.POSTGRES_DB_USER}:${process.env.POSTGRES_DB_PASSWORD}@${process.env.POSTGRES_DB_HOST}:${process.env.POSTGRES_DB_PORT}/exulu`;
|
|
729
744
|
this.memory = new import_memory.Memory({
|
|
730
745
|
storage: new import_pg.PostgresStore({
|
|
@@ -1382,7 +1397,8 @@ var import_express3 = require("express");
|
|
|
1382
1397
|
|
|
1383
1398
|
// src/registry/rate-limiter.ts
|
|
1384
1399
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1385
|
-
|
|
1400
|
+
const { client: client2 } = await redisClient();
|
|
1401
|
+
if (!client2) {
|
|
1386
1402
|
return {
|
|
1387
1403
|
status: false,
|
|
1388
1404
|
retryAfter: 10
|
|
@@ -1390,12 +1406,12 @@ var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
1390
1406
|
};
|
|
1391
1407
|
}
|
|
1392
1408
|
const redisKey = `exulu/${key}`;
|
|
1393
|
-
const current = await
|
|
1409
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1394
1410
|
if (current === points) {
|
|
1395
|
-
await
|
|
1411
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1396
1412
|
}
|
|
1397
1413
|
if (current > limit) {
|
|
1398
|
-
const ttl = await
|
|
1414
|
+
const ttl = await client2.ttl(redisKey);
|
|
1399
1415
|
return {
|
|
1400
1416
|
status: false,
|
|
1401
1417
|
retryAfter: ttl
|
|
@@ -2310,7 +2326,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2310
2326
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
2311
2327
|
return;
|
|
2312
2328
|
}
|
|
2313
|
-
const
|
|
2329
|
+
const client2 = getS3Client();
|
|
2314
2330
|
const { type, metadata, filename } = req.body;
|
|
2315
2331
|
if (typeof filename !== "string") {
|
|
2316
2332
|
return res.status(400).json({ error: "s3: content filename must be a string" });
|
|
@@ -2332,7 +2348,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2332
2348
|
Metadata: metadata
|
|
2333
2349
|
};
|
|
2334
2350
|
const command = new CreateMultipartUploadCommand(params);
|
|
2335
|
-
return
|
|
2351
|
+
return client2.send(command, (err, data) => {
|
|
2336
2352
|
if (err) {
|
|
2337
2353
|
next(err);
|
|
2338
2354
|
return;
|
|
@@ -2369,7 +2385,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2369
2385
|
}, next);
|
|
2370
2386
|
});
|
|
2371
2387
|
app.get("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2372
|
-
const
|
|
2388
|
+
const client2 = getS3Client();
|
|
2373
2389
|
const { uploadId } = req.params;
|
|
2374
2390
|
const { key } = req.query;
|
|
2375
2391
|
if (typeof key !== "string") {
|
|
@@ -2378,7 +2394,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2378
2394
|
}
|
|
2379
2395
|
const parts = [];
|
|
2380
2396
|
function listPartsPage(startAt) {
|
|
2381
|
-
|
|
2397
|
+
client2.send(new ListPartsCommand({
|
|
2382
2398
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2383
2399
|
Key: key,
|
|
2384
2400
|
UploadId: uploadId,
|
|
@@ -2402,7 +2418,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2402
2418
|
return part && typeof part === "object" && Number(part.PartNumber) && typeof part.ETag === "string";
|
|
2403
2419
|
}
|
|
2404
2420
|
app.post("/s3/multipart/:uploadId/complete", (req, res, next) => {
|
|
2405
|
-
const
|
|
2421
|
+
const client2 = getS3Client();
|
|
2406
2422
|
const { uploadId } = req.params;
|
|
2407
2423
|
const { key } = req.query;
|
|
2408
2424
|
const { parts } = req.body;
|
|
@@ -2412,7 +2428,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2412
2428
|
if (!Array.isArray(parts) || !parts.every(isValidPart)) {
|
|
2413
2429
|
return res.status(400).json({ error: "s3: `parts` must be an array of {ETag, PartNumber} objects." });
|
|
2414
2430
|
}
|
|
2415
|
-
return
|
|
2431
|
+
return client2.send(new CompleteMultipartUploadCommand({
|
|
2416
2432
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2417
2433
|
Key: key,
|
|
2418
2434
|
UploadId: uploadId,
|
|
@@ -2431,13 +2447,13 @@ var createUppyRoutes = async (app) => {
|
|
|
2431
2447
|
});
|
|
2432
2448
|
});
|
|
2433
2449
|
app.delete("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2434
|
-
const
|
|
2450
|
+
const client2 = getS3Client();
|
|
2435
2451
|
const { uploadId } = req.params;
|
|
2436
2452
|
const { key } = req.query;
|
|
2437
2453
|
if (typeof key !== "string") {
|
|
2438
2454
|
return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' });
|
|
2439
2455
|
}
|
|
2440
|
-
return
|
|
2456
|
+
return client2.send(new AbortMultipartUploadCommand({
|
|
2441
2457
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2442
2458
|
Key: key,
|
|
2443
2459
|
UploadId: uploadId
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as bullmq from 'bullmq';
|
|
2
2
|
import { Queue } from 'bullmq';
|
|
3
|
-
import
|
|
3
|
+
import { RedisClientType } from 'redis';
|
|
4
4
|
import * as _mastra_core from '@mastra/core';
|
|
5
5
|
import { ToolAction, Workflow, Agent } from '@mastra/core';
|
|
6
6
|
import { ZodSchema, z } from 'zod';
|
|
@@ -8,6 +8,10 @@ import { LanguageModelV1 } from 'ai';
|
|
|
8
8
|
import { Express } from 'express';
|
|
9
9
|
import { Knex } from 'knex';
|
|
10
10
|
|
|
11
|
+
declare function redisClient(): Promise<{
|
|
12
|
+
client: RedisClientType | null;
|
|
13
|
+
}>;
|
|
14
|
+
|
|
11
15
|
type STATISTICS_TYPE = "context.retrieve" | "source.update" | "embedder.upsert" | "embedder.delete" | "workflow.run" | "context.upsert" | "tool.call" | "agent.run";
|
|
12
16
|
declare const STATISTICS_TYPE_ENUM: {
|
|
13
17
|
CONTEXT_RETRIEVE: string;
|
|
@@ -437,7 +441,7 @@ declare class ExuluQueues {
|
|
|
437
441
|
declare const queues: ExuluQueues;
|
|
438
442
|
|
|
439
443
|
declare const ExuluJobs: {
|
|
440
|
-
redis:
|
|
444
|
+
redis: typeof redisClient;
|
|
441
445
|
jobs: {
|
|
442
446
|
validate: (job: bullmq.Job) => bullmq.Job<any, any, string>;
|
|
443
447
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as bullmq from 'bullmq';
|
|
2
2
|
import { Queue } from 'bullmq';
|
|
3
|
-
import
|
|
3
|
+
import { RedisClientType } from 'redis';
|
|
4
4
|
import * as _mastra_core from '@mastra/core';
|
|
5
5
|
import { ToolAction, Workflow, Agent } from '@mastra/core';
|
|
6
6
|
import { ZodSchema, z } from 'zod';
|
|
@@ -8,6 +8,10 @@ import { LanguageModelV1 } from 'ai';
|
|
|
8
8
|
import { Express } from 'express';
|
|
9
9
|
import { Knex } from 'knex';
|
|
10
10
|
|
|
11
|
+
declare function redisClient(): Promise<{
|
|
12
|
+
client: RedisClientType | null;
|
|
13
|
+
}>;
|
|
14
|
+
|
|
11
15
|
type STATISTICS_TYPE = "context.retrieve" | "source.update" | "embedder.upsert" | "embedder.delete" | "workflow.run" | "context.upsert" | "tool.call" | "agent.run";
|
|
12
16
|
declare const STATISTICS_TYPE_ENUM: {
|
|
13
17
|
CONTEXT_RETRIEVE: string;
|
|
@@ -437,7 +441,7 @@ declare class ExuluQueues {
|
|
|
437
441
|
declare const queues: ExuluQueues;
|
|
438
442
|
|
|
439
443
|
declare const ExuluJobs: {
|
|
440
|
-
redis:
|
|
444
|
+
redis: typeof redisClient;
|
|
441
445
|
jobs: {
|
|
442
446
|
validate: (job: bullmq.Job) => bullmq.Job<any, any, string>;
|
|
443
447
|
};
|
package/dist/index.js
CHANGED
|
@@ -15,18 +15,26 @@ var redisServer = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/redis/client.ts
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
if (!
|
|
18
|
+
var client = {};
|
|
19
|
+
async function redisClient() {
|
|
20
|
+
if (!redisServer.host || !redisServer.port) {
|
|
21
|
+
return {
|
|
22
|
+
client: null
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (!client["exulu"]) {
|
|
21
26
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
22
27
|
console.log(`[EXULU] connecting to redis.`);
|
|
23
|
-
|
|
28
|
+
client["exulu"] = createClient({
|
|
24
29
|
// todo add password
|
|
25
30
|
url
|
|
26
31
|
});
|
|
27
|
-
await
|
|
32
|
+
await client["exulu"].connect();
|
|
28
33
|
}
|
|
29
|
-
|
|
34
|
+
return {
|
|
35
|
+
client: client["exulu"]
|
|
36
|
+
};
|
|
37
|
+
}
|
|
30
38
|
|
|
31
39
|
// src/bullmq/validators.ts
|
|
32
40
|
var validateJob = (job) => {
|
|
@@ -64,6 +72,12 @@ import "pgvector/knex";
|
|
|
64
72
|
var db = {};
|
|
65
73
|
async function postgresClient() {
|
|
66
74
|
if (!db["exulu"]) {
|
|
75
|
+
console.log("[EXULU] Initializing exulu database.");
|
|
76
|
+
console.log(process.env.POSTGRES_DB_HOST);
|
|
77
|
+
console.log(process.env.POSTGRES_DB_PORT);
|
|
78
|
+
console.log(process.env.POSTGRES_DB_USER);
|
|
79
|
+
console.log(process.env.POSTGRES_DB_PASSWORD);
|
|
80
|
+
console.log(process.env.POSTGRES_DB_SSL);
|
|
67
81
|
const knex = Knex({
|
|
68
82
|
client: "pg",
|
|
69
83
|
connection: {
|
|
@@ -684,6 +698,7 @@ var ExuluAgent = class {
|
|
|
684
698
|
this.capabilities = capabilities;
|
|
685
699
|
this.slug = `/agents/${generateSlug(this.name)}/run`;
|
|
686
700
|
if (config?.memory) {
|
|
701
|
+
console.log("[EXULU] Initializing memory for agent " + this.name);
|
|
687
702
|
const connectionString = `postgresql://${process.env.POSTGRES_DB_USER}:${process.env.POSTGRES_DB_PASSWORD}@${process.env.POSTGRES_DB_HOST}:${process.env.POSTGRES_DB_PORT}/exulu`;
|
|
688
703
|
this.memory = new Memory({
|
|
689
704
|
storage: new PostgresStore({
|
|
@@ -1341,7 +1356,8 @@ import "express";
|
|
|
1341
1356
|
|
|
1342
1357
|
// src/registry/rate-limiter.ts
|
|
1343
1358
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1344
|
-
|
|
1359
|
+
const { client: client2 } = await redisClient();
|
|
1360
|
+
if (!client2) {
|
|
1345
1361
|
return {
|
|
1346
1362
|
status: false,
|
|
1347
1363
|
retryAfter: 10
|
|
@@ -1349,12 +1365,12 @@ var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
1349
1365
|
};
|
|
1350
1366
|
}
|
|
1351
1367
|
const redisKey = `exulu/${key}`;
|
|
1352
|
-
const current = await
|
|
1368
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1353
1369
|
if (current === points) {
|
|
1354
|
-
await
|
|
1370
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1355
1371
|
}
|
|
1356
1372
|
if (current > limit) {
|
|
1357
|
-
const ttl = await
|
|
1373
|
+
const ttl = await client2.ttl(redisKey);
|
|
1358
1374
|
return {
|
|
1359
1375
|
status: false,
|
|
1360
1376
|
retryAfter: ttl
|
|
@@ -2269,7 +2285,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2269
2285
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
2270
2286
|
return;
|
|
2271
2287
|
}
|
|
2272
|
-
const
|
|
2288
|
+
const client2 = getS3Client();
|
|
2273
2289
|
const { type, metadata, filename } = req.body;
|
|
2274
2290
|
if (typeof filename !== "string") {
|
|
2275
2291
|
return res.status(400).json({ error: "s3: content filename must be a string" });
|
|
@@ -2291,7 +2307,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2291
2307
|
Metadata: metadata
|
|
2292
2308
|
};
|
|
2293
2309
|
const command = new CreateMultipartUploadCommand(params);
|
|
2294
|
-
return
|
|
2310
|
+
return client2.send(command, (err, data) => {
|
|
2295
2311
|
if (err) {
|
|
2296
2312
|
next(err);
|
|
2297
2313
|
return;
|
|
@@ -2328,7 +2344,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2328
2344
|
}, next);
|
|
2329
2345
|
});
|
|
2330
2346
|
app.get("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2331
|
-
const
|
|
2347
|
+
const client2 = getS3Client();
|
|
2332
2348
|
const { uploadId } = req.params;
|
|
2333
2349
|
const { key } = req.query;
|
|
2334
2350
|
if (typeof key !== "string") {
|
|
@@ -2337,7 +2353,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2337
2353
|
}
|
|
2338
2354
|
const parts = [];
|
|
2339
2355
|
function listPartsPage(startAt) {
|
|
2340
|
-
|
|
2356
|
+
client2.send(new ListPartsCommand({
|
|
2341
2357
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2342
2358
|
Key: key,
|
|
2343
2359
|
UploadId: uploadId,
|
|
@@ -2361,7 +2377,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2361
2377
|
return part && typeof part === "object" && Number(part.PartNumber) && typeof part.ETag === "string";
|
|
2362
2378
|
}
|
|
2363
2379
|
app.post("/s3/multipart/:uploadId/complete", (req, res, next) => {
|
|
2364
|
-
const
|
|
2380
|
+
const client2 = getS3Client();
|
|
2365
2381
|
const { uploadId } = req.params;
|
|
2366
2382
|
const { key } = req.query;
|
|
2367
2383
|
const { parts } = req.body;
|
|
@@ -2371,7 +2387,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2371
2387
|
if (!Array.isArray(parts) || !parts.every(isValidPart)) {
|
|
2372
2388
|
return res.status(400).json({ error: "s3: `parts` must be an array of {ETag, PartNumber} objects." });
|
|
2373
2389
|
}
|
|
2374
|
-
return
|
|
2390
|
+
return client2.send(new CompleteMultipartUploadCommand({
|
|
2375
2391
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2376
2392
|
Key: key,
|
|
2377
2393
|
UploadId: uploadId,
|
|
@@ -2390,13 +2406,13 @@ var createUppyRoutes = async (app) => {
|
|
|
2390
2406
|
});
|
|
2391
2407
|
});
|
|
2392
2408
|
app.delete("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2393
|
-
const
|
|
2409
|
+
const client2 = getS3Client();
|
|
2394
2410
|
const { uploadId } = req.params;
|
|
2395
2411
|
const { key } = req.query;
|
|
2396
2412
|
if (typeof key !== "string") {
|
|
2397
2413
|
return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' });
|
|
2398
2414
|
}
|
|
2399
|
-
return
|
|
2415
|
+
return client2.send(new AbortMultipartUploadCommand({
|
|
2400
2416
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2401
2417
|
Key: key,
|
|
2402
2418
|
UploadId: uploadId
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exulu/backend",
|
|
3
3
|
"author": "Qventu Bv.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
7
7
|
"publishConfig": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "https://github.com/Qventu/exulu-
|
|
18
|
+
"url": "https://github.com/Qventu/exulu-backend"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsup",
|