@exulu/backend 0.2.2 → 0.2.4
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 +346 -142
- package/dist/index.d.cts +61 -9
- package/dist/index.d.ts +61 -9
- package/dist/index.js +338 -135
- package/package.json +10 -9
- package/types/enums/jobs.ts +11 -0
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import "dotenv/config";
|
|
10
|
+
|
|
8
11
|
// src/redis/client.ts
|
|
9
12
|
import { createClient } from "redis";
|
|
10
13
|
|
|
@@ -114,6 +117,10 @@ var usersSchema = {
|
|
|
114
117
|
name: "firstname",
|
|
115
118
|
type: "text"
|
|
116
119
|
},
|
|
120
|
+
{
|
|
121
|
+
name: "name",
|
|
122
|
+
type: "text"
|
|
123
|
+
},
|
|
117
124
|
{
|
|
118
125
|
name: "lastname",
|
|
119
126
|
type: "text"
|
|
@@ -217,6 +224,70 @@ var statisticsSchema = {
|
|
|
217
224
|
}
|
|
218
225
|
]
|
|
219
226
|
};
|
|
227
|
+
var workflowSchema = {
|
|
228
|
+
name: {
|
|
229
|
+
plural: "workflows",
|
|
230
|
+
singular: "workflow"
|
|
231
|
+
},
|
|
232
|
+
fields: [
|
|
233
|
+
{
|
|
234
|
+
name: "workflow_name",
|
|
235
|
+
type: "text"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "run_id",
|
|
239
|
+
type: "text"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "snapshot",
|
|
243
|
+
type: "text"
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
};
|
|
247
|
+
var threadsSchema = {
|
|
248
|
+
name: {
|
|
249
|
+
plural: "threads",
|
|
250
|
+
singular: "thread"
|
|
251
|
+
},
|
|
252
|
+
fields: [
|
|
253
|
+
{
|
|
254
|
+
name: "resourceId",
|
|
255
|
+
type: "text"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "title",
|
|
259
|
+
type: "text"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
name: "metadata",
|
|
263
|
+
type: "text"
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
};
|
|
267
|
+
var messagesSchema = {
|
|
268
|
+
name: {
|
|
269
|
+
plural: "messages",
|
|
270
|
+
singular: "message"
|
|
271
|
+
},
|
|
272
|
+
fields: [
|
|
273
|
+
{
|
|
274
|
+
name: "thread_id",
|
|
275
|
+
type: "text"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: "content",
|
|
279
|
+
type: "text"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: "role",
|
|
283
|
+
type: "text"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
name: "type",
|
|
287
|
+
type: "text"
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
};
|
|
220
291
|
var jobsSchema = {
|
|
221
292
|
name: {
|
|
222
293
|
plural: "jobs",
|
|
@@ -241,7 +312,7 @@ var jobsSchema = {
|
|
|
241
312
|
},
|
|
242
313
|
{
|
|
243
314
|
name: "result",
|
|
244
|
-
type: "
|
|
315
|
+
type: "longText"
|
|
245
316
|
},
|
|
246
317
|
{
|
|
247
318
|
name: "name",
|
|
@@ -251,6 +322,10 @@ var jobsSchema = {
|
|
|
251
322
|
name: "agent",
|
|
252
323
|
type: "text"
|
|
253
324
|
},
|
|
325
|
+
{
|
|
326
|
+
name: "workflow",
|
|
327
|
+
type: "text"
|
|
328
|
+
},
|
|
254
329
|
{
|
|
255
330
|
name: "user",
|
|
256
331
|
type: "text"
|
|
@@ -259,6 +334,10 @@ var jobsSchema = {
|
|
|
259
334
|
name: "item",
|
|
260
335
|
type: "text"
|
|
261
336
|
},
|
|
337
|
+
{
|
|
338
|
+
name: "steps",
|
|
339
|
+
type: "number"
|
|
340
|
+
},
|
|
262
341
|
{
|
|
263
342
|
name: "inputs",
|
|
264
343
|
type: "json"
|
|
@@ -362,14 +441,11 @@ var sanitizeName = (name) => {
|
|
|
362
441
|
return name.toLowerCase().replace(/ /g, "_");
|
|
363
442
|
};
|
|
364
443
|
|
|
365
|
-
// src/postgres/init-db.ts
|
|
366
|
-
import bcrypt2 from "bcryptjs";
|
|
367
|
-
|
|
368
444
|
// src/auth/generate-key.ts
|
|
369
445
|
import bcrypt from "bcryptjs";
|
|
370
446
|
var SALT_ROUNDS = 12;
|
|
371
|
-
async function
|
|
372
|
-
const hash = await bcrypt.hash(
|
|
447
|
+
async function encryptString(string) {
|
|
448
|
+
const hash = await bcrypt.hash(string, SALT_ROUNDS);
|
|
373
449
|
return hash;
|
|
374
450
|
}
|
|
375
451
|
var generateApiKey = async (name, email) => {
|
|
@@ -391,7 +467,7 @@ var generateApiKey = async (name, email) => {
|
|
|
391
467
|
const newKeyName = name;
|
|
392
468
|
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
393
469
|
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
394
|
-
const encryptedKey = await
|
|
470
|
+
const encryptedKey = await encryptString(plainKey);
|
|
395
471
|
const existingApiUser = await db2.from("users").where({ email }).first();
|
|
396
472
|
if (!existingApiUser) {
|
|
397
473
|
console.log("[EXULU] Creating default api user.");
|
|
@@ -402,6 +478,7 @@ var generateApiKey = async (name, email) => {
|
|
|
402
478
|
createdAt: /* @__PURE__ */ new Date(),
|
|
403
479
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
404
480
|
type: "api",
|
|
481
|
+
emailVerified: /* @__PURE__ */ new Date(),
|
|
405
482
|
apikey: `${encryptedKey}${postFix}`,
|
|
406
483
|
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
407
484
|
role: roleId
|
|
@@ -566,11 +643,6 @@ var up = async function(knex) {
|
|
|
566
643
|
});
|
|
567
644
|
}
|
|
568
645
|
};
|
|
569
|
-
var SALT_ROUNDS2 = 12;
|
|
570
|
-
async function encryptApiKey2(apikey) {
|
|
571
|
-
const hash = await bcrypt2.hash(apikey, SALT_ROUNDS2);
|
|
572
|
-
return hash;
|
|
573
|
-
}
|
|
574
646
|
var execute = async () => {
|
|
575
647
|
console.log("[EXULU] Initializing database.");
|
|
576
648
|
const { db: db2 } = await postgresClient();
|
|
@@ -583,33 +655,33 @@ var execute = async () => {
|
|
|
583
655
|
const role = await db2.from("roles").insert({
|
|
584
656
|
name: "admin",
|
|
585
657
|
is_admin: true,
|
|
586
|
-
agents: []
|
|
658
|
+
agents: JSON.stringify([])
|
|
587
659
|
}).returning("id");
|
|
588
660
|
roleId = role[0].id;
|
|
589
661
|
} else {
|
|
590
662
|
roleId = existingRole.id;
|
|
591
663
|
}
|
|
592
|
-
const newKeyName = "exulu_default_key";
|
|
593
|
-
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
594
|
-
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
595
|
-
const encryptedKey = await encryptApiKey2(plainKey);
|
|
596
664
|
const existingUser = await db2.from("users").where({ email: "admin@exulu.com" }).first();
|
|
597
665
|
if (!existingUser) {
|
|
666
|
+
const password = await encryptString("admin");
|
|
598
667
|
console.log("[EXULU] Creating default admin user.");
|
|
599
668
|
await db2.from("users").insert({
|
|
600
669
|
name: "exulu",
|
|
601
670
|
email: "admin@exulu.com",
|
|
602
671
|
super_admin: true,
|
|
603
672
|
createdAt: /* @__PURE__ */ new Date(),
|
|
673
|
+
emailVerified: /* @__PURE__ */ new Date(),
|
|
604
674
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
675
|
+
password,
|
|
605
676
|
type: "user",
|
|
606
|
-
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
607
677
|
role: roleId
|
|
608
678
|
});
|
|
609
679
|
}
|
|
610
680
|
const { key } = await generateApiKey("exulu", "api@exulu.com");
|
|
611
681
|
console.log("[EXULU] Database initialized.");
|
|
612
682
|
console.log("[EXULU] Default api key: ", `${key}`);
|
|
683
|
+
console.log("[EXULU] Default password if using password auth: ", `admin`);
|
|
684
|
+
console.log("[EXULU] Default email if using password auth: ", `admin@exulu.com`);
|
|
613
685
|
return;
|
|
614
686
|
};
|
|
615
687
|
|
|
@@ -620,7 +692,6 @@ import { Agent as MastraAgent } from "@mastra/core";
|
|
|
620
692
|
import { z } from "zod";
|
|
621
693
|
import * as fs from "fs";
|
|
622
694
|
import * as path from "path";
|
|
623
|
-
import "bullmq";
|
|
624
695
|
import { Memory } from "@mastra/memory";
|
|
625
696
|
import { PostgresStore, PgVector } from "@mastra/pg";
|
|
626
697
|
|
|
@@ -656,6 +727,7 @@ var bullmqDecorator = async ({
|
|
|
656
727
|
configuration,
|
|
657
728
|
updater,
|
|
658
729
|
context,
|
|
730
|
+
steps,
|
|
659
731
|
source,
|
|
660
732
|
documents,
|
|
661
733
|
trigger,
|
|
@@ -673,11 +745,13 @@ var bullmqDecorator = async ({
|
|
|
673
745
|
...context && { context },
|
|
674
746
|
...source && { source },
|
|
675
747
|
...documents && { documents },
|
|
748
|
+
...steps && { steps },
|
|
676
749
|
...trigger && { trigger },
|
|
677
750
|
...item && { item },
|
|
678
751
|
agent,
|
|
679
752
|
user,
|
|
680
753
|
inputs,
|
|
754
|
+
label,
|
|
681
755
|
session
|
|
682
756
|
},
|
|
683
757
|
{
|
|
@@ -702,6 +776,7 @@ var bullmqDecorator = async ({
|
|
|
702
776
|
...embedder && { embedder },
|
|
703
777
|
...workflow && { workflow },
|
|
704
778
|
...configuration && { configuration },
|
|
779
|
+
...steps && { steps },
|
|
705
780
|
...updater && { updater },
|
|
706
781
|
...context && { context },
|
|
707
782
|
...source && { source },
|
|
@@ -725,6 +800,17 @@ var bullmqDecorator = async ({
|
|
|
725
800
|
};
|
|
726
801
|
};
|
|
727
802
|
|
|
803
|
+
// types/enums/jobs.ts
|
|
804
|
+
var JOB_STATUS_ENUM = {
|
|
805
|
+
completed: "completed",
|
|
806
|
+
failed: "failed",
|
|
807
|
+
delayed: "delayed",
|
|
808
|
+
active: "active",
|
|
809
|
+
waiting: "waiting",
|
|
810
|
+
paused: "paused",
|
|
811
|
+
stuck: "stuck"
|
|
812
|
+
};
|
|
813
|
+
|
|
728
814
|
// src/registry/classes.ts
|
|
729
815
|
function generateSlug(name) {
|
|
730
816
|
const normalized = name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
@@ -759,6 +845,7 @@ var ExuluAgent = class {
|
|
|
759
845
|
config;
|
|
760
846
|
memory;
|
|
761
847
|
tools;
|
|
848
|
+
agent;
|
|
762
849
|
capabilities;
|
|
763
850
|
constructor({ id, name, description, outputSchema, config, rateLimit, type, capabilities, tools }) {
|
|
764
851
|
this.id = id;
|
|
@@ -771,6 +858,14 @@ var ExuluAgent = class {
|
|
|
771
858
|
this.config = config;
|
|
772
859
|
this.capabilities = capabilities;
|
|
773
860
|
this.slug = `/agents/${generateSlug(this.name)}/run`;
|
|
861
|
+
if (this.type === "agent") {
|
|
862
|
+
this.agent = new MastraAgent({
|
|
863
|
+
name: this.config.name,
|
|
864
|
+
instructions: this.config.instructions,
|
|
865
|
+
model: this.config.model,
|
|
866
|
+
memory: this.memory ? this.memory : void 0
|
|
867
|
+
});
|
|
868
|
+
}
|
|
774
869
|
if (config?.memory) {
|
|
775
870
|
console.log("[EXULU] Initializing memory for agent " + this.name);
|
|
776
871
|
const connectionString = `postgresql://${process.env.POSTGRES_DB_USER}:${process.env.POSTGRES_DB_PASSWORD}@${process.env.POSTGRES_DB_HOST}:${process.env.POSTGRES_DB_PORT}/exulu`;
|
|
@@ -784,7 +879,11 @@ var ExuluAgent = class {
|
|
|
784
879
|
password: process.env.POSTGRES_DB_PASSWORD || "",
|
|
785
880
|
ssl: process.env.POSTGRES_DB_SSL === "true" ? { rejectUnauthorized: false } : false
|
|
786
881
|
}),
|
|
787
|
-
...config?.memory.vector ? {
|
|
882
|
+
...config?.memory.vector ? {
|
|
883
|
+
vector: new PgVector({
|
|
884
|
+
connectionString
|
|
885
|
+
})
|
|
886
|
+
} : {},
|
|
788
887
|
options: {
|
|
789
888
|
lastMessages: config?.memory.lastMessages || 10,
|
|
790
889
|
semanticRecall: {
|
|
@@ -795,33 +894,17 @@ var ExuluAgent = class {
|
|
|
795
894
|
});
|
|
796
895
|
}
|
|
797
896
|
}
|
|
798
|
-
chat =
|
|
799
|
-
|
|
800
|
-
const agent = await db2.from("agents").select("*").where("id", "=", id).first();
|
|
801
|
-
if (!agent) {
|
|
897
|
+
chat = () => {
|
|
898
|
+
if (!this.agent) {
|
|
802
899
|
throw new Error("Agent not found");
|
|
803
900
|
}
|
|
804
|
-
let tools = {};
|
|
805
|
-
agent.tools?.forEach(({ name }) => {
|
|
806
|
-
const tool = this.tools?.find((t) => t.name === name);
|
|
807
|
-
if (!tool) {
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
return tool;
|
|
811
|
-
});
|
|
812
901
|
updateStatistic({
|
|
813
902
|
name: "count",
|
|
814
903
|
label: this.name,
|
|
815
904
|
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
816
905
|
trigger: "agent"
|
|
817
906
|
});
|
|
818
|
-
return
|
|
819
|
-
name: this.config.name,
|
|
820
|
-
instructions: this.config.instructions,
|
|
821
|
-
model: this.config.model,
|
|
822
|
-
tools,
|
|
823
|
-
memory: this.memory ? this.memory : void 0
|
|
824
|
-
});
|
|
907
|
+
return this.agent;
|
|
825
908
|
};
|
|
826
909
|
};
|
|
827
910
|
var ExuluEmbedder = class {
|
|
@@ -878,35 +961,141 @@ var ExuluWorkflow = class {
|
|
|
878
961
|
enable_batch = false;
|
|
879
962
|
slug = "";
|
|
880
963
|
queue;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
constructor({ id, name, description, workflow, queue, enable_batch, inputSchema }) {
|
|
964
|
+
steps;
|
|
965
|
+
constructor({ id, name, description, steps, queue, enable_batch }) {
|
|
884
966
|
this.id = id;
|
|
885
967
|
this.name = name;
|
|
886
968
|
this.description = description;
|
|
887
969
|
this.enable_batch = enable_batch;
|
|
888
970
|
this.slug = `/workflows/${generateSlug(this.name)}/run`;
|
|
889
971
|
this.queue = queue;
|
|
890
|
-
this.
|
|
891
|
-
this.workflow = workflow;
|
|
972
|
+
this.steps = steps;
|
|
892
973
|
}
|
|
974
|
+
start = async ({
|
|
975
|
+
inputs: initialInputs,
|
|
976
|
+
user,
|
|
977
|
+
logger,
|
|
978
|
+
job,
|
|
979
|
+
session,
|
|
980
|
+
agent,
|
|
981
|
+
label
|
|
982
|
+
}) => {
|
|
983
|
+
let inputs;
|
|
984
|
+
const { db: db2 } = await postgresClient();
|
|
985
|
+
if (!job?.id) {
|
|
986
|
+
logger.write(`Creating new job for workflow ${this.name} with inputs: ${JSON.stringify(initialInputs)}`, "INFO");
|
|
987
|
+
const result = await db2("jobs").insert({
|
|
988
|
+
status: JOB_STATUS_ENUM.active,
|
|
989
|
+
name: `Job running '${this.name}' for '${label}'`,
|
|
990
|
+
agent,
|
|
991
|
+
workflow: this.id,
|
|
992
|
+
type: "workflow",
|
|
993
|
+
steps: this.steps?.length || 0,
|
|
994
|
+
inputs: initialInputs,
|
|
995
|
+
session,
|
|
996
|
+
user
|
|
997
|
+
}).returning(["id", "status"]);
|
|
998
|
+
job = result[0];
|
|
999
|
+
logger.write(`Created new job for workflow ${this.name}, job id: ${job?.id}`, "INFO");
|
|
1000
|
+
}
|
|
1001
|
+
if (!job) {
|
|
1002
|
+
throw new Error("Job not found, or failed to be created.");
|
|
1003
|
+
}
|
|
1004
|
+
if (job.status !== JOB_STATUS_ENUM.active) {
|
|
1005
|
+
await db2("jobs").update({
|
|
1006
|
+
status: JOB_STATUS_ENUM.active,
|
|
1007
|
+
inputs: initialInputs
|
|
1008
|
+
}).where({ id: job?.id }).returning("id");
|
|
1009
|
+
}
|
|
1010
|
+
const runStep = async (step, inputs2) => {
|
|
1011
|
+
let result;
|
|
1012
|
+
try {
|
|
1013
|
+
result = await step.fn({
|
|
1014
|
+
inputs: inputs2,
|
|
1015
|
+
logger,
|
|
1016
|
+
job,
|
|
1017
|
+
user
|
|
1018
|
+
});
|
|
1019
|
+
return result;
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
logger.write(`Step ${step.name} failed with error: ${error.message}`, "ERROR");
|
|
1022
|
+
if (step.retries && step.retries > 0) {
|
|
1023
|
+
logger.write(`Retrying step ${step.name} with ${step.retries} retries left`, "INFO");
|
|
1024
|
+
step.retries--;
|
|
1025
|
+
let result2 = await runStep(step, inputs2);
|
|
1026
|
+
return result2;
|
|
1027
|
+
}
|
|
1028
|
+
logger.write(`Step ${step.name} failed with error: ${error.message}`, "ERROR");
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
let final;
|
|
1033
|
+
try {
|
|
1034
|
+
for (let i = 0; i < this.steps.length; i++) {
|
|
1035
|
+
const step = this.steps[i];
|
|
1036
|
+
if (!step) {
|
|
1037
|
+
throw new Error("Step not found.");
|
|
1038
|
+
}
|
|
1039
|
+
if (i === 0) {
|
|
1040
|
+
inputs = initialInputs;
|
|
1041
|
+
}
|
|
1042
|
+
logger.write(`Running step ${step.name} with inputs: ${JSON.stringify(inputs)}`, "INFO");
|
|
1043
|
+
let result = await runStep(step, inputs);
|
|
1044
|
+
inputs = result;
|
|
1045
|
+
logger.write(`Step ${step.name} output: ${JSON.stringify(result)}`, "INFO");
|
|
1046
|
+
final = result;
|
|
1047
|
+
}
|
|
1048
|
+
await db2("jobs").update({
|
|
1049
|
+
status: JOB_STATUS_ENUM.completed,
|
|
1050
|
+
result: JSON.stringify(final),
|
|
1051
|
+
finished_at: db2.fn.now()
|
|
1052
|
+
}).where({ id: job?.id }).returning("id");
|
|
1053
|
+
return final;
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
logger.write(`Workflow ${this.name} failed with error: ${error.message} for job ${job?.id}`, "ERROR");
|
|
1056
|
+
await db2("jobs").update({
|
|
1057
|
+
status: JOB_STATUS_ENUM.failed,
|
|
1058
|
+
result: JSON.stringify({
|
|
1059
|
+
error: error.message || error,
|
|
1060
|
+
stack: error.stack || "No stack trace available"
|
|
1061
|
+
})
|
|
1062
|
+
}).where({ id: job?.id }).returning("id");
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
893
1066
|
};
|
|
894
1067
|
var ExuluLogger = class {
|
|
895
1068
|
logPath;
|
|
896
1069
|
job;
|
|
897
1070
|
constructor(job, logsDir) {
|
|
898
1071
|
this.job = job;
|
|
899
|
-
if (
|
|
900
|
-
fs.
|
|
1072
|
+
if (logsDir && job) {
|
|
1073
|
+
if (!fs.existsSync(logsDir)) {
|
|
1074
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
1075
|
+
}
|
|
1076
|
+
this.logPath = path.join(logsDir, `${job.id}_${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.txt`);
|
|
901
1077
|
}
|
|
902
|
-
this.logPath = path.join(logsDir, `${job.id}_${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.txt`);
|
|
903
1078
|
}
|
|
904
1079
|
async write(message, level) {
|
|
905
1080
|
const logMessage = message.endsWith("\n") ? message : message + "\n";
|
|
1081
|
+
if (!this.logPath) {
|
|
1082
|
+
switch (level) {
|
|
1083
|
+
case "INFO":
|
|
1084
|
+
console.log(message);
|
|
1085
|
+
break;
|
|
1086
|
+
case "WARNING":
|
|
1087
|
+
console.warn(message);
|
|
1088
|
+
break;
|
|
1089
|
+
case "ERROR":
|
|
1090
|
+
console.error(message);
|
|
1091
|
+
break;
|
|
1092
|
+
}
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
906
1095
|
try {
|
|
907
1096
|
await fs.promises.appendFile(this.logPath, `[EXULU][${level}] - ${(/* @__PURE__ */ new Date()).toISOString()}: ${logMessage}`);
|
|
908
1097
|
} catch (error) {
|
|
909
|
-
console.error(`Error writing to log file ${this.job.id}:`, error);
|
|
1098
|
+
console.error(`Error writing to log file ${this.job ? this.job.id : "unknown job"}:`, error);
|
|
910
1099
|
throw error;
|
|
911
1100
|
}
|
|
912
1101
|
}
|
|
@@ -1469,7 +1658,7 @@ import "express";
|
|
|
1469
1658
|
import { getToken } from "next-auth/jwt";
|
|
1470
1659
|
|
|
1471
1660
|
// src/auth/auth.ts
|
|
1472
|
-
import
|
|
1661
|
+
import bcrypt2 from "bcryptjs";
|
|
1473
1662
|
var authentication = async ({
|
|
1474
1663
|
apikey,
|
|
1475
1664
|
authtoken,
|
|
@@ -1562,16 +1751,14 @@ var authentication = async ({
|
|
|
1562
1751
|
code: 401
|
|
1563
1752
|
};
|
|
1564
1753
|
}
|
|
1565
|
-
console.log("[EXULU] users", users);
|
|
1566
1754
|
console.log("[EXULU] request_key_name", request_key_name);
|
|
1567
1755
|
console.log("[EXULU] request_key_compare_value", request_key_compare_value);
|
|
1568
1756
|
const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(request_key_name));
|
|
1569
|
-
console.log("[EXULU] filtered", filtered);
|
|
1570
1757
|
for (const user of filtered) {
|
|
1571
1758
|
const user_key_last_slash_index = user.apikey.lastIndexOf("/");
|
|
1572
1759
|
const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
|
|
1573
1760
|
console.log("[EXULU] user_key_compare_value", user_key_compare_value);
|
|
1574
|
-
const isMatch = await
|
|
1761
|
+
const isMatch = await bcrypt2.compare(request_key_compare_value, user_key_compare_value);
|
|
1575
1762
|
console.log("[EXULU] isMatch", isMatch);
|
|
1576
1763
|
if (isMatch) {
|
|
1577
1764
|
await db2.from("users").where({ id: user.id }).update({
|
|
@@ -1793,6 +1980,7 @@ var VectorMethodEnum = {
|
|
|
1793
1980
|
// src/registry/routes.ts
|
|
1794
1981
|
import express from "express";
|
|
1795
1982
|
import { ApolloServer } from "@apollo/server";
|
|
1983
|
+
import * as Papa from "papaparse";
|
|
1796
1984
|
import cors from "cors";
|
|
1797
1985
|
import "reflect-metadata";
|
|
1798
1986
|
|
|
@@ -2129,8 +2317,8 @@ import { expressMiddleware } from "@as-integrations/express5";
|
|
|
2129
2317
|
|
|
2130
2318
|
// src/registry/uppy.ts
|
|
2131
2319
|
import "express";
|
|
2320
|
+
import bodyParser from "body-parser";
|
|
2132
2321
|
import { getToken as getToken2 } from "next-auth/jwt";
|
|
2133
|
-
var bodyParser = __require("body-parser");
|
|
2134
2322
|
var createUppyRoutes = async (app) => {
|
|
2135
2323
|
const {
|
|
2136
2324
|
S3Client,
|
|
@@ -2526,7 +2714,6 @@ var createUppyRoutes = async (app) => {
|
|
|
2526
2714
|
|
|
2527
2715
|
// src/registry/routes.ts
|
|
2528
2716
|
import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
|
|
2529
|
-
var Papa = __require("papaparse");
|
|
2530
2717
|
var global_queues = {
|
|
2531
2718
|
logs_cleaner: "logs-cleaner"
|
|
2532
2719
|
};
|
|
@@ -2624,7 +2811,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2624
2811
|
} else {
|
|
2625
2812
|
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
2626
2813
|
}
|
|
2627
|
-
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema]);
|
|
2814
|
+
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema, workflowSchema, threadsSchema, messagesSchema]);
|
|
2628
2815
|
console.log("[EXULU] graphql server");
|
|
2629
2816
|
const server = new ApolloServer({
|
|
2630
2817
|
cache: new InMemoryLRUCache(),
|
|
@@ -2680,6 +2867,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2680
2867
|
description: agent.description,
|
|
2681
2868
|
active: agent.active,
|
|
2682
2869
|
public: agent.public,
|
|
2870
|
+
type: agent.type,
|
|
2683
2871
|
slug: backend?.slug,
|
|
2684
2872
|
rateLimit: backend?.rateLimit,
|
|
2685
2873
|
streaming: backend?.streaming,
|
|
@@ -2737,13 +2925,22 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2737
2925
|
if (!exists) {
|
|
2738
2926
|
throw new Error("Table with name " + context.getTableName() + " does not exist.");
|
|
2739
2927
|
}
|
|
2740
|
-
const
|
|
2928
|
+
const query = db2.from(context.getTableName()).select("id");
|
|
2741
2929
|
if (id) {
|
|
2742
|
-
|
|
2930
|
+
query.where({ id });
|
|
2743
2931
|
}
|
|
2744
2932
|
if (external_id) {
|
|
2745
|
-
|
|
2933
|
+
query.where({ external_id });
|
|
2934
|
+
}
|
|
2935
|
+
const item = await query.first();
|
|
2936
|
+
if (!item) {
|
|
2937
|
+
throw new Error("Item not found.");
|
|
2746
2938
|
}
|
|
2939
|
+
const chunks = await db2.from(context.getChunksTableName()).where({ source: item.id }).select("id");
|
|
2940
|
+
if (chunks.length > 0) {
|
|
2941
|
+
await db2.from(context.getChunksTableName()).where({ source: item.id }).delete();
|
|
2942
|
+
}
|
|
2943
|
+
const mutation = db2.from(context.getTableName()).where({ id: item.id }).delete().returning("id");
|
|
2747
2944
|
const result = await mutation;
|
|
2748
2945
|
return result;
|
|
2749
2946
|
};
|
|
@@ -2880,21 +3077,27 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
2880
3077
|
}
|
|
2881
3078
|
const context = contexts.find((context2) => context2.id === req.params.context);
|
|
2882
3079
|
if (!context) {
|
|
3080
|
+
console.error("[EXULU] context not found in registry.", req.params.context);
|
|
2883
3081
|
res.status(400).json({
|
|
2884
3082
|
message: "Context not found in registry."
|
|
2885
3083
|
});
|
|
2886
3084
|
return;
|
|
2887
3085
|
}
|
|
3086
|
+
console.log("[EXULU] context", context);
|
|
2888
3087
|
const exists = await context.tableExists();
|
|
2889
3088
|
if (!exists) {
|
|
3089
|
+
console.log("[EXULU] context table does not exist, creating it.");
|
|
2890
3090
|
await context.createItemsTable();
|
|
2891
3091
|
}
|
|
3092
|
+
console.log("[EXULU] inserting item", req.body);
|
|
2892
3093
|
const result = await context.insertItem(authenticationResult.user.id, req.body, !!req.body.upsert);
|
|
3094
|
+
console.log("[EXULU] result", result);
|
|
2893
3095
|
res.status(200).json({
|
|
2894
3096
|
message: "Item created successfully.",
|
|
2895
3097
|
id: result
|
|
2896
3098
|
});
|
|
2897
3099
|
} catch (error) {
|
|
3100
|
+
console.error("[EXULU] error upserting item", error);
|
|
2898
3101
|
res.status(500).json({
|
|
2899
3102
|
message: error?.message || "An error occurred while creating the item."
|
|
2900
3103
|
});
|
|
@@ -3239,7 +3442,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3239
3442
|
slug: workflow.slug,
|
|
3240
3443
|
enable_batch: workflow.enable_batch,
|
|
3241
3444
|
queue: workflow.queue?.name,
|
|
3242
|
-
inputSchema: workflow.inputSchema ? zerialize(workflow.inputSchema) : null
|
|
3445
|
+
inputSchema: workflow.steps[0]?.inputSchema ? zerialize(workflow.steps[0].inputSchema) : null
|
|
3243
3446
|
})));
|
|
3244
3447
|
});
|
|
3245
3448
|
console.log("[EXULU] workflow by id");
|
|
@@ -3266,7 +3469,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3266
3469
|
res.status(200).json({
|
|
3267
3470
|
...workflow,
|
|
3268
3471
|
queue: workflow.queue?.name,
|
|
3269
|
-
inputSchema: workflow.inputSchema ? zerialize(workflow.inputSchema) : null,
|
|
3472
|
+
inputSchema: workflow.steps[0]?.inputSchema ? zerialize(workflow.steps[0].inputSchema) : null,
|
|
3270
3473
|
workflow: void 0
|
|
3271
3474
|
});
|
|
3272
3475
|
});
|
|
@@ -3402,10 +3605,6 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3402
3605
|
note: `Execute workflow ${workflow.name}`
|
|
3403
3606
|
});
|
|
3404
3607
|
app.post(`${workflow.slug}`, async (req, res) => {
|
|
3405
|
-
if (!workflow.queue) {
|
|
3406
|
-
res.status(500).json({ detail: "No queue set for workflow." });
|
|
3407
|
-
return;
|
|
3408
|
-
}
|
|
3409
3608
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3410
3609
|
if (!authenticationResult.user?.id) {
|
|
3411
3610
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3422,6 +3621,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3422
3621
|
label: `Job running '${workflow.name}' for '${req.body.label}'`,
|
|
3423
3622
|
agent: req.body.agent,
|
|
3424
3623
|
workflow: workflow.id,
|
|
3624
|
+
steps: workflow.steps?.length || 0,
|
|
3425
3625
|
type: "workflow",
|
|
3426
3626
|
inputs,
|
|
3427
3627
|
session: req.body.session,
|
|
@@ -3440,22 +3640,19 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3440
3640
|
});
|
|
3441
3641
|
return;
|
|
3442
3642
|
}
|
|
3443
|
-
const { runId, start, watch } = workflow.workflow.createRun();
|
|
3444
3643
|
console.log("[EXULU] running workflow with inputs.", inputs);
|
|
3445
|
-
const
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3644
|
+
const logger = new ExuluLogger();
|
|
3645
|
+
const result = await workflow.start({
|
|
3646
|
+
inputs,
|
|
3647
|
+
user: authenticationResult.user.id,
|
|
3648
|
+
logger,
|
|
3649
|
+
session: req.body.session,
|
|
3650
|
+
agent: req.body.agent,
|
|
3651
|
+
label: req.body.label
|
|
3450
3652
|
});
|
|
3451
|
-
const failedSteps = Object.entries(output.results).filter(([_, step]) => step.status === "failed").map(([id, step]) => `${id}: ${step.error}`);
|
|
3452
|
-
if (failedSteps.length > 0) {
|
|
3453
|
-
const message = `Workflow has failed steps: ${failedSteps.join("\n - ")}`;
|
|
3454
|
-
throw new Error(message);
|
|
3455
|
-
}
|
|
3456
3653
|
res.status(200).json({
|
|
3457
3654
|
"job": {},
|
|
3458
|
-
"output":
|
|
3655
|
+
"output": result
|
|
3459
3656
|
});
|
|
3460
3657
|
return;
|
|
3461
3658
|
});
|
|
@@ -3518,43 +3715,40 @@ import { Worker } from "bullmq";
|
|
|
3518
3715
|
// src/registry/utils.ts
|
|
3519
3716
|
import "bullmq";
|
|
3520
3717
|
var bullmq = {
|
|
3521
|
-
validate: (
|
|
3522
|
-
if (!
|
|
3523
|
-
throw new Error(`Missing job data for job ${
|
|
3718
|
+
validate: (bullmqJob) => {
|
|
3719
|
+
if (!bullmqJob.data) {
|
|
3720
|
+
throw new Error(`Missing job data for job ${bullmqJob.id}.`);
|
|
3524
3721
|
}
|
|
3525
|
-
if (!
|
|
3526
|
-
throw new Error(`Missing property "type" in data for job ${
|
|
3722
|
+
if (!bullmqJob.data.type) {
|
|
3723
|
+
throw new Error(`Missing property "type" in data for job ${bullmqJob.id}.`);
|
|
3527
3724
|
}
|
|
3528
|
-
if (!
|
|
3529
|
-
throw new Error(`Missing property "inputs" in data for job ${
|
|
3725
|
+
if (!bullmqJob.data.inputs) {
|
|
3726
|
+
throw new Error(`Missing property "inputs" in data for job ${bullmqJob.id}.`);
|
|
3530
3727
|
}
|
|
3531
|
-
if (
|
|
3532
|
-
throw new Error(`Property "type" in data for job ${
|
|
3728
|
+
if (bullmqJob.data.type !== "embedder" && bullmqJob.data.type !== "workflow") {
|
|
3729
|
+
throw new Error(`Property "type" in data for job ${bullmqJob.id} must be of value "embedder" or "workflow".`);
|
|
3533
3730
|
}
|
|
3534
|
-
if (!
|
|
3535
|
-
throw new Error(`Property "backend" in data for job ${
|
|
3731
|
+
if (!bullmqJob.data.workflow && !bullmqJob.data.embedder) {
|
|
3732
|
+
throw new Error(`Property "backend" in data for job ${bullmqJob.id} missing. Job data: ${JSON.stringify(bullmqJob)}`);
|
|
3536
3733
|
}
|
|
3537
3734
|
},
|
|
3538
3735
|
process: {
|
|
3539
|
-
workflow: async (
|
|
3736
|
+
workflow: async (bullmqJob, exuluJob, workflow, logsDir) => {
|
|
3540
3737
|
if (!workflow) {
|
|
3541
|
-
throw new Error(`Workflow function with id: ${
|
|
3542
|
-
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
const
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
logger
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
throw new Error(message);
|
|
3556
|
-
}
|
|
3557
|
-
await logger.write(`Workflow completed. ${JSON.stringify(output.results)}`, "INFO");
|
|
3738
|
+
throw new Error(`Workflow function with id: ${bullmqJob.data.backend} not found in registry.`);
|
|
3739
|
+
}
|
|
3740
|
+
console.log("[EXULU] starting workflow with job inputs.", bullmqJob.data.inputs);
|
|
3741
|
+
const logger = new ExuluLogger(exuluJob, logsDir);
|
|
3742
|
+
const output = await workflow.start({
|
|
3743
|
+
job: exuluJob,
|
|
3744
|
+
inputs: bullmqJob.data.inputs,
|
|
3745
|
+
user: bullmqJob.data.user,
|
|
3746
|
+
logger,
|
|
3747
|
+
session: bullmqJob.data.session,
|
|
3748
|
+
agent: bullmqJob.data.agent,
|
|
3749
|
+
label: bullmqJob.data.label
|
|
3750
|
+
});
|
|
3751
|
+
await logger.write(`Workflow completed. ${JSON.stringify(output)}`, "INFO");
|
|
3558
3752
|
return output;
|
|
3559
3753
|
}
|
|
3560
3754
|
}
|
|
@@ -3581,56 +3775,56 @@ var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) =>
|
|
|
3581
3775
|
console.log(`[EXULU] creating worker for queue ${queue}.`);
|
|
3582
3776
|
const worker = new Worker(
|
|
3583
3777
|
`${queue}`,
|
|
3584
|
-
async (
|
|
3778
|
+
async (bullmqJob) => {
|
|
3585
3779
|
const { db: db2 } = await postgresClient();
|
|
3586
3780
|
try {
|
|
3587
|
-
bullmq.validate(
|
|
3588
|
-
if (
|
|
3589
|
-
if (!
|
|
3781
|
+
bullmq.validate(bullmqJob);
|
|
3782
|
+
if (bullmqJob.data.type === "embedder") {
|
|
3783
|
+
if (!bullmqJob.data.updater) {
|
|
3590
3784
|
throw new Error("No updater set for embedder job.");
|
|
3591
3785
|
}
|
|
3592
|
-
const context = contexts.find((context2) => context2.id ===
|
|
3786
|
+
const context = contexts.find((context2) => context2.id === bullmqJob.data.context);
|
|
3593
3787
|
if (!context) {
|
|
3594
|
-
throw new Error(`Context ${
|
|
3788
|
+
throw new Error(`Context ${bullmqJob.data.context} not found in the registry.`);
|
|
3595
3789
|
}
|
|
3596
|
-
if (!
|
|
3790
|
+
if (!bullmqJob.data.embedder) {
|
|
3597
3791
|
throw new Error(`No embedder set for embedder job.`);
|
|
3598
3792
|
}
|
|
3599
|
-
const embedder = embedders.find((embedder2) => embedder2.id ===
|
|
3793
|
+
const embedder = embedders.find((embedder2) => embedder2.id === bullmqJob.data.embedder);
|
|
3600
3794
|
if (!embedder) {
|
|
3601
|
-
throw new Error(`Embedder ${
|
|
3795
|
+
throw new Error(`Embedder ${bullmqJob.data.embedder} not found in the registry.`);
|
|
3602
3796
|
}
|
|
3603
|
-
if (!
|
|
3797
|
+
if (!bullmqJob.data.source) {
|
|
3604
3798
|
throw new Error("No source set for embedder job.");
|
|
3605
3799
|
}
|
|
3606
|
-
const source = context.sources.get(
|
|
3800
|
+
const source = context.sources.get(bullmqJob.data.source);
|
|
3607
3801
|
if (!source) {
|
|
3608
|
-
throw new Error(`Source ${
|
|
3802
|
+
throw new Error(`Source ${bullmqJob.data.source} not found in the registry.`);
|
|
3609
3803
|
}
|
|
3610
|
-
if (!
|
|
3804
|
+
if (!bullmqJob.data.updater) {
|
|
3611
3805
|
throw new Error("No updater set for embedder job.");
|
|
3612
3806
|
}
|
|
3613
|
-
const updater = source.updaters.find((updater2) => updater2.id ===
|
|
3807
|
+
const updater = source.updaters.find((updater2) => updater2.id === bullmqJob.data.updater);
|
|
3614
3808
|
if (!updater) {
|
|
3615
|
-
throw new Error(`Updater ${
|
|
3809
|
+
throw new Error(`Updater ${bullmqJob.data.updater} not found in the registry.`);
|
|
3616
3810
|
}
|
|
3617
|
-
if (!
|
|
3811
|
+
if (!bullmqJob.data.documents) {
|
|
3618
3812
|
throw new Error("No input documents set for embedder job.");
|
|
3619
3813
|
}
|
|
3620
|
-
if (!Array.isArray(
|
|
3814
|
+
if (!Array.isArray(bullmqJob.data.documents)) {
|
|
3621
3815
|
throw new Error("Input documents must be an array.");
|
|
3622
3816
|
}
|
|
3623
|
-
const result = await embedder.upsert(
|
|
3817
|
+
const result = await embedder.upsert(bullmqJob.data.context, bullmqJob.data.documents, {
|
|
3624
3818
|
label: context.name,
|
|
3625
|
-
trigger:
|
|
3819
|
+
trigger: bullmqJob.data.trigger || "unknown"
|
|
3626
3820
|
});
|
|
3627
|
-
const mongoRecord = await db2.from("jobs").where({ redis:
|
|
3821
|
+
const mongoRecord = await db2.from("jobs").where({ redis: bullmqJob.id }).first();
|
|
3628
3822
|
if (!mongoRecord) {
|
|
3629
3823
|
throw new Error("Job not found in the database.");
|
|
3630
3824
|
}
|
|
3631
3825
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
3632
3826
|
const duration = (finishedAt.getTime() - new Date(mongoRecord.createdAt).getTime()) / 1e3;
|
|
3633
|
-
await db2.from("jobs").where({ redis:
|
|
3827
|
+
await db2.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
3634
3828
|
status: "completed",
|
|
3635
3829
|
finishedAt,
|
|
3636
3830
|
duration,
|
|
@@ -3638,19 +3832,19 @@ var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) =>
|
|
|
3638
3832
|
});
|
|
3639
3833
|
return result;
|
|
3640
3834
|
}
|
|
3641
|
-
if (
|
|
3642
|
-
const workflow = workflows.find((workflow2) => workflow2.id ===
|
|
3835
|
+
if (bullmqJob.data.type === "workflow") {
|
|
3836
|
+
const workflow = workflows.find((workflow2) => workflow2.id === bullmqJob.data.workflow);
|
|
3643
3837
|
if (!workflow) {
|
|
3644
|
-
throw new Error(`Workflow ${
|
|
3838
|
+
throw new Error(`Workflow ${bullmqJob.data.workflow} not found in the registry.`);
|
|
3645
3839
|
}
|
|
3646
|
-
const
|
|
3647
|
-
|
|
3648
|
-
if (!mongoRecord) {
|
|
3840
|
+
const exuluJob = await db2.from("jobs").where({ redis: bullmqJob.id }).first();
|
|
3841
|
+
if (!exuluJob) {
|
|
3649
3842
|
throw new Error("Job not found in the database.");
|
|
3650
3843
|
}
|
|
3844
|
+
const result = await bullmq.process.workflow(bullmqJob, exuluJob, workflow, logsDir);
|
|
3651
3845
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
3652
|
-
const duration = (finishedAt.getTime() - new Date(
|
|
3653
|
-
await db2.from("jobs").where({ redis:
|
|
3846
|
+
const duration = (finishedAt.getTime() - new Date(exuluJob.createdAt).getTime()) / 1e3;
|
|
3847
|
+
await db2.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
3654
3848
|
status: "completed",
|
|
3655
3849
|
finishedAt,
|
|
3656
3850
|
duration,
|
|
@@ -3659,7 +3853,7 @@ var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) =>
|
|
|
3659
3853
|
return result;
|
|
3660
3854
|
}
|
|
3661
3855
|
} catch (error) {
|
|
3662
|
-
await db2.from("jobs").where({ redis:
|
|
3856
|
+
await db2.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
3663
3857
|
status: "failed",
|
|
3664
3858
|
finishedAt: /* @__PURE__ */ new Date(),
|
|
3665
3859
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -3801,12 +3995,18 @@ var ExuluApp = class {
|
|
|
3801
3995
|
};
|
|
3802
3996
|
|
|
3803
3997
|
// src/index.ts
|
|
3998
|
+
import { SentenceChunker } from "chonkie";
|
|
3804
3999
|
var ExuluJobs = {
|
|
3805
4000
|
redis: redisClient,
|
|
3806
4001
|
jobs: {
|
|
3807
4002
|
validate: validateJob
|
|
3808
4003
|
}
|
|
3809
4004
|
};
|
|
4005
|
+
var ExuluChunkers = {
|
|
4006
|
+
chonkie: {
|
|
4007
|
+
sentence: SentenceChunker
|
|
4008
|
+
}
|
|
4009
|
+
};
|
|
3810
4010
|
var ExuluDatabase = {
|
|
3811
4011
|
init: async () => {
|
|
3812
4012
|
await execute();
|
|
@@ -3816,14 +4016,17 @@ var ExuluDatabase = {
|
|
|
3816
4016
|
}
|
|
3817
4017
|
};
|
|
3818
4018
|
export {
|
|
4019
|
+
JOB_STATUS_ENUM as EXULU_JOB_STATUS_ENUM,
|
|
3819
4020
|
STATISTICS_TYPE_ENUM as EXULU_STATISTICS_TYPE_ENUM,
|
|
3820
4021
|
ExuluAgent,
|
|
3821
4022
|
ExuluApp,
|
|
3822
4023
|
authentication as ExuluAuthentication,
|
|
4024
|
+
ExuluChunkers,
|
|
3823
4025
|
ExuluContext,
|
|
3824
4026
|
ExuluDatabase,
|
|
3825
4027
|
ExuluEmbedder,
|
|
3826
4028
|
ExuluJobs,
|
|
4029
|
+
ExuluLogger,
|
|
3827
4030
|
queues as ExuluQueues,
|
|
3828
4031
|
ExuluSource,
|
|
3829
4032
|
ExuluTool,
|