@exulu/backend 1.6.2 → 1.8.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 +1 -1
- package/.nvmrc +1 -0
- package/CHANGELOG.md +7 -2
- package/dist/index.cjs +202 -69
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +204 -71
- package/lms.md +3 -0
- package/package.json +3 -2
- package/types/models/user.ts +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,14 @@ interface ExuluAgentParams {
|
|
|
123
123
|
outputSchema?: ZodSchema;
|
|
124
124
|
rateLimit?: RateLimiterRule;
|
|
125
125
|
}
|
|
126
|
+
interface ExuluAgentToolConfig {
|
|
127
|
+
toolId: string;
|
|
128
|
+
config: {
|
|
129
|
+
name: string;
|
|
130
|
+
variable: string;
|
|
131
|
+
value?: any;
|
|
132
|
+
}[];
|
|
133
|
+
}
|
|
126
134
|
declare class ExuluAgent {
|
|
127
135
|
id: string;
|
|
128
136
|
name: string;
|
|
@@ -142,17 +150,19 @@ declare class ExuluAgent {
|
|
|
142
150
|
};
|
|
143
151
|
constructor({ id, name, description, config, rateLimit, capabilities, type, evals }: ExuluAgentParams);
|
|
144
152
|
tool: () => ExuluTool;
|
|
145
|
-
generateSync: ({ messages, prompt, tools, statistics }: {
|
|
153
|
+
generateSync: ({ messages, prompt, tools, statistics, configs }: {
|
|
146
154
|
messages?: Message[];
|
|
147
155
|
prompt?: string;
|
|
148
156
|
tools?: ExuluTool[];
|
|
149
157
|
statistics?: ExuluStatisticParams;
|
|
158
|
+
configs?: ExuluAgentToolConfig[];
|
|
150
159
|
}) => Promise<string>;
|
|
151
|
-
generateStream: ({ messages, prompt, tools, statistics }: {
|
|
160
|
+
generateStream: ({ messages, prompt, tools, statistics, configs }: {
|
|
152
161
|
messages?: Message[];
|
|
153
162
|
prompt?: string;
|
|
154
163
|
tools?: ExuluTool[];
|
|
155
164
|
statistics?: ExuluStatisticParams;
|
|
165
|
+
configs?: ExuluAgentToolConfig[];
|
|
156
166
|
}) => ai.StreamTextResult<Record<string, Tool>, never>;
|
|
157
167
|
}
|
|
158
168
|
type VectorOperationResponse = Promise<{
|
|
@@ -303,18 +313,27 @@ declare class ExuluTool {
|
|
|
303
313
|
inputSchema?: ZodSchema;
|
|
304
314
|
type: "context" | "function" | "agent";
|
|
305
315
|
tool: Tool;
|
|
306
|
-
|
|
316
|
+
config: {
|
|
317
|
+
name: string;
|
|
318
|
+
description: string;
|
|
319
|
+
}[];
|
|
320
|
+
constructor({ id, name, description, inputSchema, type, execute, config }: {
|
|
307
321
|
id: string;
|
|
308
322
|
name: string;
|
|
309
323
|
description: string;
|
|
310
324
|
inputSchema?: ZodSchema;
|
|
311
325
|
type: "context" | "function" | "agent";
|
|
326
|
+
config: {
|
|
327
|
+
name: string;
|
|
328
|
+
description: string;
|
|
329
|
+
}[];
|
|
312
330
|
execute: (inputs: any) => Promise<any>;
|
|
313
331
|
});
|
|
314
332
|
}
|
|
315
333
|
type ExuluContextFieldDefinition = {
|
|
316
334
|
name: string;
|
|
317
335
|
type: ExuluFieldTypes;
|
|
336
|
+
unique?: boolean;
|
|
318
337
|
};
|
|
319
338
|
declare class ExuluContext {
|
|
320
339
|
id: string;
|
|
@@ -512,6 +531,7 @@ type User = {
|
|
|
512
531
|
emailVerified?: string;
|
|
513
532
|
type?: "api" | "user";
|
|
514
533
|
anthropic_token?: string;
|
|
534
|
+
super_admin?: boolean;
|
|
515
535
|
roles?: {
|
|
516
536
|
id: string;
|
|
517
537
|
role: string;
|
package/dist/index.js
CHANGED
|
@@ -261,41 +261,50 @@ var bullmqDecorator = async ({
|
|
|
261
261
|
};
|
|
262
262
|
|
|
263
263
|
// src/registry/utils/map-types.ts
|
|
264
|
-
var mapType = (t, type, name, defaultValue) => {
|
|
264
|
+
var mapType = (t, type, name, defaultValue, unique) => {
|
|
265
265
|
if (type === "text") {
|
|
266
266
|
t.text(name);
|
|
267
|
+
if (unique) t.unique(name);
|
|
267
268
|
return;
|
|
268
269
|
}
|
|
269
270
|
if (type === "longText") {
|
|
270
271
|
t.text(name);
|
|
272
|
+
if (unique) t.unique(name);
|
|
271
273
|
return;
|
|
272
274
|
}
|
|
273
275
|
if (type === "shortText") {
|
|
274
276
|
t.string(name, 100);
|
|
277
|
+
if (unique) t.unique(name);
|
|
275
278
|
return;
|
|
276
279
|
}
|
|
277
280
|
if (type === "number") {
|
|
278
281
|
t.float(name);
|
|
282
|
+
if (unique) t.unique(name);
|
|
279
283
|
return;
|
|
280
284
|
}
|
|
281
285
|
if (type === "boolean") {
|
|
282
286
|
t.boolean(name).defaultTo(defaultValue || false);
|
|
287
|
+
if (unique) t.unique(name);
|
|
283
288
|
return;
|
|
284
289
|
}
|
|
285
290
|
if (type === "code") {
|
|
286
291
|
t.text(name);
|
|
292
|
+
if (unique) t.unique(name);
|
|
287
293
|
return;
|
|
288
294
|
}
|
|
289
295
|
if (type === "json") {
|
|
290
296
|
t.jsonb(name);
|
|
297
|
+
if (unique) t.unique(name);
|
|
291
298
|
return;
|
|
292
299
|
}
|
|
293
300
|
if (type === "date") {
|
|
294
301
|
t.timestamp(name);
|
|
302
|
+
if (unique) t.unique(name);
|
|
295
303
|
return;
|
|
296
304
|
}
|
|
297
305
|
if (type === "uuid") {
|
|
298
306
|
t.uuid(name);
|
|
307
|
+
if (unique) t.unique(name);
|
|
299
308
|
return;
|
|
300
309
|
}
|
|
301
310
|
throw new Error("Invalid type: " + type);
|
|
@@ -394,7 +403,39 @@ var ExuluEvalUtils = {
|
|
|
394
403
|
}
|
|
395
404
|
};
|
|
396
405
|
|
|
406
|
+
// src/registry/utils/claude-messages.ts
|
|
407
|
+
var CLAUDE_MESSAGES = {
|
|
408
|
+
anthropic_token_variable_not_encrypted: `
|
|
409
|
+
\x1B[41m -- Anthropic token variable set by your admin is not encrypted. This poses a security risk. Please contact your admin to fix the variable used for your key. --
|
|
410
|
+
\x1B[0m`,
|
|
411
|
+
anthropic_token_variable_not_found: `
|
|
412
|
+
\x1B[41m -- Anthropic token variable not found. Please contact to fix the variable used for your key. --
|
|
413
|
+
\x1B[0m`,
|
|
414
|
+
authentication_error: `
|
|
415
|
+
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
416
|
+
\x1B[0m`,
|
|
417
|
+
missing_body: `
|
|
418
|
+
\x1B[41m -- Missing body Anthropic response. --
|
|
419
|
+
\x1B[0m`,
|
|
420
|
+
missing_nextauth_secret: `
|
|
421
|
+
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
422
|
+
\x1B[0m`,
|
|
423
|
+
not_enabled: `
|
|
424
|
+
\x1B[31m
|
|
425
|
+
\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
|
|
426
|
+
\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
|
|
427
|
+
\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
|
|
428
|
+
\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
|
|
429
|
+
\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
|
|
430
|
+
\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
|
|
431
|
+
Intelligence Management Platform
|
|
432
|
+
\x1B[0m
|
|
433
|
+
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
434
|
+
\x1B[0m`
|
|
435
|
+
};
|
|
436
|
+
|
|
397
437
|
// src/registry/classes.ts
|
|
438
|
+
import CryptoJS from "crypto-js";
|
|
398
439
|
function sanitizeToolName(name) {
|
|
399
440
|
if (typeof name !== "string") return "";
|
|
400
441
|
let sanitized = name.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
@@ -404,7 +445,7 @@ function sanitizeToolName(name) {
|
|
|
404
445
|
}
|
|
405
446
|
return sanitized;
|
|
406
447
|
}
|
|
407
|
-
var convertToolsArrayToObject = (tools) => {
|
|
448
|
+
var convertToolsArrayToObject = (tools, configs) => {
|
|
408
449
|
if (!tools) return {};
|
|
409
450
|
const sanitizedTools = tools ? tools.map((tool2) => ({
|
|
410
451
|
...tool2,
|
|
@@ -418,12 +459,57 @@ var convertToolsArrayToObject = (tools) => {
|
|
|
418
459
|
};
|
|
419
460
|
return {
|
|
420
461
|
...sanitizedTools?.reduce(
|
|
421
|
-
(prev, cur) => ({
|
|
462
|
+
(prev, cur) => ({
|
|
463
|
+
...prev,
|
|
464
|
+
[cur.name]: {
|
|
465
|
+
...cur.tool,
|
|
466
|
+
execute: async (inputs, options) => {
|
|
467
|
+
if (!cur.tool?.execute) {
|
|
468
|
+
console.error("[EXULU] Tool execute function is undefined.", cur.tool);
|
|
469
|
+
throw new Error("Tool execute function is undefined.");
|
|
470
|
+
}
|
|
471
|
+
let config = configs?.find((config2) => config2.toolId === cur.id);
|
|
472
|
+
if (config) {
|
|
473
|
+
config = await hydrateVariables(config || []);
|
|
474
|
+
}
|
|
475
|
+
return await cur.tool.execute({
|
|
476
|
+
...inputs,
|
|
477
|
+
// Convert config to object format if a config object
|
|
478
|
+
// is available, after we added the .value property
|
|
479
|
+
// by hydrating it from the variables table.
|
|
480
|
+
config: config ? config.config.reduce((acc, curr) => {
|
|
481
|
+
acc[curr.name] = curr.value;
|
|
482
|
+
return acc;
|
|
483
|
+
}, {}) : {}
|
|
484
|
+
}, options);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}),
|
|
422
488
|
{}
|
|
423
489
|
),
|
|
424
490
|
askForConfirmation
|
|
425
491
|
};
|
|
426
492
|
};
|
|
493
|
+
var hydrateVariables = async (tool2) => {
|
|
494
|
+
const { db: db3 } = await postgresClient();
|
|
495
|
+
const promises2 = tool2.config.map(async (toolConfig) => {
|
|
496
|
+
const variableName = toolConfig.variable;
|
|
497
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
498
|
+
if (!variable) {
|
|
499
|
+
console.error("[EXULU] Variable " + variableName + " not found.");
|
|
500
|
+
throw new Error("Variable " + variableName + " not found.");
|
|
501
|
+
}
|
|
502
|
+
let value = variable.value;
|
|
503
|
+
if (variable.encrypted) {
|
|
504
|
+
const bytes = CryptoJS.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
505
|
+
value = bytes.toString(CryptoJS.enc.Utf8);
|
|
506
|
+
}
|
|
507
|
+
toolConfig.value = value;
|
|
508
|
+
});
|
|
509
|
+
await Promise.all(promises2);
|
|
510
|
+
console.log("[EXULU] Variable values retrieved and added to tool config.");
|
|
511
|
+
return tool2;
|
|
512
|
+
};
|
|
427
513
|
function generateSlug(name) {
|
|
428
514
|
const normalized = name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
429
515
|
const lowercase = normalized.toLowerCase();
|
|
@@ -480,12 +566,13 @@ var ExuluAgent = class {
|
|
|
480
566
|
tool = () => {
|
|
481
567
|
return new ExuluTool({
|
|
482
568
|
id: this.id,
|
|
483
|
-
name: `${this.name}
|
|
569
|
+
name: `${this.name}`,
|
|
484
570
|
type: "agent",
|
|
485
571
|
inputSchema: z.object({
|
|
486
572
|
prompt: z.string()
|
|
487
573
|
}),
|
|
488
574
|
description: `A function that calls an AI agent named: ${this.name}. The agent does the following: ${this.description}.`,
|
|
575
|
+
config: [],
|
|
489
576
|
execute: async ({ prompt }) => {
|
|
490
577
|
return await this.generateSync({
|
|
491
578
|
prompt,
|
|
@@ -497,7 +584,7 @@ var ExuluAgent = class {
|
|
|
497
584
|
}
|
|
498
585
|
});
|
|
499
586
|
};
|
|
500
|
-
generateSync = async ({ messages, prompt, tools, statistics }) => {
|
|
587
|
+
generateSync = async ({ messages, prompt, tools, statistics, configs }) => {
|
|
501
588
|
if (!this.model) {
|
|
502
589
|
throw new Error("Model is required for streaming.");
|
|
503
590
|
}
|
|
@@ -513,7 +600,7 @@ var ExuluAgent = class {
|
|
|
513
600
|
messages,
|
|
514
601
|
prompt,
|
|
515
602
|
maxRetries: 2,
|
|
516
|
-
tools: convertToolsArrayToObject(tools),
|
|
603
|
+
tools: convertToolsArrayToObject(tools, configs),
|
|
517
604
|
maxSteps: 5
|
|
518
605
|
});
|
|
519
606
|
if (statistics) {
|
|
@@ -527,7 +614,7 @@ var ExuluAgent = class {
|
|
|
527
614
|
}
|
|
528
615
|
return text;
|
|
529
616
|
};
|
|
530
|
-
generateStream = ({ messages, prompt, tools, statistics }) => {
|
|
617
|
+
generateStream = ({ messages, prompt, tools, statistics, configs }) => {
|
|
531
618
|
if (!this.model) {
|
|
532
619
|
throw new Error("Model is required for streaming.");
|
|
533
620
|
}
|
|
@@ -543,7 +630,7 @@ var ExuluAgent = class {
|
|
|
543
630
|
prompt,
|
|
544
631
|
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.",
|
|
545
632
|
maxRetries: 2,
|
|
546
|
-
tools: convertToolsArrayToObject(tools),
|
|
633
|
+
tools: convertToolsArrayToObject(tools, configs),
|
|
547
634
|
maxSteps: 5,
|
|
548
635
|
onError: (error) => console.error("[EXULU] chat stream error.", error),
|
|
549
636
|
onFinish: async ({ response, usage }) => {
|
|
@@ -899,8 +986,10 @@ var ExuluTool = class {
|
|
|
899
986
|
inputSchema;
|
|
900
987
|
type;
|
|
901
988
|
tool;
|
|
902
|
-
|
|
989
|
+
config;
|
|
990
|
+
constructor({ id, name, description, inputSchema, type, execute: execute2, config }) {
|
|
903
991
|
this.id = id;
|
|
992
|
+
this.config = config;
|
|
904
993
|
this.name = name;
|
|
905
994
|
this.description = description;
|
|
906
995
|
this.inputSchema = inputSchema;
|
|
@@ -1308,11 +1397,11 @@ var ExuluContext = class {
|
|
|
1308
1397
|
table.text("source");
|
|
1309
1398
|
table.timestamp("embeddings_updated_at");
|
|
1310
1399
|
for (const field of this.fields) {
|
|
1311
|
-
const { type, name } = field;
|
|
1400
|
+
const { type, name, unique } = field;
|
|
1312
1401
|
if (!type || !name) {
|
|
1313
1402
|
continue;
|
|
1314
1403
|
}
|
|
1315
|
-
mapType(table, type, sanitizeName(name));
|
|
1404
|
+
mapType(table, type, sanitizeName(name), void 0, unique);
|
|
1316
1405
|
}
|
|
1317
1406
|
table.timestamps(true, true);
|
|
1318
1407
|
});
|
|
@@ -1334,11 +1423,12 @@ var ExuluContext = class {
|
|
|
1334
1423
|
tool = () => {
|
|
1335
1424
|
return new ExuluTool({
|
|
1336
1425
|
id: this.id,
|
|
1337
|
-
name: `${this.name}
|
|
1426
|
+
name: `${this.name}`,
|
|
1338
1427
|
type: "context",
|
|
1339
1428
|
inputSchema: z.object({
|
|
1340
1429
|
query: z.string()
|
|
1341
1430
|
}),
|
|
1431
|
+
config: [],
|
|
1342
1432
|
description: `Gets information from the context called: ${this.name}. The context description is: ${this.description}.`,
|
|
1343
1433
|
execute: async ({ query }) => {
|
|
1344
1434
|
return await this.getItems({
|
|
@@ -1806,7 +1896,7 @@ import "reflect-metadata";
|
|
|
1806
1896
|
import { makeExecutableSchema } from "@graphql-tools/schema";
|
|
1807
1897
|
import GraphQLJSON from "graphql-type-json";
|
|
1808
1898
|
import { GraphQLScalarType, Kind } from "graphql";
|
|
1809
|
-
import
|
|
1899
|
+
import CryptoJS2 from "crypto-js";
|
|
1810
1900
|
var GraphQLDate = new GraphQLScalarType({
|
|
1811
1901
|
name: "Date",
|
|
1812
1902
|
description: "Date custom scalar type",
|
|
@@ -1972,8 +2062,9 @@ function createMutations(table) {
|
|
|
1972
2062
|
return results[0];
|
|
1973
2063
|
},
|
|
1974
2064
|
[`${tableNamePlural}UpdateOne`]: async (_, args, context, info) => {
|
|
1975
|
-
const { db: db3 } = context;
|
|
2065
|
+
const { db: db3, req } = context;
|
|
1976
2066
|
let { where, input } = args;
|
|
2067
|
+
await validateSuperAdminPermission(tableNamePlural, input, req);
|
|
1977
2068
|
input = encryptSensitiveFields(input);
|
|
1978
2069
|
await db3(tableNamePlural).where(where).update({
|
|
1979
2070
|
...input,
|
|
@@ -1984,9 +2075,10 @@ function createMutations(table) {
|
|
|
1984
2075
|
return result;
|
|
1985
2076
|
},
|
|
1986
2077
|
[`${tableNamePlural}UpdateOneById`]: async (_, args, context, info) => {
|
|
2078
|
+
const { db: db3, req } = context;
|
|
1987
2079
|
let { id, input } = args;
|
|
2080
|
+
await validateSuperAdminPermission(tableNamePlural, input, req);
|
|
1988
2081
|
input = encryptSensitiveFields(input);
|
|
1989
|
-
const { db: db3 } = context;
|
|
1990
2082
|
await db3(tableNamePlural).where({ id }).update({
|
|
1991
2083
|
...input,
|
|
1992
2084
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -2123,6 +2215,7 @@ function createQueries(table) {
|
|
|
2123
2215
|
};
|
|
2124
2216
|
}
|
|
2125
2217
|
function createSDL(tables) {
|
|
2218
|
+
console.log("[EXULU] Creating SDL");
|
|
2126
2219
|
let typeDefs = `
|
|
2127
2220
|
scalar JSON
|
|
2128
2221
|
scalar Date
|
|
@@ -2138,6 +2231,7 @@ function createSDL(tables) {
|
|
|
2138
2231
|
const tableNamePlural = table.name.plural.toLowerCase();
|
|
2139
2232
|
const tableNameSingular = table.name.singular.toLowerCase();
|
|
2140
2233
|
const tableNameSingularUpperCaseFirst = table.name.singular.charAt(0).toUpperCase() + table.name.singular.slice(1);
|
|
2234
|
+
console.log("[EXULU] Adding table >>>>>", tableNamePlural);
|
|
2141
2235
|
typeDefs += `
|
|
2142
2236
|
${tableNameSingular}ById(id: ID!): ${tableNameSingular}
|
|
2143
2237
|
${tableNamePlural}Pagination(limit: Int, page: Int, filters: [Filter${tableNameSingularUpperCaseFirst}], sort: SortBy): ${tableNameSingularUpperCaseFirst}PaginationResult
|
|
@@ -2212,15 +2306,23 @@ type JobStatistics {
|
|
|
2212
2306
|
console.log("\n");
|
|
2213
2307
|
return schema;
|
|
2214
2308
|
}
|
|
2215
|
-
var sensitiveFields = ["anthropic_token"];
|
|
2216
2309
|
var encryptSensitiveFields = (input) => {
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
}
|
|
2221
|
-
});
|
|
2310
|
+
if (input.value && input.encrypted === true) {
|
|
2311
|
+
input.value = CryptoJS2.AES.encrypt(input.value, process.env.NEXTAUTH_SECRET).toString();
|
|
2312
|
+
}
|
|
2222
2313
|
return input;
|
|
2223
2314
|
};
|
|
2315
|
+
var validateSuperAdminPermission = async (tableNamePlural, input, req) => {
|
|
2316
|
+
if (tableNamePlural === "users" && input.super_admin !== void 0) {
|
|
2317
|
+
const authResult = await requestValidators.authenticate(req);
|
|
2318
|
+
if (authResult.error || !authResult.user) {
|
|
2319
|
+
throw new Error("Authentication failed");
|
|
2320
|
+
}
|
|
2321
|
+
if (!authResult.user.super_admin) {
|
|
2322
|
+
throw new Error("Only super administrators can modify super_admin status");
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
};
|
|
2224
2326
|
|
|
2225
2327
|
// src/registry/routes.ts
|
|
2226
2328
|
import { expressMiddleware } from "@as-integrations/express5";
|
|
@@ -2558,6 +2660,29 @@ var agentsSchema = {
|
|
|
2558
2660
|
}
|
|
2559
2661
|
]
|
|
2560
2662
|
};
|
|
2663
|
+
var variablesSchema = {
|
|
2664
|
+
name: {
|
|
2665
|
+
plural: "variables",
|
|
2666
|
+
singular: "variable"
|
|
2667
|
+
},
|
|
2668
|
+
fields: [
|
|
2669
|
+
{
|
|
2670
|
+
name: "name",
|
|
2671
|
+
type: "text",
|
|
2672
|
+
index: true,
|
|
2673
|
+
unique: true
|
|
2674
|
+
},
|
|
2675
|
+
{
|
|
2676
|
+
name: "value",
|
|
2677
|
+
type: "longText"
|
|
2678
|
+
},
|
|
2679
|
+
{
|
|
2680
|
+
name: "encrypted",
|
|
2681
|
+
type: "boolean",
|
|
2682
|
+
default: false
|
|
2683
|
+
}
|
|
2684
|
+
]
|
|
2685
|
+
};
|
|
2561
2686
|
|
|
2562
2687
|
// src/registry/uppy.ts
|
|
2563
2688
|
import "express";
|
|
@@ -2953,34 +3078,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2953
3078
|
// src/registry/routes.ts
|
|
2954
3079
|
import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
|
|
2955
3080
|
import bodyParser from "body-parser";
|
|
2956
|
-
import
|
|
2957
|
-
|
|
2958
|
-
// src/registry/utils/claude-messages.ts
|
|
2959
|
-
var CLAUDE_MESSAGES = {
|
|
2960
|
-
authentication_error: `
|
|
2961
|
-
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
2962
|
-
\x1B[0m`,
|
|
2963
|
-
missing_body: `
|
|
2964
|
-
\x1B[41m -- Missing body Anthropic response. --
|
|
2965
|
-
\x1B[0m`,
|
|
2966
|
-
missing_nextauth_secret: `
|
|
2967
|
-
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
2968
|
-
\x1B[0m`,
|
|
2969
|
-
not_enabled: `
|
|
2970
|
-
\x1B[31m
|
|
2971
|
-
\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
|
|
2972
|
-
\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
|
|
2973
|
-
\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
|
|
2974
|
-
\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
|
|
2975
|
-
\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
|
|
2976
|
-
\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
|
|
2977
|
-
Intelligence Management Platform
|
|
2978
|
-
\x1B[0m
|
|
2979
|
-
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
2980
|
-
\x1B[0m`
|
|
2981
|
-
};
|
|
2982
|
-
|
|
2983
|
-
// src/registry/routes.ts
|
|
3081
|
+
import CryptoJS3 from "crypto-js";
|
|
2984
3082
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
2985
3083
|
var global_queues = {
|
|
2986
3084
|
logs_cleaner: "logs-cleaner"
|
|
@@ -3087,7 +3185,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3087
3185
|
} else {
|
|
3088
3186
|
console.log("===========================", "[EXULU] no redis server configured, not setting up recurring jobs.", "===========================");
|
|
3089
3187
|
}
|
|
3090
|
-
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema, workflowSchema, evalResultsSchema, agentSessionsSchema, agentMessagesSchema]);
|
|
3188
|
+
const schema = createSDL([usersSchema, rolesSchema, agentsSchema, jobsSchema, workflowSchema, evalResultsSchema, agentSessionsSchema, agentMessagesSchema, variablesSchema]);
|
|
3091
3189
|
console.log("[EXULU] graphql server");
|
|
3092
3190
|
const server = new ApolloServer({
|
|
3093
3191
|
cache: new InMemoryLRUCache(),
|
|
@@ -3922,6 +4020,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3922
4020
|
const result = agent.generateStream({
|
|
3923
4021
|
messages: req.body.messages,
|
|
3924
4022
|
tools: enabledTools,
|
|
4023
|
+
configs: agentInstance.tools,
|
|
3925
4024
|
statistics: {
|
|
3926
4025
|
label: agent.name,
|
|
3927
4026
|
trigger: "agent"
|
|
@@ -3932,7 +4031,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3932
4031
|
} else {
|
|
3933
4032
|
const response = await agent.generateSync({
|
|
3934
4033
|
messages: req.body.messages,
|
|
3935
|
-
tools: enabledTools.map(),
|
|
4034
|
+
tools: enabledTools.map((tool2) => tool2.tool),
|
|
4035
|
+
configs: agentInstance.tools,
|
|
3936
4036
|
statistics: {
|
|
3937
4037
|
label: agent.name,
|
|
3938
4038
|
trigger: "agent"
|
|
@@ -4049,8 +4149,25 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4049
4149
|
res.end(Buffer.from(arrayBuffer));
|
|
4050
4150
|
return;
|
|
4051
4151
|
}
|
|
4052
|
-
const
|
|
4053
|
-
const
|
|
4152
|
+
const variableName = authenticationResult.user.anthropic_token;
|
|
4153
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
4154
|
+
if (!variable) {
|
|
4155
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.anthropic_token_variable_not_found);
|
|
4156
|
+
res.setHeader("Content-Type", "application/json");
|
|
4157
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4158
|
+
return;
|
|
4159
|
+
}
|
|
4160
|
+
let anthropicApiKey = variable.value;
|
|
4161
|
+
if (!variable.encrypted) {
|
|
4162
|
+
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.anthropic_token_variable_not_encrypted);
|
|
4163
|
+
res.setHeader("Content-Type", "application/json");
|
|
4164
|
+
res.end(Buffer.from(arrayBuffer));
|
|
4165
|
+
return;
|
|
4166
|
+
}
|
|
4167
|
+
if (variable.encrypted) {
|
|
4168
|
+
const bytes = CryptoJS3.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
4169
|
+
anthropicApiKey = bytes.toString(CryptoJS3.enc.Utf8);
|
|
4170
|
+
}
|
|
4054
4171
|
const headers = {
|
|
4055
4172
|
"x-api-key": anthropicApiKey,
|
|
4056
4173
|
"anthropic-version": "2023-06-01",
|
|
@@ -4979,8 +5096,8 @@ var RecursiveChunk = class _RecursiveChunk extends Chunk {
|
|
|
4979
5096
|
// src/chunking/tokenizer.ts
|
|
4980
5097
|
import { Tiktoken } from "tiktoken/lite";
|
|
4981
5098
|
import { load } from "tiktoken/load";
|
|
4982
|
-
import registry from "tiktoken/registry.json"
|
|
4983
|
-
import models from "tiktoken/model_to_encoding.json"
|
|
5099
|
+
import registry from "tiktoken/registry.json";
|
|
5100
|
+
import models from "tiktoken/model_to_encoding.json";
|
|
4984
5101
|
var ExuluTokenizer = class {
|
|
4985
5102
|
constructor() {
|
|
4986
5103
|
}
|
|
@@ -5925,6 +6042,7 @@ var generateApiKey = async (name, email) => {
|
|
|
5925
6042
|
|
|
5926
6043
|
// src/postgres/init-db.ts
|
|
5927
6044
|
var up = async function(knex) {
|
|
6045
|
+
console.log("[EXULU] Database up.");
|
|
5928
6046
|
if (!await knex.schema.hasTable("agent_sessions")) {
|
|
5929
6047
|
console.log("[EXULU] Creating agent_sessions table.");
|
|
5930
6048
|
await knex.schema.createTable("agent_sessions", (table) => {
|
|
@@ -5932,11 +6050,11 @@ var up = async function(knex) {
|
|
|
5932
6050
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
5933
6051
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
5934
6052
|
for (const field of agentSessionsSchema.fields) {
|
|
5935
|
-
const { type, name, default: defaultValue } = field;
|
|
6053
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
5936
6054
|
if (!type || !name) {
|
|
5937
6055
|
continue;
|
|
5938
6056
|
}
|
|
5939
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6057
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
5940
6058
|
}
|
|
5941
6059
|
});
|
|
5942
6060
|
}
|
|
@@ -5947,11 +6065,11 @@ var up = async function(knex) {
|
|
|
5947
6065
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
5948
6066
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
5949
6067
|
for (const field of agentMessagesSchema.fields) {
|
|
5950
|
-
const { type, name, default: defaultValue } = field;
|
|
6068
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
5951
6069
|
if (!type || !name) {
|
|
5952
6070
|
continue;
|
|
5953
6071
|
}
|
|
5954
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6072
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
5955
6073
|
}
|
|
5956
6074
|
});
|
|
5957
6075
|
}
|
|
@@ -5962,11 +6080,11 @@ var up = async function(knex) {
|
|
|
5962
6080
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
5963
6081
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
5964
6082
|
for (const field of rolesSchema.fields) {
|
|
5965
|
-
const { type, name, default: defaultValue } = field;
|
|
6083
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
5966
6084
|
if (!type || !name) {
|
|
5967
6085
|
continue;
|
|
5968
6086
|
}
|
|
5969
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6087
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
5970
6088
|
}
|
|
5971
6089
|
});
|
|
5972
6090
|
}
|
|
@@ -5977,11 +6095,11 @@ var up = async function(knex) {
|
|
|
5977
6095
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
5978
6096
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
5979
6097
|
for (const field of evalResultsSchema.fields) {
|
|
5980
|
-
const { type, name, default: defaultValue } = field;
|
|
6098
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
5981
6099
|
if (!type || !name) {
|
|
5982
6100
|
continue;
|
|
5983
6101
|
}
|
|
5984
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6102
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
5985
6103
|
}
|
|
5986
6104
|
});
|
|
5987
6105
|
}
|
|
@@ -5992,11 +6110,11 @@ var up = async function(knex) {
|
|
|
5992
6110
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
5993
6111
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
5994
6112
|
for (const field of statisticsSchema.fields) {
|
|
5995
|
-
const { type, name, default: defaultValue } = field;
|
|
6113
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
5996
6114
|
if (!type || !name) {
|
|
5997
6115
|
continue;
|
|
5998
6116
|
}
|
|
5999
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6117
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
6000
6118
|
}
|
|
6001
6119
|
});
|
|
6002
6120
|
}
|
|
@@ -6007,11 +6125,11 @@ var up = async function(knex) {
|
|
|
6007
6125
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6008
6126
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6009
6127
|
for (const field of jobsSchema.fields) {
|
|
6010
|
-
const { type, name, default: defaultValue } = field;
|
|
6128
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
6011
6129
|
if (!type || !name) {
|
|
6012
6130
|
continue;
|
|
6013
6131
|
}
|
|
6014
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6132
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
6015
6133
|
}
|
|
6016
6134
|
});
|
|
6017
6135
|
}
|
|
@@ -6022,11 +6140,26 @@ var up = async function(knex) {
|
|
|
6022
6140
|
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6023
6141
|
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6024
6142
|
for (const field of agentsSchema.fields) {
|
|
6025
|
-
const { type, name, default: defaultValue } = field;
|
|
6143
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
6144
|
+
if (!type || !name) {
|
|
6145
|
+
continue;
|
|
6146
|
+
}
|
|
6147
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
6148
|
+
}
|
|
6149
|
+
});
|
|
6150
|
+
}
|
|
6151
|
+
if (!await knex.schema.hasTable("variables")) {
|
|
6152
|
+
console.log("[EXULU] Creating variables table.");
|
|
6153
|
+
await knex.schema.createTable("variables", (table) => {
|
|
6154
|
+
table.uuid("id").primary().defaultTo(knex.fn.uuid());
|
|
6155
|
+
table.timestamp("createdAt").defaultTo(knex.fn.now());
|
|
6156
|
+
table.timestamp("updatedAt").defaultTo(knex.fn.now());
|
|
6157
|
+
for (const field of variablesSchema.fields) {
|
|
6158
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
6026
6159
|
if (!type || !name) {
|
|
6027
6160
|
continue;
|
|
6028
6161
|
}
|
|
6029
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6162
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
6030
6163
|
}
|
|
6031
6164
|
});
|
|
6032
6165
|
}
|
|
@@ -6052,14 +6185,14 @@ var up = async function(knex) {
|
|
|
6052
6185
|
table.text("image");
|
|
6053
6186
|
for (const field of usersSchema.fields) {
|
|
6054
6187
|
console.log("[EXULU] field", field);
|
|
6055
|
-
const { type, name, default: defaultValue } = field;
|
|
6188
|
+
const { type, name, default: defaultValue, unique } = field;
|
|
6056
6189
|
if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
|
|
6057
6190
|
continue;
|
|
6058
6191
|
}
|
|
6059
6192
|
if (!type || !name) {
|
|
6060
6193
|
continue;
|
|
6061
6194
|
}
|
|
6062
|
-
mapType(table, type, sanitizeName(name), defaultValue);
|
|
6195
|
+
mapType(table, type, sanitizeName(name), defaultValue, unique);
|
|
6063
6196
|
}
|
|
6064
6197
|
});
|
|
6065
6198
|
}
|
package/lms.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
The Exulu LMS is a Tutor Open Edx instance hosted on a hetzner cloud. Important, we used this guide https://community.hetzner.com/tutorials/open-edx-lms-docker. Pleas note the command "config save --set ENABLE_WEB_PROXY=false --set CADDY_HTTP_PORT=84" used in the guide is false, it should be "tutor config save --set ENABLE_WEB_PROXY=true --set ENABLE_HTTPS=true --set CADDY_HTTP_PORT=80 --set CADDY_HTTPS_PORT=443".
|
|
2
|
+
|
|
3
|
+
Also follow this guide to setup the first user, and upgrade the database to support icons / emojis: https://docs.tutor.edly.io/local.html#createuser
|