@exulu/backend 0.3.12 → 1.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/.github/workflows/release.yml +38 -0
- package/.husky/commit-msg +1 -0
- package/CHANGELOG.md +45 -0
- package/README.md +152 -47
- package/commitlint.config.js +4 -0
- package/dist/index.cjs +805 -504
- package/dist/index.d.cts +46 -44
- package/dist/index.d.ts +46 -44
- package/dist/index.js +805 -503
- package/package.json +98 -88
- package/release.config.cjs +9 -0
- package/types/models/user.ts +1 -0
- package/git-conventional-commits.yaml +0 -43
- package/types/models/embedder-backend.ts +0 -15
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,6 @@ __export(index_exports, {
|
|
|
36
36
|
ExuluApp: () => ExuluApp,
|
|
37
37
|
ExuluAuthentication: () => authentication,
|
|
38
38
|
ExuluChunkers: () => ExuluChunkers,
|
|
39
|
-
ExuluCli: () => cli_default,
|
|
40
39
|
ExuluContext: () => ExuluContext,
|
|
41
40
|
ExuluDatabase: () => ExuluDatabase,
|
|
42
41
|
ExuluEmbedder: () => ExuluEmbedder,
|
|
@@ -122,11 +121,6 @@ async function postgresClient() {
|
|
|
122
121
|
if (!db["exulu"]) {
|
|
123
122
|
try {
|
|
124
123
|
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
124
|
const knex = (0, import_knex.default)({
|
|
131
125
|
client: "pg",
|
|
132
126
|
connection: {
|
|
@@ -151,6 +145,47 @@ async function postgresClient() {
|
|
|
151
145
|
}
|
|
152
146
|
|
|
153
147
|
// src/postgres/core-schema.ts
|
|
148
|
+
var agentMessagesSchema = {
|
|
149
|
+
name: {
|
|
150
|
+
plural: "agent_messages",
|
|
151
|
+
singular: "agent_message"
|
|
152
|
+
},
|
|
153
|
+
fields: [
|
|
154
|
+
{
|
|
155
|
+
name: "content",
|
|
156
|
+
type: "text"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "title",
|
|
160
|
+
type: "text"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "session",
|
|
164
|
+
type: "text"
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
};
|
|
168
|
+
var agentSessionsSchema = {
|
|
169
|
+
name: {
|
|
170
|
+
plural: "agent_sessions",
|
|
171
|
+
singular: "agent_session"
|
|
172
|
+
},
|
|
173
|
+
fields: [
|
|
174
|
+
{
|
|
175
|
+
name: "agent",
|
|
176
|
+
type: "uuid"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "user",
|
|
180
|
+
// next auth stores users with id type SERIAL, so we need to use number
|
|
181
|
+
type: "number"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "title",
|
|
185
|
+
type: "text"
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
};
|
|
154
189
|
var usersSchema = {
|
|
155
190
|
name: {
|
|
156
191
|
plural: "users",
|
|
@@ -208,14 +243,13 @@ var usersSchema = {
|
|
|
208
243
|
name: "last_used",
|
|
209
244
|
type: "date"
|
|
210
245
|
},
|
|
246
|
+
{
|
|
247
|
+
name: "anthropic_token",
|
|
248
|
+
type: "text"
|
|
249
|
+
},
|
|
211
250
|
{
|
|
212
251
|
name: "role",
|
|
213
|
-
type: "
|
|
214
|
-
references: {
|
|
215
|
-
table: "roles",
|
|
216
|
-
field: "id",
|
|
217
|
-
onDelete: "CASCADE"
|
|
218
|
-
}
|
|
252
|
+
type: "uuid"
|
|
219
253
|
}
|
|
220
254
|
]
|
|
221
255
|
};
|
|
@@ -261,10 +295,6 @@ var statisticsSchema = {
|
|
|
261
295
|
{
|
|
262
296
|
name: "total",
|
|
263
297
|
type: "number"
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
name: "timeseries",
|
|
267
|
-
type: "json"
|
|
268
298
|
}
|
|
269
299
|
]
|
|
270
300
|
};
|
|
@@ -320,11 +350,11 @@ var evalResultsSchema = {
|
|
|
320
350
|
},
|
|
321
351
|
{
|
|
322
352
|
name: "agent_id",
|
|
323
|
-
type: "
|
|
353
|
+
type: "uuid"
|
|
324
354
|
},
|
|
325
355
|
{
|
|
326
356
|
name: "workflow_id",
|
|
327
|
-
type: "
|
|
357
|
+
type: "uuid"
|
|
328
358
|
},
|
|
329
359
|
{
|
|
330
360
|
name: "eval_type",
|
|
@@ -340,50 +370,6 @@ var evalResultsSchema = {
|
|
|
340
370
|
}
|
|
341
371
|
]
|
|
342
372
|
};
|
|
343
|
-
var threadsSchema = {
|
|
344
|
-
name: {
|
|
345
|
-
plural: "threads",
|
|
346
|
-
singular: "thread"
|
|
347
|
-
},
|
|
348
|
-
fields: [
|
|
349
|
-
{
|
|
350
|
-
name: "resourceId",
|
|
351
|
-
type: "text"
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
name: "title",
|
|
355
|
-
type: "text"
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
name: "metadata",
|
|
359
|
-
type: "text"
|
|
360
|
-
}
|
|
361
|
-
]
|
|
362
|
-
};
|
|
363
|
-
var messagesSchema = {
|
|
364
|
-
name: {
|
|
365
|
-
plural: "messages",
|
|
366
|
-
singular: "message"
|
|
367
|
-
},
|
|
368
|
-
fields: [
|
|
369
|
-
{
|
|
370
|
-
name: "thread_id",
|
|
371
|
-
type: "text"
|
|
372
|
-
},
|
|
373
|
-
{
|
|
374
|
-
name: "content",
|
|
375
|
-
type: "text"
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
name: "role",
|
|
379
|
-
type: "text"
|
|
380
|
-
},
|
|
381
|
-
{
|
|
382
|
-
name: "type",
|
|
383
|
-
type: "text"
|
|
384
|
-
}
|
|
385
|
-
]
|
|
386
|
-
};
|
|
387
373
|
var jobsSchema = {
|
|
388
374
|
name: {
|
|
389
375
|
plural: "jobs",
|
|
@@ -416,19 +402,20 @@ var jobsSchema = {
|
|
|
416
402
|
},
|
|
417
403
|
{
|
|
418
404
|
name: "agent",
|
|
419
|
-
type: "
|
|
405
|
+
type: "uuid"
|
|
420
406
|
},
|
|
421
407
|
{
|
|
422
408
|
name: "workflow",
|
|
423
|
-
type: "
|
|
409
|
+
type: "uuid"
|
|
424
410
|
},
|
|
425
411
|
{
|
|
426
412
|
name: "user",
|
|
427
|
-
type
|
|
413
|
+
// next auth stores users with id type SERIAL, so we need to use number
|
|
414
|
+
type: "number"
|
|
428
415
|
},
|
|
429
416
|
{
|
|
430
417
|
name: "item",
|
|
431
|
-
type: "
|
|
418
|
+
type: "uuid"
|
|
432
419
|
},
|
|
433
420
|
{
|
|
434
421
|
name: "steps",
|
|
@@ -522,7 +509,7 @@ var mapType = (t, type, name, defaultValue) => {
|
|
|
522
509
|
return;
|
|
523
510
|
}
|
|
524
511
|
if (type === "date") {
|
|
525
|
-
t.
|
|
512
|
+
t.timestamp(name);
|
|
526
513
|
return;
|
|
527
514
|
}
|
|
528
515
|
if (type === "uuid") {
|
|
@@ -592,23 +579,44 @@ var generateApiKey = async (name, email) => {
|
|
|
592
579
|
|
|
593
580
|
// src/postgres/init-db.ts
|
|
594
581
|
var up = async function(knex) {
|
|
582
|
+
if (!await knex.schema.hasTable("agent_sessions")) {
|
|
583
|
+
await knex.schema.createTable("agent_sessions", (table) => {
|
|
584
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
585
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
586
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
587
|
+
for (const field of agentSessionsSchema.fields) {
|
|
588
|
+
const { type, name, default: defaultValue } = field;
|
|
589
|
+
if (!type || !name) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
if (!await knex.schema.hasTable("agent_messages")) {
|
|
597
|
+
await knex.schema.createTable("agent_messages", (table) => {
|
|
598
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
599
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
600
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
601
|
+
for (const field of agentMessagesSchema.fields) {
|
|
602
|
+
const { type, name, default: defaultValue } = field;
|
|
603
|
+
if (!type || !name) {
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
mapType(table, type, sanitizeName(name), defaultValue);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
595
610
|
if (!await knex.schema.hasTable("roles")) {
|
|
596
611
|
await knex.schema.createTable("roles", (table) => {
|
|
597
612
|
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
598
|
-
table.
|
|
599
|
-
table.
|
|
613
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
614
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
600
615
|
for (const field of rolesSchema.fields) {
|
|
601
|
-
const { type, name,
|
|
616
|
+
const { type, name, default: defaultValue } = field;
|
|
602
617
|
if (!type || !name) {
|
|
603
618
|
continue;
|
|
604
619
|
}
|
|
605
|
-
if (type === "reference") {
|
|
606
|
-
if (!references) {
|
|
607
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
608
|
-
}
|
|
609
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
620
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
613
621
|
}
|
|
614
622
|
});
|
|
@@ -616,20 +624,13 @@ var up = async function(knex) {
|
|
|
616
624
|
if (!await knex.schema.hasTable("eval_results")) {
|
|
617
625
|
await knex.schema.createTable("eval_results", (table) => {
|
|
618
626
|
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
619
|
-
table.
|
|
620
|
-
table.
|
|
627
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
628
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
621
629
|
for (const field of evalResultsSchema.fields) {
|
|
622
|
-
const { type, name,
|
|
630
|
+
const { type, name, default: defaultValue } = field;
|
|
623
631
|
if (!type || !name) {
|
|
624
632
|
continue;
|
|
625
633
|
}
|
|
626
|
-
if (type === "reference") {
|
|
627
|
-
if (!references) {
|
|
628
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
629
|
-
}
|
|
630
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
634
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
634
635
|
}
|
|
635
636
|
});
|
|
@@ -637,62 +638,41 @@ var up = async function(knex) {
|
|
|
637
638
|
if (!await knex.schema.hasTable("statistics")) {
|
|
638
639
|
await knex.schema.createTable("statistics", (table) => {
|
|
639
640
|
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
640
|
-
table.
|
|
641
|
-
table.
|
|
641
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
642
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
642
643
|
for (const field of statisticsSchema.fields) {
|
|
643
|
-
const { type, name,
|
|
644
|
+
const { type, name, default: defaultValue } = field;
|
|
644
645
|
if (!type || !name) {
|
|
645
646
|
continue;
|
|
646
647
|
}
|
|
647
|
-
if (type === "reference") {
|
|
648
|
-
if (!references) {
|
|
649
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
650
|
-
}
|
|
651
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
648
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
655
649
|
}
|
|
656
650
|
});
|
|
657
651
|
}
|
|
658
652
|
if (!await knex.schema.hasTable("jobs")) {
|
|
659
653
|
await knex.schema.createTable("jobs", (table) => {
|
|
660
|
-
table.
|
|
661
|
-
table.
|
|
662
|
-
table.
|
|
654
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
655
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
656
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
663
657
|
for (const field of jobsSchema.fields) {
|
|
664
|
-
const { type, name,
|
|
658
|
+
const { type, name, default: defaultValue } = field;
|
|
665
659
|
if (!type || !name) {
|
|
666
660
|
continue;
|
|
667
661
|
}
|
|
668
|
-
if (type === "reference") {
|
|
669
|
-
if (!references) {
|
|
670
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
671
|
-
}
|
|
672
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
662
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
676
663
|
}
|
|
677
664
|
});
|
|
678
665
|
}
|
|
679
666
|
if (!await knex.schema.hasTable("agents")) {
|
|
680
667
|
await knex.schema.createTable("agents", (table) => {
|
|
681
|
-
table.
|
|
682
|
-
table.
|
|
683
|
-
table.
|
|
668
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
669
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
670
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
684
671
|
for (const field of agentsSchema.fields) {
|
|
685
|
-
const { type, name,
|
|
672
|
+
const { type, name, default: defaultValue } = field;
|
|
686
673
|
if (!type || !name) {
|
|
687
674
|
continue;
|
|
688
675
|
}
|
|
689
|
-
if (type === "reference") {
|
|
690
|
-
if (!references) {
|
|
691
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
692
|
-
}
|
|
693
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
676
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
697
677
|
}
|
|
698
678
|
});
|
|
@@ -708,8 +688,8 @@ var up = async function(knex) {
|
|
|
708
688
|
if (!await knex.schema.hasTable("users")) {
|
|
709
689
|
await knex.schema.createTable("users", (table) => {
|
|
710
690
|
table.increments("id").primary();
|
|
711
|
-
table.
|
|
712
|
-
table.
|
|
691
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
692
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
713
693
|
table.string("name", 255);
|
|
714
694
|
table.string("password", 255);
|
|
715
695
|
table.string("email", 255);
|
|
@@ -717,20 +697,13 @@ var up = async function(knex) {
|
|
|
717
697
|
table.text("image");
|
|
718
698
|
for (const field of usersSchema.fields) {
|
|
719
699
|
console.log("[EXULU] field", field);
|
|
720
|
-
const { type, name,
|
|
700
|
+
const { type, name, default: defaultValue } = field;
|
|
721
701
|
if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
|
|
722
702
|
continue;
|
|
723
703
|
}
|
|
724
704
|
if (!type || !name) {
|
|
725
705
|
continue;
|
|
726
706
|
}
|
|
727
|
-
if (type === "reference") {
|
|
728
|
-
if (!references) {
|
|
729
|
-
throw new Error("Field with type reference must have a reference definition.");
|
|
730
|
-
}
|
|
731
|
-
table.uuid(name).references(references.field).inTable(references.table);
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
707
|
mapType(table, type, sanitizeName(name), defaultValue);
|
|
735
708
|
}
|
|
736
709
|
});
|
|
@@ -751,14 +724,6 @@ var up = async function(knex) {
|
|
|
751
724
|
table.text("token_type");
|
|
752
725
|
});
|
|
753
726
|
}
|
|
754
|
-
if (!await knex.schema.hasTable("sessions")) {
|
|
755
|
-
await knex.schema.createTable("sessions", (table) => {
|
|
756
|
-
table.increments("id").primary();
|
|
757
|
-
table.integer("userId").notNullable();
|
|
758
|
-
table.timestamp("expires", { useTz: true }).notNullable();
|
|
759
|
-
table.string("sessionToken", 255).notNullable();
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
727
|
};
|
|
763
728
|
var execute = async () => {
|
|
764
729
|
console.log("[EXULU] Initializing database.");
|
|
@@ -1009,6 +974,35 @@ var ExuluEvalUtils = {
|
|
|
1009
974
|
};
|
|
1010
975
|
|
|
1011
976
|
// src/registry/classes.ts
|
|
977
|
+
function sanitizeToolName(name) {
|
|
978
|
+
if (typeof name !== "string") return "";
|
|
979
|
+
let sanitized = name.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
980
|
+
sanitized = sanitized.replace(/^_+|_+$/g, "");
|
|
981
|
+
if (sanitized.length > 128) {
|
|
982
|
+
sanitized = sanitized.substring(0, 128);
|
|
983
|
+
}
|
|
984
|
+
return sanitized;
|
|
985
|
+
}
|
|
986
|
+
var convertToolsArrayToObject = (tools) => {
|
|
987
|
+
if (!tools) return {};
|
|
988
|
+
const sanitizedTools = tools ? tools.map((tool2) => ({
|
|
989
|
+
...tool2,
|
|
990
|
+
name: sanitizeToolName(tool2.name)
|
|
991
|
+
})) : [];
|
|
992
|
+
const askForConfirmation = {
|
|
993
|
+
description: "Ask the user for confirmation.",
|
|
994
|
+
parameters: import_zod2.z.object({
|
|
995
|
+
message: import_zod2.z.string().describe("The message to ask for confirmation.")
|
|
996
|
+
})
|
|
997
|
+
};
|
|
998
|
+
return {
|
|
999
|
+
...sanitizedTools?.reduce(
|
|
1000
|
+
(prev, cur) => ({ ...prev, [cur.name]: cur.tool }),
|
|
1001
|
+
{}
|
|
1002
|
+
),
|
|
1003
|
+
askForConfirmation
|
|
1004
|
+
};
|
|
1005
|
+
};
|
|
1012
1006
|
function generateSlug(name) {
|
|
1013
1007
|
const normalized = name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
1014
1008
|
const lowercase = normalized.toLowerCase();
|
|
@@ -1035,54 +1029,119 @@ var ExuluAgent = class {
|
|
|
1035
1029
|
name;
|
|
1036
1030
|
description = "";
|
|
1037
1031
|
slug = "";
|
|
1032
|
+
type;
|
|
1038
1033
|
streaming = false;
|
|
1039
1034
|
rateLimit;
|
|
1040
1035
|
config;
|
|
1041
1036
|
// private memory: Memory | undefined; // TODO do own implementation
|
|
1042
|
-
tools;
|
|
1043
1037
|
evals;
|
|
1044
1038
|
model;
|
|
1045
1039
|
capabilities;
|
|
1046
|
-
constructor({ id, name, description, config, rateLimit, capabilities,
|
|
1040
|
+
constructor({ id, name, description, config, rateLimit, capabilities, type, evals }) {
|
|
1047
1041
|
this.id = id;
|
|
1048
1042
|
this.name = name;
|
|
1049
1043
|
this.evals = evals;
|
|
1050
1044
|
this.description = description;
|
|
1051
1045
|
this.rateLimit = rateLimit;
|
|
1052
|
-
this.tools = tools;
|
|
1053
1046
|
this.config = config;
|
|
1054
|
-
this.
|
|
1047
|
+
this.type = type;
|
|
1048
|
+
this.capabilities = capabilities || {
|
|
1049
|
+
images: [],
|
|
1050
|
+
files: [],
|
|
1051
|
+
audio: [],
|
|
1052
|
+
video: []
|
|
1053
|
+
};
|
|
1055
1054
|
this.slug = `/agents/${generateSlug(this.name)}/run`;
|
|
1056
|
-
this.model = this.config
|
|
1055
|
+
this.model = this.config?.model;
|
|
1057
1056
|
}
|
|
1058
|
-
|
|
1057
|
+
// Exports the agent as a tool that can be used by another agent
|
|
1058
|
+
// todo test this
|
|
1059
|
+
tool = () => {
|
|
1060
|
+
return new ExuluTool({
|
|
1061
|
+
id: this.id,
|
|
1062
|
+
name: `${this.name} agent`,
|
|
1063
|
+
type: "agent",
|
|
1064
|
+
inputSchema: import_zod2.z.object({
|
|
1065
|
+
prompt: import_zod2.z.string()
|
|
1066
|
+
}),
|
|
1067
|
+
description: `A function that calls an AI agent named: ${this.name}. The agent does the following: ${this.description}.`,
|
|
1068
|
+
execute: async ({ prompt }) => {
|
|
1069
|
+
return await this.generateSync({
|
|
1070
|
+
prompt,
|
|
1071
|
+
statistics: {
|
|
1072
|
+
label: "",
|
|
1073
|
+
trigger: "tool"
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
};
|
|
1079
|
+
generateSync = async ({ messages, prompt, tools, statistics }) => {
|
|
1059
1080
|
if (!this.model) {
|
|
1060
1081
|
throw new Error("Model is required for streaming.");
|
|
1061
1082
|
}
|
|
1062
|
-
if (this.config
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1065
|
-
const { object } = await (0, import_ai.generateObject)({
|
|
1066
|
-
model: this.model,
|
|
1067
|
-
schema: this.config.outputSchema,
|
|
1068
|
-
prompt
|
|
1069
|
-
});
|
|
1070
|
-
return object;
|
|
1083
|
+
if (!this.config) {
|
|
1084
|
+
throw new Error("Config is required for generating.");
|
|
1071
1085
|
}
|
|
1072
|
-
if (
|
|
1073
|
-
|
|
1074
|
-
model: this.model,
|
|
1075
|
-
prompt
|
|
1076
|
-
});
|
|
1077
|
-
const text2 = await result.text;
|
|
1078
|
-
return text2;
|
|
1086
|
+
if (prompt && messages) {
|
|
1087
|
+
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
1079
1088
|
}
|
|
1080
1089
|
const { text } = await (0, import_ai.generateText)({
|
|
1081
1090
|
model: this.model,
|
|
1082
|
-
|
|
1091
|
+
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
1092
|
+
messages,
|
|
1093
|
+
prompt,
|
|
1094
|
+
maxRetries: 2,
|
|
1095
|
+
tools: convertToolsArrayToObject(tools),
|
|
1096
|
+
maxSteps: 5
|
|
1083
1097
|
});
|
|
1098
|
+
if (statistics) {
|
|
1099
|
+
await updateStatistic({
|
|
1100
|
+
name: "count",
|
|
1101
|
+
label: statistics.label,
|
|
1102
|
+
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
1103
|
+
trigger: statistics.trigger,
|
|
1104
|
+
count: 1
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1084
1107
|
return text;
|
|
1085
1108
|
};
|
|
1109
|
+
generateStream = ({ messages, prompt, tools, statistics }) => {
|
|
1110
|
+
if (!this.model) {
|
|
1111
|
+
throw new Error("Model is required for streaming.");
|
|
1112
|
+
}
|
|
1113
|
+
if (!this.config) {
|
|
1114
|
+
throw new Error("Config is required for generating.");
|
|
1115
|
+
}
|
|
1116
|
+
if (prompt && messages) {
|
|
1117
|
+
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
1118
|
+
}
|
|
1119
|
+
return (0, import_ai.streamText)({
|
|
1120
|
+
model: this.model,
|
|
1121
|
+
messages,
|
|
1122
|
+
prompt,
|
|
1123
|
+
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
1124
|
+
maxRetries: 2,
|
|
1125
|
+
tools: convertToolsArrayToObject(tools),
|
|
1126
|
+
maxSteps: 5,
|
|
1127
|
+
onError: (error) => console.error("[EXULU] chat stream error.", error),
|
|
1128
|
+
onFinish: async ({ response, usage }) => {
|
|
1129
|
+
console.info(
|
|
1130
|
+
"[EXULU] chat stream finished.",
|
|
1131
|
+
usage
|
|
1132
|
+
);
|
|
1133
|
+
if (statistics) {
|
|
1134
|
+
await updateStatistic({
|
|
1135
|
+
name: "count",
|
|
1136
|
+
label: statistics.label,
|
|
1137
|
+
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
1138
|
+
trigger: statistics.trigger,
|
|
1139
|
+
count: 1
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
};
|
|
1086
1145
|
};
|
|
1087
1146
|
var ExuluEmbedder = class {
|
|
1088
1147
|
id;
|
|
@@ -1105,6 +1164,13 @@ var ExuluEmbedder = class {
|
|
|
1105
1164
|
}
|
|
1106
1165
|
async generateFromQuery(query, statistics) {
|
|
1107
1166
|
if (statistics) {
|
|
1167
|
+
await updateStatistic({
|
|
1168
|
+
name: "count",
|
|
1169
|
+
label: statistics.label,
|
|
1170
|
+
type: STATISTICS_TYPE_ENUM.EMBEDDER_GENERATE,
|
|
1171
|
+
trigger: statistics.trigger,
|
|
1172
|
+
count: 1
|
|
1173
|
+
});
|
|
1108
1174
|
}
|
|
1109
1175
|
return await this.generateEmbeddings({
|
|
1110
1176
|
item: {
|
|
@@ -1118,16 +1184,22 @@ var ExuluEmbedder = class {
|
|
|
1118
1184
|
}
|
|
1119
1185
|
async generateFromDocument(input, statistics) {
|
|
1120
1186
|
if (statistics) {
|
|
1187
|
+
await updateStatistic({
|
|
1188
|
+
name: "count",
|
|
1189
|
+
label: statistics.label,
|
|
1190
|
+
type: STATISTICS_TYPE_ENUM.EMBEDDER_GENERATE,
|
|
1191
|
+
trigger: statistics.trigger,
|
|
1192
|
+
count: 1
|
|
1193
|
+
});
|
|
1121
1194
|
}
|
|
1122
1195
|
if (!this.chunker) {
|
|
1123
1196
|
throw new Error("Chunker not found for embedder " + this.name);
|
|
1124
1197
|
}
|
|
1125
|
-
console.log("generating chunks");
|
|
1126
1198
|
if (!input.id) {
|
|
1127
1199
|
throw new Error("Item id is required for generating embeddings.");
|
|
1128
1200
|
}
|
|
1129
1201
|
const output = await this.chunker(input, this.maxChunkSize);
|
|
1130
|
-
console.log("
|
|
1202
|
+
console.log("[EXULU] Generating embeddings.");
|
|
1131
1203
|
return await this.generateEmbeddings(output);
|
|
1132
1204
|
}
|
|
1133
1205
|
};
|
|
@@ -1307,9 +1379,8 @@ var ExuluEval = class {
|
|
|
1307
1379
|
if (!data.prompt) {
|
|
1308
1380
|
throw new Error("Prompt is required for running an agent.");
|
|
1309
1381
|
}
|
|
1310
|
-
const result = await runner.agent.
|
|
1311
|
-
prompt: data.prompt
|
|
1312
|
-
stream: false
|
|
1382
|
+
const result = await runner.agent.generateSync({
|
|
1383
|
+
prompt: data.prompt
|
|
1313
1384
|
});
|
|
1314
1385
|
data.result = result;
|
|
1315
1386
|
}
|
|
@@ -1404,18 +1475,18 @@ var ExuluTool = class {
|
|
|
1404
1475
|
id;
|
|
1405
1476
|
name;
|
|
1406
1477
|
description;
|
|
1407
|
-
|
|
1478
|
+
inputSchema;
|
|
1408
1479
|
type;
|
|
1409
1480
|
tool;
|
|
1410
|
-
constructor({ id, name, description,
|
|
1481
|
+
constructor({ id, name, description, inputSchema, type, execute: execute2 }) {
|
|
1411
1482
|
this.id = id;
|
|
1412
1483
|
this.name = name;
|
|
1413
1484
|
this.description = description;
|
|
1414
|
-
this.
|
|
1485
|
+
this.inputSchema = inputSchema;
|
|
1415
1486
|
this.type = type;
|
|
1416
1487
|
this.tool = (0, import_ai.tool)({
|
|
1417
1488
|
description,
|
|
1418
|
-
parameters,
|
|
1489
|
+
parameters: inputSchema || import_zod2.z.object({}),
|
|
1419
1490
|
execute: execute2
|
|
1420
1491
|
});
|
|
1421
1492
|
}
|
|
@@ -1471,10 +1542,9 @@ var ExuluContext = class {
|
|
|
1471
1542
|
}
|
|
1472
1543
|
const { db: db2 } = await postgresClient();
|
|
1473
1544
|
Object.keys(item).forEach((key) => {
|
|
1474
|
-
if (key === "name" || key === "description" || key === "external_id" || key === "tags" || key === "source" || key === "textLength" || key === "upsert") {
|
|
1545
|
+
if (key === "name" || key === "description" || key === "external_id" || key === "tags" || key === "source" || key === "textLength" || key === "upsert" || key === "archived") {
|
|
1475
1546
|
return;
|
|
1476
1547
|
}
|
|
1477
|
-
console.log("this.fields", this.fields);
|
|
1478
1548
|
const field = this.fields.find((field2) => field2.name === key);
|
|
1479
1549
|
if (!field) {
|
|
1480
1550
|
throw new Error("Trying to uppdate value for field '" + key + "' that does not exist on the context fields definition. Available fields: " + this.fields.map((field2) => sanitizeName(field2.name)).join(", ") + " ,name, description, external_id");
|
|
@@ -1519,6 +1589,9 @@ var ExuluContext = class {
|
|
|
1519
1589
|
chunk_index: chunk.index,
|
|
1520
1590
|
embedding: import_knex4.default.toSql(chunk.vector)
|
|
1521
1591
|
})));
|
|
1592
|
+
await db2.from(this.getTableName()).where({ id }).update({
|
|
1593
|
+
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1594
|
+
}).returning("id");
|
|
1522
1595
|
}
|
|
1523
1596
|
return {
|
|
1524
1597
|
id: result[0].id,
|
|
@@ -1548,10 +1621,9 @@ var ExuluContext = class {
|
|
|
1548
1621
|
}
|
|
1549
1622
|
}
|
|
1550
1623
|
Object.keys(item).forEach((key) => {
|
|
1551
|
-
if (key === "name" || key === "description" || key === "external_id" || key === "tags" || key === "source" || key === "textLength" || key === "upsert") {
|
|
1624
|
+
if (key === "name" || key === "description" || key === "external_id" || key === "tags" || key === "source" || key === "textLength" || key === "upsert" || key === "archived") {
|
|
1552
1625
|
return;
|
|
1553
1626
|
}
|
|
1554
|
-
console.log("this.fields", this.fields);
|
|
1555
1627
|
const field = this.fields.find((field2) => field2.name === key);
|
|
1556
1628
|
if (!field) {
|
|
1557
1629
|
throw new Error("Trying to insert value for field '" + key + "' that does not exist on the context fields definition. Available fields: " + this.fields.map((field2) => sanitizeName(field2.name)).join(", ") + " ,name, description, external_id");
|
|
@@ -1593,13 +1665,16 @@ var ExuluContext = class {
|
|
|
1593
1665
|
if (!exists) {
|
|
1594
1666
|
await this.createChunksTable();
|
|
1595
1667
|
}
|
|
1596
|
-
console.log("
|
|
1668
|
+
console.log("[EXULU] Inserting chunks.");
|
|
1597
1669
|
await db2.from(this.getChunksTableName()).insert(chunks.map((chunk) => ({
|
|
1598
1670
|
source,
|
|
1599
1671
|
content: chunk.content,
|
|
1600
1672
|
chunk_index: chunk.index,
|
|
1601
1673
|
embedding: import_knex4.default.toSql(chunk.vector)
|
|
1602
1674
|
})));
|
|
1675
|
+
await db2.from(this.getTableName()).where({ id: result[0].id }).update({
|
|
1676
|
+
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1677
|
+
}).returning("id");
|
|
1603
1678
|
}
|
|
1604
1679
|
return {
|
|
1605
1680
|
id: result[0].id,
|
|
@@ -1609,6 +1684,8 @@ var ExuluContext = class {
|
|
|
1609
1684
|
getItems = async ({
|
|
1610
1685
|
statistics,
|
|
1611
1686
|
limit,
|
|
1687
|
+
sort,
|
|
1688
|
+
order,
|
|
1612
1689
|
page,
|
|
1613
1690
|
name,
|
|
1614
1691
|
archived,
|
|
@@ -1629,6 +1706,9 @@ var ExuluContext = class {
|
|
|
1629
1706
|
const columns = await db2(mainTable).columnInfo();
|
|
1630
1707
|
const totalQuery = db2.count("* as count").from(mainTable).first();
|
|
1631
1708
|
const itemsQuery = db2.select(Object.keys(columns).map((column) => mainTable + "." + column)).from(mainTable).offset(offset).limit(limit);
|
|
1709
|
+
if (sort) {
|
|
1710
|
+
itemsQuery.orderBy(sort, order === "desc" ? "desc" : "asc");
|
|
1711
|
+
}
|
|
1632
1712
|
if (typeof name === "string") {
|
|
1633
1713
|
itemsQuery.whereILike("name", `%${name}%`);
|
|
1634
1714
|
totalQuery.whereILike("name", `%${name}%`);
|
|
@@ -1672,7 +1752,7 @@ var ExuluContext = class {
|
|
|
1672
1752
|
}
|
|
1673
1753
|
itemsQuery.limit(limit * 5);
|
|
1674
1754
|
if (statistics) {
|
|
1675
|
-
updateStatistic({
|
|
1755
|
+
await updateStatistic({
|
|
1676
1756
|
name: "count",
|
|
1677
1757
|
label: statistics.label,
|
|
1678
1758
|
type: STATISTICS_TYPE_ENUM.CONTEXT_RETRIEVE,
|
|
@@ -1805,6 +1885,7 @@ var ExuluContext = class {
|
|
|
1805
1885
|
table.text("external_id");
|
|
1806
1886
|
table.integer("textLength");
|
|
1807
1887
|
table.text("source");
|
|
1888
|
+
table.timestamp("embeddings_updated_at");
|
|
1808
1889
|
for (const field of this.fields) {
|
|
1809
1890
|
const { type, name } = field;
|
|
1810
1891
|
if (!type || !name) {
|
|
@@ -1834,15 +1915,15 @@ var ExuluContext = class {
|
|
|
1834
1915
|
id: this.id,
|
|
1835
1916
|
name: `${this.name} context`,
|
|
1836
1917
|
type: "context",
|
|
1837
|
-
|
|
1918
|
+
inputSchema: import_zod2.z.object({
|
|
1838
1919
|
query: import_zod2.z.string()
|
|
1839
1920
|
}),
|
|
1840
1921
|
description: `Gets information from the context called: ${this.name}. The context description is: ${this.description}.`,
|
|
1841
|
-
execute: async ({
|
|
1922
|
+
execute: async ({ query }) => {
|
|
1842
1923
|
return await this.getItems({
|
|
1843
1924
|
page: 1,
|
|
1844
1925
|
limit: 10,
|
|
1845
|
-
query
|
|
1926
|
+
query,
|
|
1846
1927
|
statistics: {
|
|
1847
1928
|
label: this.name,
|
|
1848
1929
|
trigger: "agent"
|
|
@@ -1891,7 +1972,32 @@ var ExuluSource = class {
|
|
|
1891
1972
|
}
|
|
1892
1973
|
};
|
|
1893
1974
|
var updateStatistic = async (statistic) => {
|
|
1894
|
-
|
|
1975
|
+
const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1976
|
+
const { db: db2 } = await postgresClient();
|
|
1977
|
+
const existing = await db2.from("statistics").where({
|
|
1978
|
+
name: statistic.name,
|
|
1979
|
+
label: statistic.label,
|
|
1980
|
+
type: statistic.type,
|
|
1981
|
+
createdAt: currentDate
|
|
1982
|
+
}).first();
|
|
1983
|
+
if (!existing) {
|
|
1984
|
+
await db2.from("statistics").insert({
|
|
1985
|
+
name: statistic.name,
|
|
1986
|
+
label: statistic.label,
|
|
1987
|
+
type: statistic.type,
|
|
1988
|
+
total: statistic.count ?? 1,
|
|
1989
|
+
createdAt: currentDate
|
|
1990
|
+
});
|
|
1991
|
+
} else {
|
|
1992
|
+
await db2.from("statistics").update({
|
|
1993
|
+
total: db2.raw("total + ?", [statistic.count ?? 1])
|
|
1994
|
+
}).where({
|
|
1995
|
+
name: statistic.name,
|
|
1996
|
+
label: statistic.label,
|
|
1997
|
+
type: statistic.type,
|
|
1998
|
+
createdAt: currentDate
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
1895
2001
|
};
|
|
1896
2002
|
|
|
1897
2003
|
// src/registry/index.ts
|
|
@@ -1964,7 +2070,6 @@ var authentication = async ({
|
|
|
1964
2070
|
internalkey,
|
|
1965
2071
|
db: db2
|
|
1966
2072
|
}) => {
|
|
1967
|
-
console.log("[EXULU] apikey", apikey);
|
|
1968
2073
|
if (internalkey) {
|
|
1969
2074
|
if (!process.env.INTERNAL_SECRET) {
|
|
1970
2075
|
return {
|
|
@@ -1992,7 +2097,7 @@ var authentication = async ({
|
|
|
1992
2097
|
}
|
|
1993
2098
|
if (authtoken) {
|
|
1994
2099
|
try {
|
|
1995
|
-
console.log("authtoken", authtoken);
|
|
2100
|
+
console.log("[EXULU] authtoken", authtoken);
|
|
1996
2101
|
if (!authtoken?.email) {
|
|
1997
2102
|
return {
|
|
1998
2103
|
error: true,
|
|
@@ -2001,7 +2106,6 @@ var authentication = async ({
|
|
|
2001
2106
|
};
|
|
2002
2107
|
}
|
|
2003
2108
|
const user = await db2.from("users").select("*").where("email", authtoken?.email).first();
|
|
2004
|
-
console.log("user", user);
|
|
2005
2109
|
if (!user) {
|
|
2006
2110
|
return {
|
|
2007
2111
|
error: true,
|
|
@@ -2050,15 +2154,11 @@ var authentication = async ({
|
|
|
2050
2154
|
code: 401
|
|
2051
2155
|
};
|
|
2052
2156
|
}
|
|
2053
|
-
console.log("[EXULU] request_key_name", request_key_name);
|
|
2054
|
-
console.log("[EXULU] request_key_compare_value", request_key_compare_value);
|
|
2055
2157
|
const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(request_key_name));
|
|
2056
2158
|
for (const user of filtered) {
|
|
2057
2159
|
const user_key_last_slash_index = user.apikey.lastIndexOf("/");
|
|
2058
2160
|
const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
|
|
2059
|
-
console.log("[EXULU] user_key_compare_value", user_key_compare_value);
|
|
2060
2161
|
const isMatch = await import_bcryptjs2.default.compare(request_key_compare_value, user_key_compare_value);
|
|
2061
|
-
console.log("[EXULU] isMatch", isMatch);
|
|
2062
2162
|
if (isMatch) {
|
|
2063
2163
|
await db2.from("users").where({ id: user.id }).update({
|
|
2064
2164
|
last_used: /* @__PURE__ */ new Date()
|
|
@@ -2091,9 +2191,7 @@ var requestValidators = {
|
|
|
2091
2191
|
const { db: db2 } = await postgresClient();
|
|
2092
2192
|
let authtoken = null;
|
|
2093
2193
|
if (typeof apikey !== "string") {
|
|
2094
|
-
|
|
2095
|
-
authtoken = await getToken(req.headers["authorization"] ?? "");
|
|
2096
|
-
console.log("[EXULU] authtoken", authtoken);
|
|
2194
|
+
authtoken = await getToken((req.headers["authorization"] || req.headers["x-api-key"]) ?? "");
|
|
2097
2195
|
}
|
|
2098
2196
|
return await authentication({
|
|
2099
2197
|
authtoken,
|
|
@@ -2195,7 +2293,6 @@ var requestValidators = {
|
|
|
2195
2293
|
};
|
|
2196
2294
|
},
|
|
2197
2295
|
agents: (req) => {
|
|
2198
|
-
console.log("[EXULU] validating request body and headers.", req.body);
|
|
2199
2296
|
const contentType = req.headers["content-type"] || "";
|
|
2200
2297
|
if (!contentType.includes("application/json")) {
|
|
2201
2298
|
return {
|
|
@@ -2287,6 +2384,42 @@ var import_reflect_metadata = require("reflect-metadata");
|
|
|
2287
2384
|
// src/registry/utils/graphql.ts
|
|
2288
2385
|
var import_schema = require("@graphql-tools/schema");
|
|
2289
2386
|
var import_graphql_type_json = __toESM(require("graphql-type-json"), 1);
|
|
2387
|
+
var import_graphql = require("graphql");
|
|
2388
|
+
var import_crypto_js = __toESM(require("crypto-js"), 1);
|
|
2389
|
+
var GraphQLDate = new import_graphql.GraphQLScalarType({
|
|
2390
|
+
name: "Date",
|
|
2391
|
+
description: "Date custom scalar type",
|
|
2392
|
+
serialize(value) {
|
|
2393
|
+
if (value instanceof Date) {
|
|
2394
|
+
return value.toISOString();
|
|
2395
|
+
}
|
|
2396
|
+
if (typeof value === "number") {
|
|
2397
|
+
return new Date(value).toISOString();
|
|
2398
|
+
}
|
|
2399
|
+
if (typeof value === "string") {
|
|
2400
|
+
return new Date(value).toISOString();
|
|
2401
|
+
}
|
|
2402
|
+
return value;
|
|
2403
|
+
},
|
|
2404
|
+
parseValue(value) {
|
|
2405
|
+
if (typeof value === "string") {
|
|
2406
|
+
return new Date(value);
|
|
2407
|
+
}
|
|
2408
|
+
if (typeof value === "number") {
|
|
2409
|
+
return new Date(value);
|
|
2410
|
+
}
|
|
2411
|
+
return value;
|
|
2412
|
+
},
|
|
2413
|
+
parseLiteral(ast) {
|
|
2414
|
+
if (ast.kind === import_graphql.Kind.STRING) {
|
|
2415
|
+
return new Date(ast.value);
|
|
2416
|
+
}
|
|
2417
|
+
if (ast.kind === import_graphql.Kind.INT) {
|
|
2418
|
+
return new Date(parseInt(ast.value, 10));
|
|
2419
|
+
}
|
|
2420
|
+
return null;
|
|
2421
|
+
}
|
|
2422
|
+
});
|
|
2290
2423
|
var map = (field) => {
|
|
2291
2424
|
let type;
|
|
2292
2425
|
switch (field.type) {
|
|
@@ -2306,7 +2439,7 @@ var map = (field) => {
|
|
|
2306
2439
|
type = "JSON";
|
|
2307
2440
|
break;
|
|
2308
2441
|
case "date":
|
|
2309
|
-
type = "
|
|
2442
|
+
type = "Date";
|
|
2310
2443
|
break;
|
|
2311
2444
|
default:
|
|
2312
2445
|
type = "String";
|
|
@@ -2324,8 +2457,8 @@ function createTypeDefs(table) {
|
|
|
2324
2457
|
type ${table.name.singular} {
|
|
2325
2458
|
${fields.join("\n")}
|
|
2326
2459
|
id: ID!
|
|
2327
|
-
createdAt:
|
|
2328
|
-
updatedAt:
|
|
2460
|
+
createdAt: Date!
|
|
2461
|
+
updatedAt: Date!
|
|
2329
2462
|
}
|
|
2330
2463
|
`;
|
|
2331
2464
|
const inputDef = `
|
|
@@ -2351,6 +2484,11 @@ input FilterOperatorString {
|
|
|
2351
2484
|
contains: String
|
|
2352
2485
|
}
|
|
2353
2486
|
|
|
2487
|
+
input FilterOperatorDate {
|
|
2488
|
+
lte: Date
|
|
2489
|
+
gte: Date
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2354
2492
|
input FilterOperatorFloat {
|
|
2355
2493
|
eq: Float
|
|
2356
2494
|
ne: Float
|
|
@@ -2403,17 +2541,19 @@ function createMutations(table) {
|
|
|
2403
2541
|
[`${tableNamePlural}CreateOne`]: async (_, args, context, info) => {
|
|
2404
2542
|
const { db: db2 } = context;
|
|
2405
2543
|
const requestedFields = getRequestedFields(info);
|
|
2544
|
+
let { input } = args;
|
|
2545
|
+
input = encryptSensitiveFields(input);
|
|
2406
2546
|
const results = await db2(tableNamePlural).insert({
|
|
2407
|
-
...
|
|
2547
|
+
...input,
|
|
2408
2548
|
createdAt: /* @__PURE__ */ new Date(),
|
|
2409
2549
|
updatedAt: /* @__PURE__ */ new Date()
|
|
2410
2550
|
}).returning(requestedFields);
|
|
2411
|
-
console.log("requestedFields", requestedFields);
|
|
2412
2551
|
return results[0];
|
|
2413
2552
|
},
|
|
2414
2553
|
[`${tableNamePlural}UpdateOne`]: async (_, args, context, info) => {
|
|
2415
2554
|
const { db: db2 } = context;
|
|
2416
|
-
|
|
2555
|
+
let { where, input } = args;
|
|
2556
|
+
input = encryptSensitiveFields(input);
|
|
2417
2557
|
await db2(tableNamePlural).where(where).update({
|
|
2418
2558
|
...input,
|
|
2419
2559
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -2423,7 +2563,8 @@ function createMutations(table) {
|
|
|
2423
2563
|
return result;
|
|
2424
2564
|
},
|
|
2425
2565
|
[`${tableNamePlural}UpdateOneById`]: async (_, args, context, info) => {
|
|
2426
|
-
|
|
2566
|
+
let { id, input } = args;
|
|
2567
|
+
input = encryptSensitiveFields(input);
|
|
2427
2568
|
const { db: db2 } = context;
|
|
2428
2569
|
await db2(tableNamePlural).where({ id }).update({
|
|
2429
2570
|
...input,
|
|
@@ -2501,7 +2642,6 @@ function createQueries(table) {
|
|
|
2501
2642
|
[`${tableNamePlural}Pagination`]: async (_, args, context, info) => {
|
|
2502
2643
|
const { limit = 10, page = 0, filters = [], sort } = args;
|
|
2503
2644
|
const { db: db2 } = context;
|
|
2504
|
-
console.log("page", page);
|
|
2505
2645
|
let baseQuery = db2(tableNamePlural);
|
|
2506
2646
|
baseQuery = applyFilters(baseQuery, filters);
|
|
2507
2647
|
const [{ count }] = await baseQuery.clone().count("* as count");
|
|
@@ -2517,8 +2657,6 @@ function createQueries(table) {
|
|
|
2517
2657
|
dataQuery = dataQuery.offset((page - 1) * limit);
|
|
2518
2658
|
}
|
|
2519
2659
|
const items = await dataQuery.select(requestedFields).limit(limit);
|
|
2520
|
-
console.log("items", items);
|
|
2521
|
-
console.log("query", dataQuery.toQuery());
|
|
2522
2660
|
return {
|
|
2523
2661
|
pageInfo: {
|
|
2524
2662
|
pageCount,
|
|
@@ -2529,12 +2667,44 @@ function createQueries(table) {
|
|
|
2529
2667
|
},
|
|
2530
2668
|
items
|
|
2531
2669
|
};
|
|
2532
|
-
}
|
|
2670
|
+
},
|
|
2671
|
+
// Add jobStatistics query for jobs table
|
|
2672
|
+
...tableNamePlural === "jobs" ? {
|
|
2673
|
+
jobStatistics: async (_, args, context, info) => {
|
|
2674
|
+
const { user, agent, from, to } = args;
|
|
2675
|
+
const { db: db2 } = context;
|
|
2676
|
+
let query = db2("jobs");
|
|
2677
|
+
if (user) {
|
|
2678
|
+
query = query.where("user", user);
|
|
2679
|
+
}
|
|
2680
|
+
if (agent) {
|
|
2681
|
+
query = query.where("agent", agent);
|
|
2682
|
+
}
|
|
2683
|
+
if (from) {
|
|
2684
|
+
query = query.where("createdAt", ">=", from);
|
|
2685
|
+
}
|
|
2686
|
+
if (to) {
|
|
2687
|
+
query = query.where("createdAt", "<=", to);
|
|
2688
|
+
}
|
|
2689
|
+
const completedQuery = query.clone().where("status", "completed");
|
|
2690
|
+
const [{ completedCount }] = await completedQuery.count("* as completedCount");
|
|
2691
|
+
const failedQuery = query.clone().where("status", "failed");
|
|
2692
|
+
const [{ failedCount }] = await failedQuery.count("* as failedCount");
|
|
2693
|
+
const durationQuery = query.clone().where("status", "completed").whereNotNull("duration").select(db2.raw('AVG("duration") as averageDuration'));
|
|
2694
|
+
const [{ averageDuration }] = await durationQuery;
|
|
2695
|
+
return {
|
|
2696
|
+
completedCount: Number(completedCount),
|
|
2697
|
+
failedCount: Number(failedCount),
|
|
2698
|
+
averageDuration: averageDuration ? Number(averageDuration) : 0
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
} : {}
|
|
2533
2702
|
};
|
|
2534
2703
|
}
|
|
2535
2704
|
function createSDL(tables) {
|
|
2536
2705
|
let typeDefs = `
|
|
2537
2706
|
scalar JSON
|
|
2707
|
+
scalar Date
|
|
2538
2708
|
|
|
2539
2709
|
type Query {
|
|
2540
2710
|
`;
|
|
@@ -2542,7 +2712,7 @@ function createSDL(tables) {
|
|
|
2542
2712
|
type Mutation {
|
|
2543
2713
|
`;
|
|
2544
2714
|
let modelDefs = "";
|
|
2545
|
-
const resolvers = { JSON: import_graphql_type_json.default, Query: {}, Mutation: {} };
|
|
2715
|
+
const resolvers = { JSON: import_graphql_type_json.default, Date: GraphQLDate, Query: {}, Mutation: {} };
|
|
2546
2716
|
for (const table of tables) {
|
|
2547
2717
|
const tableNamePlural = table.name.plural.toLowerCase();
|
|
2548
2718
|
const tableNameSingular = table.name.singular.toLowerCase();
|
|
@@ -2551,6 +2721,7 @@ function createSDL(tables) {
|
|
|
2551
2721
|
${tableNameSingular}ById(id: ID!): ${tableNameSingular}
|
|
2552
2722
|
${tableNamePlural}Pagination(limit: Int, page: Int, filters: [Filter${tableNameSingularUpperCaseFirst}], sort: SortBy): ${tableNameSingularUpperCaseFirst}PaginationResult
|
|
2553
2723
|
${tableNameSingular}One(filters: [Filter${tableNameSingularUpperCaseFirst}], sort: SortBy): ${tableNameSingular}
|
|
2724
|
+
${tableNamePlural === "jobs" ? `jobStatistics(user: ID, agent: String, from: String, to: String): JobStatistics` : ""}
|
|
2554
2725
|
`;
|
|
2555
2726
|
mutationDefs += `
|
|
2556
2727
|
${tableNamePlural}CreateOne(input: ${tableNameSingular}Input!): ${tableNameSingular}
|
|
@@ -2575,6 +2746,15 @@ type PageInfo {
|
|
|
2575
2746
|
hasNextPage: Boolean!
|
|
2576
2747
|
}
|
|
2577
2748
|
`;
|
|
2749
|
+
if (tableNamePlural === "jobs") {
|
|
2750
|
+
modelDefs += `
|
|
2751
|
+
type JobStatistics {
|
|
2752
|
+
completedCount: Int!
|
|
2753
|
+
failedCount: Int!
|
|
2754
|
+
averageDuration: Float!
|
|
2755
|
+
}
|
|
2756
|
+
`;
|
|
2757
|
+
}
|
|
2578
2758
|
Object.assign(resolvers.Query, createQueries(table));
|
|
2579
2759
|
Object.assign(resolvers.Mutation, createMutations(table));
|
|
2580
2760
|
}
|
|
@@ -2611,6 +2791,15 @@ type PageInfo {
|
|
|
2611
2791
|
console.log("\n");
|
|
2612
2792
|
return schema;
|
|
2613
2793
|
}
|
|
2794
|
+
var sensitiveFields = ["anthropic_token"];
|
|
2795
|
+
var encryptSensitiveFields = (input) => {
|
|
2796
|
+
sensitiveFields.forEach((field) => {
|
|
2797
|
+
if (input[field]) {
|
|
2798
|
+
input[field] = import_crypto_js.default.AES.encrypt(input[field], process.env.NEXTAUTH_SECRET).toString();
|
|
2799
|
+
}
|
|
2800
|
+
});
|
|
2801
|
+
return input;
|
|
2802
|
+
};
|
|
2614
2803
|
|
|
2615
2804
|
// src/registry/routes.ts
|
|
2616
2805
|
var import_express5 = require("@as-integrations/express5");
|
|
@@ -3009,6 +3198,34 @@ var createUppyRoutes = async (app) => {
|
|
|
3009
3198
|
// src/registry/routes.ts
|
|
3010
3199
|
var import_utils2 = require("@apollo/utils.keyvaluecache");
|
|
3011
3200
|
var import_body_parser = __toESM(require("body-parser"), 1);
|
|
3201
|
+
var import_crypto_js2 = __toESM(require("crypto-js"), 1);
|
|
3202
|
+
|
|
3203
|
+
// src/registry/utils/claude-messages.ts
|
|
3204
|
+
var CLAUDE_MESSAGES = {
|
|
3205
|
+
authentication_error: `
|
|
3206
|
+
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
3207
|
+
\x1B[0m`,
|
|
3208
|
+
missing_body: `
|
|
3209
|
+
\x1B[41m -- Missing body Anthropic response. --
|
|
3210
|
+
\x1B[0m`,
|
|
3211
|
+
missing_nextauth_secret: `
|
|
3212
|
+
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
3213
|
+
\x1B[0m`,
|
|
3214
|
+
not_enabled: `
|
|
3215
|
+
\x1B[31m
|
|
3216
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557
|
|
3217
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3218
|
+
\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3219
|
+
\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3220
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
3221
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D
|
|
3222
|
+
Intelligence Management Platform
|
|
3223
|
+
\x1B[0m
|
|
3224
|
+
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
3225
|
+
\x1B[0m`
|
|
3226
|
+
};
|
|
3227
|
+
|
|
3228
|
+
// src/registry/routes.ts
|
|
3012
3229
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
3013
3230
|
var global_queues = {
|
|
3014
3231
|
logs_cleaner: "logs-cleaner"
|
|
@@ -3045,7 +3262,7 @@ var createRecurringJobs = async () => {
|
|
|
3045
3262
|
console.table(recurringJobSchedulersLogs);
|
|
3046
3263
|
return queue;
|
|
3047
3264
|
};
|
|
3048
|
-
var createExpressRoutes = async (app, agents,
|
|
3265
|
+
var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
3049
3266
|
const routeLogs = [];
|
|
3050
3267
|
var corsOptions = {
|
|
3051
3268
|
origin: "*",
|
|
@@ -3065,6 +3282,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3065
3282
|
\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3066
3283
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
3067
3284
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D
|
|
3285
|
+
Intelligence Management Platform
|
|
3068
3286
|
|
|
3069
3287
|
`);
|
|
3070
3288
|
console.log("Agents:");
|
|
@@ -3113,7 +3331,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3113
3331
|
} else {
|
|
3114
3332
|
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
3115
3333
|
}
|
|
3116
|
-
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema, workflowSchema, evalResultsSchema,
|
|
3334
|
+
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema, workflowSchema, evalResultsSchema, agentSessionsSchema, agentMessagesSchema]);
|
|
3117
3335
|
console.log("[EXULU] graphql server");
|
|
3118
3336
|
const server = new import_server3.ApolloServer({
|
|
3119
3337
|
cache: new import_utils2.InMemoryLRUCache(),
|
|
@@ -3141,10 +3359,52 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3141
3359
|
}
|
|
3142
3360
|
})
|
|
3143
3361
|
);
|
|
3144
|
-
app.get(`/
|
|
3362
|
+
app.get(`/providers`, async (req, res) => {
|
|
3363
|
+
const authenticationResult = await requestValidators.authenticate(req);
|
|
3364
|
+
if (!authenticationResult.user?.id) {
|
|
3365
|
+
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3366
|
+
return;
|
|
3367
|
+
}
|
|
3145
3368
|
res.status(200).json(agents);
|
|
3146
3369
|
});
|
|
3370
|
+
app.get(`/agents`, async (req, res) => {
|
|
3371
|
+
const authenticationResult = await requestValidators.authenticate(req);
|
|
3372
|
+
if (!authenticationResult.user?.id) {
|
|
3373
|
+
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3374
|
+
return;
|
|
3375
|
+
}
|
|
3376
|
+
const { db: db2 } = await postgresClient();
|
|
3377
|
+
const agentsFromDb = await db2.from("agents").select("*");
|
|
3378
|
+
res.status(200).json(agentsFromDb.map((agent) => {
|
|
3379
|
+
const backend = agents.find((a) => a.id === agent.backend);
|
|
3380
|
+
if (!backend) {
|
|
3381
|
+
return null;
|
|
3382
|
+
}
|
|
3383
|
+
return {
|
|
3384
|
+
name: agent.name,
|
|
3385
|
+
id: agent.id,
|
|
3386
|
+
description: agent.description,
|
|
3387
|
+
provider: backend?.model?.provider,
|
|
3388
|
+
model: backend?.model?.modelId,
|
|
3389
|
+
active: agent.active,
|
|
3390
|
+
public: agent.public,
|
|
3391
|
+
type: agent.type,
|
|
3392
|
+
slug: backend?.slug,
|
|
3393
|
+
rateLimit: backend?.rateLimit,
|
|
3394
|
+
streaming: backend?.streaming,
|
|
3395
|
+
capabilities: backend?.capabilities,
|
|
3396
|
+
// todo add contexts
|
|
3397
|
+
availableTools: tools,
|
|
3398
|
+
enabledTools: agent.tools
|
|
3399
|
+
};
|
|
3400
|
+
}).filter(Boolean));
|
|
3401
|
+
});
|
|
3147
3402
|
app.get(`/agents/:id`, async (req, res) => {
|
|
3403
|
+
const authenticationResult = await requestValidators.authenticate(req);
|
|
3404
|
+
if (!authenticationResult.user?.id) {
|
|
3405
|
+
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3406
|
+
return;
|
|
3407
|
+
}
|
|
3148
3408
|
const { db: db2 } = await postgresClient();
|
|
3149
3409
|
const id = req.params.id;
|
|
3150
3410
|
if (!id) {
|
|
@@ -3167,6 +3427,8 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3167
3427
|
name: agent.name,
|
|
3168
3428
|
id: agent.id,
|
|
3169
3429
|
description: agent.description,
|
|
3430
|
+
provider: backend?.model?.provider,
|
|
3431
|
+
model: backend?.model?.modelId,
|
|
3170
3432
|
active: agent.active,
|
|
3171
3433
|
public: agent.public,
|
|
3172
3434
|
type: agent.type,
|
|
@@ -3175,7 +3437,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3175
3437
|
streaming: backend?.streaming,
|
|
3176
3438
|
capabilities: backend?.capabilities,
|
|
3177
3439
|
// todo add contexts
|
|
3178
|
-
availableTools:
|
|
3440
|
+
availableTools: tools,
|
|
3179
3441
|
enabledTools: agent.tools
|
|
3180
3442
|
}
|
|
3181
3443
|
});
|
|
@@ -3186,8 +3448,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3186
3448
|
name: tool2.name,
|
|
3187
3449
|
description: tool2.description,
|
|
3188
3450
|
type: tool2.type || "tool",
|
|
3189
|
-
inputSchema: tool2.inputSchema ? (0, import_zodex.zerialize)(tool2.inputSchema) : null
|
|
3190
|
-
outputSchema: tool2.outputSchema ? (0, import_zodex.zerialize)(tool2.outputSchema) : null
|
|
3451
|
+
inputSchema: tool2.inputSchema ? (0, import_zodex.zerialize)(tool2.inputSchema) : null
|
|
3191
3452
|
})));
|
|
3192
3453
|
});
|
|
3193
3454
|
app.get("/tools/:id", async (req, res) => {
|
|
@@ -3305,6 +3566,14 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3305
3566
|
});
|
|
3306
3567
|
return;
|
|
3307
3568
|
}
|
|
3569
|
+
const itemsTableExists = await context.tableExists();
|
|
3570
|
+
if (!itemsTableExists) {
|
|
3571
|
+
await context.createItemsTable();
|
|
3572
|
+
}
|
|
3573
|
+
const chunksTableExists = await db2.schema.hasTable(context.getChunksTableName());
|
|
3574
|
+
if (!chunksTableExists) {
|
|
3575
|
+
await context.createChunksTable();
|
|
3576
|
+
}
|
|
3308
3577
|
const item = await db2.from(context.getTableName()).where({ id: req.params.id }).select("*").first();
|
|
3309
3578
|
if (!item) {
|
|
3310
3579
|
res.status(404).json({
|
|
@@ -3426,6 +3695,20 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3426
3695
|
}
|
|
3427
3696
|
let limit = req.query.limit ? parseInt(req.query.limit) : 10;
|
|
3428
3697
|
let page = req.query.page ? parseInt(req.query.page) : 1;
|
|
3698
|
+
let sort = req.query.sort ? req.query.sort : "created_at";
|
|
3699
|
+
let order = req.query.order ? req.query.order : "desc";
|
|
3700
|
+
if (sort && !["created_at", "embeddings_updated_at"].includes(sort)) {
|
|
3701
|
+
res.status(400).json({
|
|
3702
|
+
message: "Invalid sort field, must be one of: createdAt, embeddings_updated_at"
|
|
3703
|
+
});
|
|
3704
|
+
return;
|
|
3705
|
+
}
|
|
3706
|
+
if (order && !["desc", "asc"].includes(order)) {
|
|
3707
|
+
res.status(400).json({
|
|
3708
|
+
message: "Invalid order, must be one of: desc, asc"
|
|
3709
|
+
});
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3429
3712
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3430
3713
|
if (!authenticationResult.user?.id) {
|
|
3431
3714
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3449,6 +3732,8 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3449
3732
|
return;
|
|
3450
3733
|
}
|
|
3451
3734
|
const result = await context.getItems({
|
|
3735
|
+
sort,
|
|
3736
|
+
order,
|
|
3452
3737
|
page,
|
|
3453
3738
|
limit,
|
|
3454
3739
|
archived: req.query.archived === "true",
|
|
@@ -3528,6 +3813,18 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3528
3813
|
message: "Embedding deleted."
|
|
3529
3814
|
});
|
|
3530
3815
|
});
|
|
3816
|
+
app.get("/ping", async (req, res) => {
|
|
3817
|
+
const authenticationResult = await requestValidators.authenticate(req);
|
|
3818
|
+
if (!authenticationResult.user?.id) {
|
|
3819
|
+
res.status(200).json({
|
|
3820
|
+
authenticated: false
|
|
3821
|
+
});
|
|
3822
|
+
return;
|
|
3823
|
+
}
|
|
3824
|
+
res.status(200).json({
|
|
3825
|
+
authenticated: true
|
|
3826
|
+
});
|
|
3827
|
+
});
|
|
3531
3828
|
console.log("[EXULU] statistics timeseries");
|
|
3532
3829
|
app.post("/statistics/timeseries", async (req, res) => {
|
|
3533
3830
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
@@ -3618,7 +3915,6 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3618
3915
|
const response = await db2("jobs").select(db2.raw(`to_char("createdAt", 'YYYY-MM-DD') as date`)).count("* as count").where("type", "embedder").groupByRaw(`to_char("createdAt", 'YYYY-MM-DD')`).then((rows) => ({
|
|
3619
3916
|
jobs: rows
|
|
3620
3917
|
}));
|
|
3621
|
-
console.log({ response });
|
|
3622
3918
|
let jobs = [];
|
|
3623
3919
|
if (response[0]) {
|
|
3624
3920
|
jobs = response[0].jobs.map((job) => ({
|
|
@@ -3668,6 +3964,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3668
3964
|
slug: "/contexts/" + context.id,
|
|
3669
3965
|
active: context.active,
|
|
3670
3966
|
fields: context.fields,
|
|
3967
|
+
configuration: context.configuration,
|
|
3671
3968
|
sources: context.sources.get().map((source) => ({
|
|
3672
3969
|
id: source.id,
|
|
3673
3970
|
name: source.name,
|
|
@@ -3715,13 +4012,11 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3715
4012
|
});
|
|
3716
4013
|
console.log("[EXULU] contexts get list");
|
|
3717
4014
|
app.get(`/contexts`, async (req, res) => {
|
|
3718
|
-
console.log("contexts!!");
|
|
3719
4015
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
3720
4016
|
if (!authenticationResult.user?.id) {
|
|
3721
4017
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3722
4018
|
return;
|
|
3723
4019
|
}
|
|
3724
|
-
console.log("contexts", contexts?.length);
|
|
3725
4020
|
res.status(200).json(contexts.map((context) => ({
|
|
3726
4021
|
id: context.id,
|
|
3727
4022
|
name: context.name,
|
|
@@ -3864,47 +4159,28 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3864
4159
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
3865
4160
|
return;
|
|
3866
4161
|
}
|
|
4162
|
+
console.log("[EXULU] agent tools", agentInstance.tools);
|
|
4163
|
+
const enabledTools = agentInstance.tools.map((tool2) => tools.find(({ id }) => id === tool2)).filter(Boolean);
|
|
4164
|
+
console.log("[EXULU] enabled tools", enabledTools);
|
|
3867
4165
|
if (!!stream) {
|
|
3868
|
-
const
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
const { textStream } = await chatClient.stream(req.body.messages, {
|
|
3876
|
-
threadId: `${req.body.threadId}`,
|
|
3877
|
-
// conversation id
|
|
3878
|
-
resourceId: `${req.body.resourceId}`,
|
|
3879
|
-
// user id
|
|
3880
|
-
...agent.outputSchema && { output: agent.outputSchema },
|
|
3881
|
-
maxRetries: 2,
|
|
3882
|
-
// todo make part of ExuluAgent class
|
|
3883
|
-
maxSteps: 5,
|
|
3884
|
-
// todo make part of ExuluAgent class
|
|
3885
|
-
onError: (error) => console.error("[EXULU] chat stream error.", error),
|
|
3886
|
-
onFinish: ({ response, usage }) => console.info(
|
|
3887
|
-
"[EXULU] chat stream finished.",
|
|
3888
|
-
usage
|
|
3889
|
-
)
|
|
4166
|
+
const result = agent.generateStream({
|
|
4167
|
+
messages: req.body.messages,
|
|
4168
|
+
tools: enabledTools,
|
|
4169
|
+
statistics: {
|
|
4170
|
+
label: agent.name,
|
|
4171
|
+
trigger: "agent"
|
|
4172
|
+
}
|
|
3890
4173
|
});
|
|
3891
|
-
|
|
3892
|
-
res.write(`data: ${delta}
|
|
3893
|
-
|
|
3894
|
-
`);
|
|
3895
|
-
}
|
|
3896
|
-
res.end();
|
|
4174
|
+
result.pipeDataStreamToResponse(res);
|
|
3897
4175
|
return;
|
|
3898
4176
|
} else {
|
|
3899
|
-
const response = await agent.
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
maxSteps: 5
|
|
3907
|
-
// todo make part of ExuluAgent class
|
|
4177
|
+
const response = await agent.generateSync({
|
|
4178
|
+
messages: req.body.messages,
|
|
4179
|
+
tools: enabledTools.map(),
|
|
4180
|
+
statistics: {
|
|
4181
|
+
label: agent.name,
|
|
4182
|
+
trigger: "agent"
|
|
4183
|
+
}
|
|
3908
4184
|
});
|
|
3909
4185
|
res.status(200).json(response);
|
|
3910
4186
|
return;
|
|
@@ -3979,7 +4255,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3979
4255
|
console.log("Routes:");
|
|
3980
4256
|
console.table(routeLogs);
|
|
3981
4257
|
const TARGET_API = "https://api.anthropic.com";
|
|
3982
|
-
app.use("/gateway/anthropic", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
|
|
4258
|
+
app.use("/gateway/anthropic/:id", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
|
|
3983
4259
|
const path3 = req.url;
|
|
3984
4260
|
const url = `${TARGET_API}${path3}`;
|
|
3985
4261
|
console.log("[PROXY] Manual proxy to:", url);
|
|
@@ -3988,60 +4264,102 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
|
|
|
3988
4264
|
console.log("[PROXY] Request body length:", req.body ? req.body.length : 0);
|
|
3989
4265
|
console.log("[PROXY] Request model name:", req.body.model);
|
|
3990
4266
|
console.log("[PROXY] Request stream:", req.body.stream);
|
|
3991
|
-
console.log("[PROXY] API key:", req.headers["x-api-key"]);
|
|
3992
4267
|
console.log("[PROXY] Request messages:", req.body.messages?.length);
|
|
3993
4268
|
try {
|
|
3994
|
-
const headers = {
|
|
3995
|
-
"x-api-key": process.env.ANTHROPIC_API_KEY,
|
|
3996
|
-
"anthropic-version": "2023-06-01",
|
|
3997
|
-
"content-type": req.headers["content-type"] || "application/json"
|
|
3998
|
-
};
|
|
3999
|
-
if (req.headers["accept"]) headers["accept"] = req.headers["accept"];
|
|
4000
|
-
if (req.headers["user-agent"]) headers["user-agent"] = req.headers["user-agent"];
|
|
4001
4269
|
console.log("[PROXY] Request body tools array length:", req.body.tools?.length);
|
|
4002
4270
|
if (!req.body.tools) {
|
|
4003
4271
|
req.body.tools = [];
|
|
4004
4272
|
}
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4273
|
+
const authenticationResult = await requestValidators.authenticate(req);
|
|
4274
|
+
if (!authenticationResult.user?.id) {
|
|
4275
|
+
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
4276
|
+
return;
|
|
4277
|
+
}
|
|
4278
|
+
console.log("[EXULU] authentication result", authenticationResult);
|
|
4279
|
+
const { db: db2 } = await postgresClient();
|
|
4280
|
+
const agent = await db2.from("agents").where({
|
|
4281
|
+
id: req.params.id
|
|
4282
|
+
}).first();
|
|
4283
|
+
if (!agent) {
|
|
4284
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(`
|
|
4285
|
+
\x1B[41m -- Agent ${req.params.id} not found or you do not have access to it. --
|
|
4286
|
+
\x1B[0m`);
|
|
4287
|
+
res.setHeader("Content-Type", "application/json");
|
|
4288
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4289
|
+
return;
|
|
4290
|
+
}
|
|
4291
|
+
console.log("[EXULU] agent", agent?.name);
|
|
4292
|
+
if (!process.env.NEXTAUTH_SECRET) {
|
|
4293
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.missing_nextauth_secret);
|
|
4294
|
+
res.setHeader("Content-Type", "application/json");
|
|
4295
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4296
|
+
return;
|
|
4297
|
+
}
|
|
4298
|
+
if (!authenticationResult.user?.anthropic_token) {
|
|
4299
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.not_enabled);
|
|
4300
|
+
res.setHeader("Content-Type", "application/json");
|
|
4301
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4015
4302
|
return;
|
|
4016
4303
|
}
|
|
4304
|
+
const bytes = import_crypto_js2.default.AES.decrypt(authenticationResult.user?.anthropic_token, process.env.NEXTAUTH_SECRET);
|
|
4305
|
+
const anthropicApiKey = bytes.toString(import_crypto_js2.default.enc.Utf8);
|
|
4306
|
+
const headers = {
|
|
4307
|
+
"x-api-key": anthropicApiKey,
|
|
4308
|
+
"anthropic-version": "2023-06-01",
|
|
4309
|
+
"content-type": req.headers["content-type"] || "application/json"
|
|
4310
|
+
};
|
|
4311
|
+
if (req.headers["accept"]) headers["accept"] = req.headers["accept"];
|
|
4312
|
+
if (req.headers["user-agent"]) headers["user-agent"] = req.headers["user-agent"];
|
|
4313
|
+
console.log("[EXULU] anthropic api key", anthropicApiKey);
|
|
4017
4314
|
const response = await fetch(url, {
|
|
4018
4315
|
method: req.method,
|
|
4019
4316
|
headers,
|
|
4020
4317
|
body: req.method !== "GET" ? JSON.stringify(req.body) : void 0
|
|
4021
4318
|
});
|
|
4022
|
-
console.log("[PROXY] Response
|
|
4319
|
+
console.log("[PROXY] Response:", response);
|
|
4320
|
+
console.log("[PROXY] Response:", response.body);
|
|
4321
|
+
await updateStatistic({
|
|
4322
|
+
name: "count",
|
|
4323
|
+
label: "Claude Code",
|
|
4324
|
+
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
4325
|
+
trigger: "claude-code",
|
|
4326
|
+
count: 1
|
|
4327
|
+
});
|
|
4023
4328
|
response.headers.forEach((value, key) => {
|
|
4024
4329
|
res.setHeader(key, value);
|
|
4025
4330
|
});
|
|
4026
4331
|
res.status(response.status);
|
|
4027
|
-
|
|
4332
|
+
const isStreaming = response.headers.get("content-type")?.includes("text/event-stream");
|
|
4333
|
+
if (isStreaming && !response?.body) {
|
|
4334
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.missing_body);
|
|
4335
|
+
res.setHeader("Content-Type", "application/json");
|
|
4336
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4337
|
+
return;
|
|
4338
|
+
}
|
|
4339
|
+
if (isStreaming) {
|
|
4028
4340
|
const reader = response.body.getReader();
|
|
4029
4341
|
const decoder = new TextDecoder();
|
|
4030
4342
|
while (true) {
|
|
4031
4343
|
const { done, value } = await reader.read();
|
|
4032
4344
|
if (done) break;
|
|
4033
4345
|
const chunk = decoder.decode(value, { stream: true });
|
|
4346
|
+
console.log("[PROXY] Chunk:", chunk);
|
|
4034
4347
|
res.write(chunk);
|
|
4035
4348
|
}
|
|
4036
4349
|
res.end();
|
|
4037
|
-
|
|
4038
|
-
const data = await response.arrayBuffer();
|
|
4039
|
-
res.end(Buffer.from(data));
|
|
4350
|
+
return;
|
|
4040
4351
|
}
|
|
4352
|
+
const data = await response.arrayBuffer();
|
|
4353
|
+
console.log("[PROXY] Data:", data);
|
|
4354
|
+
res.end(Buffer.from(data));
|
|
4041
4355
|
} catch (error) {
|
|
4042
4356
|
console.error("[PROXY] Manual proxy error:", error);
|
|
4043
4357
|
if (!res.headersSent) {
|
|
4044
|
-
|
|
4358
|
+
if (error?.message === "Invalid token") {
|
|
4359
|
+
res.status(500).json({ error: "Authentication error, please check your IMP token and try again." });
|
|
4360
|
+
} else {
|
|
4361
|
+
res.status(500).json({ error: error.message });
|
|
4362
|
+
}
|
|
4045
4363
|
}
|
|
4046
4364
|
}
|
|
4047
4365
|
});
|
|
@@ -4089,6 +4407,20 @@ var getPresignedFileUrl = async (key) => {
|
|
|
4089
4407
|
console.log(`[EXULU] presigned url for file with key: ${key}, generated: ${json.url}`);
|
|
4090
4408
|
return json.url;
|
|
4091
4409
|
};
|
|
4410
|
+
var createCustomAnthropicStreamingMessage = (message) => {
|
|
4411
|
+
const responseData = {
|
|
4412
|
+
type: "message",
|
|
4413
|
+
content: [
|
|
4414
|
+
{
|
|
4415
|
+
type: "text",
|
|
4416
|
+
text: message
|
|
4417
|
+
}
|
|
4418
|
+
]
|
|
4419
|
+
};
|
|
4420
|
+
const jsonString = JSON.stringify(responseData);
|
|
4421
|
+
const arrayBuffer = new TextEncoder().encode(jsonString).buffer;
|
|
4422
|
+
return arrayBuffer;
|
|
4423
|
+
};
|
|
4092
4424
|
|
|
4093
4425
|
// src/registry/workers.ts
|
|
4094
4426
|
var import_ioredis = __toESM(require("ioredis"), 1);
|
|
@@ -4141,7 +4473,7 @@ var fs2 = __toESM(require("fs"), 1);
|
|
|
4141
4473
|
var import_path = __toESM(require("path"), 1);
|
|
4142
4474
|
var defaultLogsDir = import_path.default.join(process.cwd(), "logs");
|
|
4143
4475
|
var redisConnection;
|
|
4144
|
-
var createWorkers = async (queues2, contexts,
|
|
4476
|
+
var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
|
|
4145
4477
|
if (!redisServer.host || !redisServer.port) {
|
|
4146
4478
|
console.error("[EXULU] you are trying to start workers, but no redis server is configured in the environment.");
|
|
4147
4479
|
throw new Error("No redis server configured in the environment, so cannot start workers.");
|
|
@@ -4172,7 +4504,7 @@ var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) =>
|
|
|
4172
4504
|
if (!bullmqJob.data.embedder) {
|
|
4173
4505
|
throw new Error(`No embedder set for embedder job.`);
|
|
4174
4506
|
}
|
|
4175
|
-
const embedder =
|
|
4507
|
+
const embedder = contexts.find((context2) => context2.embedder?.id === bullmqJob.data.embedder);
|
|
4176
4508
|
if (!embedder) {
|
|
4177
4509
|
throw new Error(`Embedder ${bullmqJob.data.embedder} not found in the registry.`);
|
|
4178
4510
|
}
|
|
@@ -4212,6 +4544,9 @@ var createWorkers = async (queues2, contexts, embedders, workflows, _logsDir) =>
|
|
|
4212
4544
|
duration,
|
|
4213
4545
|
result: JSON.stringify(result)
|
|
4214
4546
|
});
|
|
4547
|
+
await db2.from((void 0).getTableName()).where({ id: result[0].id }).update({
|
|
4548
|
+
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4549
|
+
}).returning("id");
|
|
4215
4550
|
return result;
|
|
4216
4551
|
}
|
|
4217
4552
|
if (bullmqJob.data.type === "workflow") {
|
|
@@ -4309,7 +4644,7 @@ var ExuluMCP = class {
|
|
|
4309
4644
|
express;
|
|
4310
4645
|
constructor() {
|
|
4311
4646
|
}
|
|
4312
|
-
create = async ({ express: express3, contexts,
|
|
4647
|
+
create = async ({ express: express3, contexts, agents, workflows, config, tools }) => {
|
|
4313
4648
|
this.express = express3;
|
|
4314
4649
|
if (!this.server) {
|
|
4315
4650
|
console.log("[EXULU] Creating MCP server.");
|
|
@@ -4386,8 +4721,6 @@ ${code}`
|
|
|
4386
4721
|
throw new Error("MCP server not initialized.");
|
|
4387
4722
|
}
|
|
4388
4723
|
const sessionId = req.headers[SESSION_ID_HEADER];
|
|
4389
|
-
console.log("sessionId!!", sessionId);
|
|
4390
|
-
console.log("req.headers!!", req.headers);
|
|
4391
4724
|
let transport;
|
|
4392
4725
|
if (sessionId && this.transports[sessionId]) {
|
|
4393
4726
|
transport = this.transports[sessionId];
|
|
@@ -4417,10 +4750,9 @@ ${code}`
|
|
|
4417
4750
|
await transport.handleRequest(req, res, req.body);
|
|
4418
4751
|
});
|
|
4419
4752
|
const handleSessionRequest = async (req, res) => {
|
|
4420
|
-
console.log("handleSessionRequest", req.body);
|
|
4421
4753
|
const sessionId = req.headers[SESSION_ID_HEADER];
|
|
4422
4754
|
if (!sessionId || !this.transports[sessionId]) {
|
|
4423
|
-
console.log("
|
|
4755
|
+
console.log("[EXULU] MCP request invalid or missing session ID");
|
|
4424
4756
|
res.status(400).send("Invalid or missing session ID");
|
|
4425
4757
|
return;
|
|
4426
4758
|
}
|
|
@@ -4443,28 +4775,210 @@ ${code}`
|
|
|
4443
4775
|
|
|
4444
4776
|
// src/registry/index.ts
|
|
4445
4777
|
var import_express7 = __toESM(require("express"), 1);
|
|
4778
|
+
|
|
4779
|
+
// src/templates/agents/claude-code.ts
|
|
4780
|
+
var agentId = "0832-5178-1145-2194";
|
|
4781
|
+
var claudeCodeAgent = new ExuluAgent({
|
|
4782
|
+
id: `${agentId}-claude-code-agent`,
|
|
4783
|
+
name: `Claude Code Agent`,
|
|
4784
|
+
description: `Claude Code agent, enabling the creation of multiple Claude Code Agent instances with different configurations (rate limits, functions, etc).`,
|
|
4785
|
+
type: "custom"
|
|
4786
|
+
});
|
|
4787
|
+
|
|
4788
|
+
// src/templates/agents/claude-opus-4.ts
|
|
4789
|
+
var import_anthropic = require("@ai-sdk/anthropic");
|
|
4790
|
+
var import_zod4 = require("zod");
|
|
4791
|
+
var agentId2 = "5434-5678-9143-2590";
|
|
4792
|
+
var defaultAgent = new ExuluAgent({
|
|
4793
|
+
id: `${agentId2}-default-claude-4-opus-agent`,
|
|
4794
|
+
name: `Default Claude 4 Opus Agent`,
|
|
4795
|
+
description: `Basic agent without any defined tools, that can support MCP's.`,
|
|
4796
|
+
type: "agent",
|
|
4797
|
+
capabilities: {
|
|
4798
|
+
tools: false,
|
|
4799
|
+
images: [],
|
|
4800
|
+
files: [],
|
|
4801
|
+
audio: [],
|
|
4802
|
+
video: []
|
|
4803
|
+
},
|
|
4804
|
+
evals: [],
|
|
4805
|
+
config: {
|
|
4806
|
+
name: `Default agent`,
|
|
4807
|
+
instructions: "You are a helpful assistant.",
|
|
4808
|
+
model: (0, import_anthropic.anthropic)("claude-4-opus-20250514"),
|
|
4809
|
+
// todo add a field of type string that adds a dropdown list from which the user can select the model
|
|
4810
|
+
// todo for each model, check which provider is used, and require the admin to add one or multiple
|
|
4811
|
+
// API keys for the provider (which we can then auto-rotate).
|
|
4812
|
+
// todo also add custom fields for rate limiting, so the admin can set custom rate limits for the agent
|
|
4813
|
+
// and allow him/her to decide if the rate limit is per user or per agent.
|
|
4814
|
+
// todo finally allow switching on or off immutable audit logs on the agent. Which then enables OTEL
|
|
4815
|
+
// and stores the logs into the pre-defined storage.
|
|
4816
|
+
custom: import_zod4.z.object({
|
|
4817
|
+
apiKey: import_zod4.z.string()
|
|
4818
|
+
})
|
|
4819
|
+
}
|
|
4820
|
+
});
|
|
4821
|
+
|
|
4822
|
+
// src/templates/tools/browserbase.ts
|
|
4823
|
+
var import_zod5 = require("zod");
|
|
4824
|
+
var import_stagehand = require("@browserbasehq/stagehand");
|
|
4825
|
+
var import_sdk = require("@browserbasehq/sdk");
|
|
4826
|
+
var PROJECT_ID = "811444dd-6e6d-40b5-bd90-541c93e44be6";
|
|
4827
|
+
process.env.BROWSERBASE_PROJECT_ID = PROJECT_ID;
|
|
4828
|
+
var BB_API_KEY = "bb_live_LwMwNgZB5cIEKcBwMuAugrgNkFM";
|
|
4829
|
+
async function createContext() {
|
|
4830
|
+
const bb = new import_sdk.Browserbase({ apiKey: BB_API_KEY });
|
|
4831
|
+
const context = await bb.contexts.create({
|
|
4832
|
+
projectId: PROJECT_ID
|
|
4833
|
+
});
|
|
4834
|
+
return context;
|
|
4835
|
+
}
|
|
4836
|
+
async function createAuthSession(contextId) {
|
|
4837
|
+
const bb = new import_sdk.Browserbase({ apiKey: BB_API_KEY });
|
|
4838
|
+
const session = await bb.sessions.create({
|
|
4839
|
+
projectId: PROJECT_ID,
|
|
4840
|
+
browserSettings: {
|
|
4841
|
+
context: {
|
|
4842
|
+
id: contextId,
|
|
4843
|
+
persist: true
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
/* proxies: [{ // not included in the free tier
|
|
4847
|
+
type: "browserbase",
|
|
4848
|
+
geolocation: {
|
|
4849
|
+
city: CITY,
|
|
4850
|
+
country: COUNTRY
|
|
4851
|
+
}
|
|
4852
|
+
}] */
|
|
4853
|
+
});
|
|
4854
|
+
const liveViewLinks = await bb.sessions.debug(session.id);
|
|
4855
|
+
const liveViewLink = liveViewLinks.debuggerFullscreenUrl;
|
|
4856
|
+
console.log(`\u{1F50D} Live View Link: ${liveViewLink}`);
|
|
4857
|
+
console.log("Session URL: https://browserbase.com/sessions/" + session.id);
|
|
4858
|
+
return {
|
|
4859
|
+
url: liveViewLink,
|
|
4860
|
+
id: session.id
|
|
4861
|
+
};
|
|
4862
|
+
}
|
|
4863
|
+
var createSession = new ExuluTool({
|
|
4864
|
+
id: `1234-5178-9423-4267`,
|
|
4865
|
+
type: "function",
|
|
4866
|
+
name: "Create a browserbase session.",
|
|
4867
|
+
description: `
|
|
4868
|
+
Creates a browserbase session and returns the live view url as well as
|
|
4869
|
+
the session id as a JSON object. A browserbase session is a headless browser
|
|
4870
|
+
that can be used to to visit websites and perform actions.
|
|
4871
|
+
`,
|
|
4872
|
+
execute: async () => {
|
|
4873
|
+
const { id } = await createContext();
|
|
4874
|
+
return await createAuthSession(id);
|
|
4875
|
+
}
|
|
4876
|
+
});
|
|
4877
|
+
var askChatgpt = new ExuluTool({
|
|
4878
|
+
id: `1234-5178-9423-4268`,
|
|
4879
|
+
type: "function",
|
|
4880
|
+
name: "ChatGPT browserbase operation.",
|
|
4881
|
+
inputSchema: import_zod5.z.object({
|
|
4882
|
+
session: import_zod5.z.string().describe("The session id of the browserbase session."),
|
|
4883
|
+
question: import_zod5.z.string().describe("The question to ask ChatGPT.")
|
|
4884
|
+
}),
|
|
4885
|
+
description: `Uses an existing, authenticated browserbase session to visit ChatGPT and perform actions such as asking questions.`,
|
|
4886
|
+
execute: async ({ session, question }) => {
|
|
4887
|
+
const stagehand = new import_stagehand.Stagehand({
|
|
4888
|
+
// With npx create-browser-app, this config is found
|
|
4889
|
+
// in a separate stagehand.config.ts file
|
|
4890
|
+
env: "BROWSERBASE",
|
|
4891
|
+
// set to "LOCAL" for local development
|
|
4892
|
+
apiKey: BB_API_KEY,
|
|
4893
|
+
// todo make this a config variable the admin can set in the UI
|
|
4894
|
+
modelName: "openai/gpt-4.1-mini",
|
|
4895
|
+
// todo change to claude || optionally make configurable?
|
|
4896
|
+
browserbaseSessionID: session,
|
|
4897
|
+
modelClientOptions: {
|
|
4898
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
4899
|
+
// todo make this a config variable the admin can set in the UI
|
|
4900
|
+
}
|
|
4901
|
+
});
|
|
4902
|
+
await stagehand.init();
|
|
4903
|
+
const page = stagehand.page;
|
|
4904
|
+
await page.goto("https://chatgpt.com");
|
|
4905
|
+
await page.act(`Type in '${question}' into the search bar`);
|
|
4906
|
+
const { answer } = await page.extract({
|
|
4907
|
+
instruction: "The answer to the question generated by ChatGPT.",
|
|
4908
|
+
schema: import_zod5.z.object({
|
|
4909
|
+
answer: import_zod5.z.string()
|
|
4910
|
+
})
|
|
4911
|
+
});
|
|
4912
|
+
console.log(answer);
|
|
4913
|
+
await stagehand.close();
|
|
4914
|
+
return {
|
|
4915
|
+
answer
|
|
4916
|
+
};
|
|
4917
|
+
}
|
|
4918
|
+
});
|
|
4919
|
+
|
|
4920
|
+
// src/templates/tools/jira.ts
|
|
4921
|
+
var import_zod6 = require("zod");
|
|
4922
|
+
var getTicket = new ExuluTool({
|
|
4923
|
+
id: `1414-5179-1423-1269`,
|
|
4924
|
+
name: "JIRA ticket retrieval.",
|
|
4925
|
+
type: "function",
|
|
4926
|
+
inputSchema: import_zod6.z.object({
|
|
4927
|
+
ticketId: import_zod6.z.string().describe("The id of the ticket to retrieve.")
|
|
4928
|
+
}),
|
|
4929
|
+
description: `Retrieves a ticket from Jira.`,
|
|
4930
|
+
execute: async ({ session, question }) => {
|
|
4931
|
+
return {
|
|
4932
|
+
name: "BYD-1234",
|
|
4933
|
+
id: "12345678",
|
|
4934
|
+
status: "Open",
|
|
4935
|
+
description: "This is a test ticket",
|
|
4936
|
+
assignee: "John Doe",
|
|
4937
|
+
createdAt: "2021-01-01",
|
|
4938
|
+
updatedAt: "2021-01-01",
|
|
4939
|
+
dueDate: "2021-01-01",
|
|
4940
|
+
priority: "High"
|
|
4941
|
+
};
|
|
4942
|
+
}
|
|
4943
|
+
});
|
|
4944
|
+
|
|
4945
|
+
// src/registry/index.ts
|
|
4446
4946
|
var ExuluApp = class {
|
|
4447
4947
|
_agents = [];
|
|
4448
4948
|
_workflows = [];
|
|
4449
4949
|
_config;
|
|
4450
|
-
_embedders = [];
|
|
4451
4950
|
_queues = [];
|
|
4452
4951
|
_contexts = {};
|
|
4453
4952
|
_tools = [];
|
|
4454
4953
|
_expressApp = null;
|
|
4455
4954
|
constructor() {
|
|
4456
4955
|
}
|
|
4457
|
-
// Factory function so we can async
|
|
4458
|
-
// MCP server if needed.
|
|
4459
|
-
create = async ({ contexts,
|
|
4460
|
-
this._embedders = embedders ?? [];
|
|
4956
|
+
// Factory function so we can async
|
|
4957
|
+
// initialize the MCP server if needed.
|
|
4958
|
+
create = async ({ contexts, agents, workflows, config, tools }) => {
|
|
4461
4959
|
this._workflows = workflows ?? [];
|
|
4462
4960
|
this._contexts = contexts ?? {};
|
|
4463
|
-
this._agents =
|
|
4961
|
+
this._agents = [
|
|
4962
|
+
claudeCodeAgent,
|
|
4963
|
+
defaultAgent,
|
|
4964
|
+
...agents ?? []
|
|
4965
|
+
];
|
|
4464
4966
|
this._config = config;
|
|
4465
|
-
this._tools =
|
|
4967
|
+
this._tools = [
|
|
4968
|
+
...tools ?? [],
|
|
4969
|
+
// Add contexts as tools
|
|
4970
|
+
...Object.values(contexts || {}).map((context) => context.tool()),
|
|
4971
|
+
// Add agents as tools
|
|
4972
|
+
...(agents || []).map((agent) => agent.tool()),
|
|
4973
|
+
...[
|
|
4974
|
+
createSession,
|
|
4975
|
+
askChatgpt,
|
|
4976
|
+
getTicket
|
|
4977
|
+
]
|
|
4978
|
+
];
|
|
4979
|
+
const contextsArray = Object.values(contexts || {});
|
|
4466
4980
|
const queues2 = [
|
|
4467
|
-
...
|
|
4981
|
+
...contextsArray?.length ? contextsArray.map((context) => context.embedder.queue?.name || null) : [],
|
|
4468
4982
|
...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
|
|
4469
4983
|
];
|
|
4470
4984
|
this._queues = [...new Set(queues2.filter((o) => !!o))];
|
|
@@ -4481,9 +4995,6 @@ var ExuluApp = class {
|
|
|
4481
4995
|
}
|
|
4482
4996
|
return this._expressApp;
|
|
4483
4997
|
}
|
|
4484
|
-
embedder(id) {
|
|
4485
|
-
return this._embedders.find((x) => x.id === id);
|
|
4486
|
-
}
|
|
4487
4998
|
tool(id) {
|
|
4488
4999
|
return this._tools.find((x) => x.id === id);
|
|
4489
5000
|
}
|
|
@@ -4499,9 +5010,6 @@ var ExuluApp = class {
|
|
|
4499
5010
|
workflow(id) {
|
|
4500
5011
|
return this._workflows.find((x) => x.id === id);
|
|
4501
5012
|
}
|
|
4502
|
-
get embedders() {
|
|
4503
|
-
return this._embedders;
|
|
4504
|
-
}
|
|
4505
5013
|
get contexts() {
|
|
4506
5014
|
return Object.values(this._contexts ?? {});
|
|
4507
5015
|
}
|
|
@@ -4517,7 +5025,6 @@ var ExuluApp = class {
|
|
|
4517
5025
|
return await createWorkers(
|
|
4518
5026
|
this._queues,
|
|
4519
5027
|
Object.values(this._contexts ?? {}),
|
|
4520
|
-
this._embedders,
|
|
4521
5028
|
this._workflows,
|
|
4522
5029
|
this._config?.workers?.logsDir
|
|
4523
5030
|
);
|
|
@@ -4534,7 +5041,6 @@ var ExuluApp = class {
|
|
|
4534
5041
|
await createExpressRoutes(
|
|
4535
5042
|
app,
|
|
4536
5043
|
this._agents,
|
|
4537
|
-
this._embedders,
|
|
4538
5044
|
this._tools,
|
|
4539
5045
|
this._workflows,
|
|
4540
5046
|
Object.values(this._contexts ?? {})
|
|
@@ -4544,7 +5050,6 @@ var ExuluApp = class {
|
|
|
4544
5050
|
await mcp.create({
|
|
4545
5051
|
express: app,
|
|
4546
5052
|
contexts: this._contexts,
|
|
4547
|
-
embedders: this._embedders,
|
|
4548
5053
|
agents: this._agents,
|
|
4549
5054
|
workflows: this._workflows,
|
|
4550
5055
|
config: this._config,
|
|
@@ -4873,15 +5378,12 @@ var ExuluTokenizer = class {
|
|
|
4873
5378
|
console.log("[EXULU] Loading tokenizer.", modelName);
|
|
4874
5379
|
const model = await (0, import_load.load)(import_registry.default[import_model_to_encoding.default[modelName]]);
|
|
4875
5380
|
console.log("[EXULU] Loaded tokenizer.", modelName, performance.now() - time);
|
|
4876
|
-
console.log("[EXULU] Model.", model.bpe_ranks);
|
|
4877
|
-
console.log("[EXULU] Model.", model.special_tokens);
|
|
4878
|
-
console.log("[EXULU] Model.", model.pat_str);
|
|
4879
5381
|
const encoder = new import_lite.Tiktoken(
|
|
4880
5382
|
model.bpe_ranks,
|
|
4881
5383
|
model.special_tokens,
|
|
4882
5384
|
model.pat_str
|
|
4883
5385
|
);
|
|
4884
|
-
console.log("[EXULU]
|
|
5386
|
+
console.log("[EXULU] Set encoder.");
|
|
4885
5387
|
this.encoder = encoder;
|
|
4886
5388
|
return encoder;
|
|
4887
5389
|
}
|
|
@@ -4904,9 +5406,9 @@ var ExuluTokenizer = class {
|
|
|
4904
5406
|
throw new Error("Tokenizer not initialized");
|
|
4905
5407
|
}
|
|
4906
5408
|
const time = performance.now();
|
|
4907
|
-
console.log("[EXULU] Encoding text
|
|
5409
|
+
console.log("[EXULU] Encoding text length: " + (text?.length || 0));
|
|
4908
5410
|
const tokens = this.encoder.encode(text);
|
|
4909
|
-
console.log("[EXULU]
|
|
5411
|
+
console.log("[EXULU] Finished encoding text.", performance.now() - time);
|
|
4910
5412
|
return tokens;
|
|
4911
5413
|
}
|
|
4912
5414
|
async countTokensBatch(texts) {
|
|
@@ -4920,7 +5422,6 @@ var ExuluTokenizer = class {
|
|
|
4920
5422
|
if (!this.encoder) {
|
|
4921
5423
|
throw new Error("Tokenizer not initialized");
|
|
4922
5424
|
}
|
|
4923
|
-
console.log("[EXULU] Counting tokens.", text);
|
|
4924
5425
|
const tokens = this.encoder.encode(text);
|
|
4925
5426
|
const count = tokens.length;
|
|
4926
5427
|
console.log("[EXULU] Token count.", count);
|
|
@@ -5090,8 +5591,6 @@ var RecursiveChunker = class _RecursiveChunker extends BaseChunker {
|
|
|
5090
5591
|
*
|
|
5091
5592
|
* @example <caption>Accessing properties and methods</caption>
|
|
5092
5593
|
* const chunker = await RecursiveChunker.create();
|
|
5093
|
-
* console.log(chunker.chunkSize); // 512
|
|
5094
|
-
* console.log(chunker.rules); // RecursiveRules instance
|
|
5095
5594
|
* const chunks = await chunker.chunk("Some text"); // Use as object method
|
|
5096
5595
|
*
|
|
5097
5596
|
* @note
|
|
@@ -5310,8 +5809,6 @@ var RecursiveChunker = class _RecursiveChunker extends BaseChunker {
|
|
|
5310
5809
|
if (!text) {
|
|
5311
5810
|
return [];
|
|
5312
5811
|
}
|
|
5313
|
-
console.log("[EXULU] Rule.", this.rules.length);
|
|
5314
|
-
console.log("[EXULU] Level.", level);
|
|
5315
5812
|
if (level >= this.rules.length) {
|
|
5316
5813
|
const tokenCount = await this._estimateTokenCount(text);
|
|
5317
5814
|
return [
|
|
@@ -5375,7 +5872,6 @@ var RecursiveChunker = class _RecursiveChunker extends BaseChunker {
|
|
|
5375
5872
|
* @returns {Promise<RecursiveChunk[]>} A promise that resolves to an array of RecursiveChunk objects
|
|
5376
5873
|
*/
|
|
5377
5874
|
async chunk(text) {
|
|
5378
|
-
console.log("[EXULU] Chunking text.", text);
|
|
5379
5875
|
const result = await this._recursiveChunk(text, 0, 0);
|
|
5380
5876
|
await this.tokenizer.free();
|
|
5381
5877
|
return result;
|
|
@@ -5761,200 +6257,6 @@ var SentenceChunker = class _SentenceChunker extends BaseChunker {
|
|
|
5761
6257
|
}
|
|
5762
6258
|
};
|
|
5763
6259
|
|
|
5764
|
-
// src/cli/index.tsx
|
|
5765
|
-
var import_react2 = require("react");
|
|
5766
|
-
var import_ink4 = require("ink");
|
|
5767
|
-
var import_ui5 = require("@inkjs/ui");
|
|
5768
|
-
var import_patch_console = __toESM(require("patch-console"), 1);
|
|
5769
|
-
|
|
5770
|
-
// src/cli/components/nav.tsx
|
|
5771
|
-
var import_ui = require("@inkjs/ui");
|
|
5772
|
-
var import_ink = require("ink");
|
|
5773
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
5774
|
-
var nav = [
|
|
5775
|
-
{
|
|
5776
|
-
label: "Agents",
|
|
5777
|
-
value: "agents"
|
|
5778
|
-
},
|
|
5779
|
-
{
|
|
5780
|
-
label: "Start Claude Code",
|
|
5781
|
-
value: "claude-code"
|
|
5782
|
-
},
|
|
5783
|
-
{
|
|
5784
|
-
label: "Exit",
|
|
5785
|
-
value: "exit"
|
|
5786
|
-
}
|
|
5787
|
-
];
|
|
5788
|
-
var Nav = ({ setView }) => {
|
|
5789
|
-
const { exit } = (0, import_ink.useApp)();
|
|
5790
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Select, { options: nav, onChange: (value) => {
|
|
5791
|
-
if (value === "exit") {
|
|
5792
|
-
exit();
|
|
5793
|
-
}
|
|
5794
|
-
setView(value);
|
|
5795
|
-
} });
|
|
5796
|
-
};
|
|
5797
|
-
var nav_default = Nav;
|
|
5798
|
-
|
|
5799
|
-
// src/cli/components/agent-selector.tsx
|
|
5800
|
-
var import_ink2 = require("ink");
|
|
5801
|
-
var import_ui2 = require("@inkjs/ui");
|
|
5802
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
5803
|
-
var AgentSelector = ({ exulu, setAgent, setEvaluations }) => {
|
|
5804
|
-
const agents = exulu.agents.map((agent) => ({
|
|
5805
|
-
label: agent.name,
|
|
5806
|
-
value: agent.id
|
|
5807
|
-
}));
|
|
5808
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
5809
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Text, { children: "Please select an agent:" }),
|
|
5810
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Select, { options: agents, onChange: (value) => {
|
|
5811
|
-
console.log("selected agent", value);
|
|
5812
|
-
const agent = exulu.agent(value);
|
|
5813
|
-
if (!agent) {
|
|
5814
|
-
console.error("Agent not found", value);
|
|
5815
|
-
return;
|
|
5816
|
-
}
|
|
5817
|
-
setAgent(agent);
|
|
5818
|
-
if (agent) {
|
|
5819
|
-
setEvaluations(agent.evals || []);
|
|
5820
|
-
}
|
|
5821
|
-
} })
|
|
5822
|
-
] });
|
|
5823
|
-
};
|
|
5824
|
-
var agent_selector_default = AgentSelector;
|
|
5825
|
-
|
|
5826
|
-
// src/cli/components/eval-selector.tsx
|
|
5827
|
-
var import_ui3 = require("@inkjs/ui");
|
|
5828
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
5829
|
-
var EvalSelector = ({ evaluations, setEvaluation }) => {
|
|
5830
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Select, { options: evaluations.map((evaluation) => ({
|
|
5831
|
-
label: evaluation.runner.name,
|
|
5832
|
-
value: evaluation.runner.name
|
|
5833
|
-
})), onChange: (value) => {
|
|
5834
|
-
console.log("selected eval", value);
|
|
5835
|
-
const evaluation = evaluations?.find((evaluation2) => evaluation2.runner.name === value);
|
|
5836
|
-
if (evaluation) {
|
|
5837
|
-
setEvaluation(evaluation);
|
|
5838
|
-
}
|
|
5839
|
-
} });
|
|
5840
|
-
};
|
|
5841
|
-
var eval_selector_default = EvalSelector;
|
|
5842
|
-
|
|
5843
|
-
// src/cli/components/eval-actions.tsx
|
|
5844
|
-
var import_react = require("react");
|
|
5845
|
-
var import_ui4 = require("@inkjs/ui");
|
|
5846
|
-
var import_ink3 = require("ink");
|
|
5847
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
5848
|
-
var EvalActions = ({ agent, evaluation, setEvaluation }) => {
|
|
5849
|
-
const [progress, setProgress] = (0, import_react.useState)(0);
|
|
5850
|
-
const [results, setResults] = (0, import_react.useState)([]);
|
|
5851
|
-
const [running, setRunning] = (0, import_react.useState)();
|
|
5852
|
-
const run = async (evaluation2) => {
|
|
5853
|
-
setRunning({
|
|
5854
|
-
label: evaluation2.runner.name
|
|
5855
|
-
});
|
|
5856
|
-
const testCases = evaluation2.runner.testcases;
|
|
5857
|
-
const total = testCases.length;
|
|
5858
|
-
if (!testCases) {
|
|
5859
|
-
throw new Error("No test cases found");
|
|
5860
|
-
}
|
|
5861
|
-
let i = 0;
|
|
5862
|
-
for (const testCase of testCases) {
|
|
5863
|
-
i++;
|
|
5864
|
-
const result = await evaluation2.runner.run({
|
|
5865
|
-
data: testCase,
|
|
5866
|
-
runner: {
|
|
5867
|
-
agent
|
|
5868
|
-
}
|
|
5869
|
-
});
|
|
5870
|
-
setProgress(Math.round(i / total * 100));
|
|
5871
|
-
setResults([...results, {
|
|
5872
|
-
name: evaluation2.runner.name,
|
|
5873
|
-
prompt: testCase.prompt?.slice(0, 100) + "...",
|
|
5874
|
-
score: result.score,
|
|
5875
|
-
comment: result.comment
|
|
5876
|
-
}]);
|
|
5877
|
-
}
|
|
5878
|
-
setRunning(void 0);
|
|
5879
|
-
};
|
|
5880
|
-
if (progress === 100) {
|
|
5881
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
5882
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink3.Text, { children: "Evaluations completed." }),
|
|
5883
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.UnorderedList, { children: results.map((result) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.UnorderedList.Item, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ink3.Text, { children: [
|
|
5884
|
-
result.name,
|
|
5885
|
-
": ",
|
|
5886
|
-
result.score,
|
|
5887
|
-
" - ",
|
|
5888
|
-
result.comment
|
|
5889
|
-
] }) })) })
|
|
5890
|
-
] });
|
|
5891
|
-
}
|
|
5892
|
-
if (running) {
|
|
5893
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
5894
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ink3.Text, { children: [
|
|
5895
|
-
"Running ",
|
|
5896
|
-
running.label,
|
|
5897
|
-
"..."
|
|
5898
|
-
] }),
|
|
5899
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.ProgressBar, { value: progress })
|
|
5900
|
-
] });
|
|
5901
|
-
}
|
|
5902
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Select, { options: [{
|
|
5903
|
-
label: "Run evaluation",
|
|
5904
|
-
value: "run"
|
|
5905
|
-
}, {
|
|
5906
|
-
label: "Go back",
|
|
5907
|
-
value: "back"
|
|
5908
|
-
}], onChange: (value) => {
|
|
5909
|
-
if (value === "back") {
|
|
5910
|
-
setEvaluation(void 0);
|
|
5911
|
-
}
|
|
5912
|
-
if (value === "run") {
|
|
5913
|
-
run(evaluation);
|
|
5914
|
-
}
|
|
5915
|
-
} });
|
|
5916
|
-
};
|
|
5917
|
-
var eval_actions_default = EvalActions;
|
|
5918
|
-
|
|
5919
|
-
// src/cli/index.tsx
|
|
5920
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
5921
|
-
var Main = ({ exulu }) => {
|
|
5922
|
-
(0, import_patch_console.default)((stream, data) => {
|
|
5923
|
-
setLogs([...logs, data]);
|
|
5924
|
-
});
|
|
5925
|
-
const [logs, setLogs] = (0, import_react2.useState)([]);
|
|
5926
|
-
const [view, setView] = (0, import_react2.useState)();
|
|
5927
|
-
const [agent, setAgent] = (0, import_react2.useState)();
|
|
5928
|
-
const [evaluations, setEvaluations] = (0, import_react2.useState)([]);
|
|
5929
|
-
const [evaluation, setEvaluation] = (0, import_react2.useState)();
|
|
5930
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink4.Box, { borderStyle: "round", borderColor: "cyan", padding: 1, flexDirection: "column", width: "70%", children: [
|
|
5931
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink4.Text, { children: "Logs:" }),
|
|
5932
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.UnorderedList, { children: logs.map((log, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.UnorderedList.Item, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink4.Text, { children: log }) })) }),
|
|
5933
|
-
!view && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(nav_default, { setView }),
|
|
5934
|
-
view === "agents" && !agent && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(agent_selector_default, { exulu, setAgent, setEvaluations }),
|
|
5935
|
-
view === "agents" && agent && !evaluation && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
5936
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink4.Text, { children: [
|
|
5937
|
-
'Selected agent "',
|
|
5938
|
-
agent.name,
|
|
5939
|
-
'". Please select an evaluation:'
|
|
5940
|
-
] }),
|
|
5941
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(eval_selector_default, { evaluations, setEvaluation })
|
|
5942
|
-
] }),
|
|
5943
|
-
view === "agents" && agent && evaluation && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
5944
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink4.Text, { children: [
|
|
5945
|
-
"Selected evaluation: ",
|
|
5946
|
-
evaluation.runner.name
|
|
5947
|
-
] }),
|
|
5948
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(eval_actions_default, { agent, evaluation, setEvaluation })
|
|
5949
|
-
] })
|
|
5950
|
-
] });
|
|
5951
|
-
};
|
|
5952
|
-
var cli_default = {
|
|
5953
|
-
run: (exulu) => {
|
|
5954
|
-
(0, import_ink4.render)(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Main, { exulu }));
|
|
5955
|
-
}
|
|
5956
|
-
};
|
|
5957
|
-
|
|
5958
6260
|
// src/index.ts
|
|
5959
6261
|
var ExuluJobs = {
|
|
5960
6262
|
redis: redisClient,
|
|
@@ -5985,7 +6287,6 @@ var ExuluDatabase = {
|
|
|
5985
6287
|
ExuluApp,
|
|
5986
6288
|
ExuluAuthentication,
|
|
5987
6289
|
ExuluChunkers,
|
|
5988
|
-
ExuluCli,
|
|
5989
6290
|
ExuluContext,
|
|
5990
6291
|
ExuluDatabase,
|
|
5991
6292
|
ExuluEmbedder,
|