@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/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
- constructor({ id, name, description, inputSchema, type, execute }: {
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) => ({ ...prev, [cur.name]: cur.tool }),
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} agent`,
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
- constructor({ id, name, description, inputSchema, type, execute: execute2 }) {
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} context`,
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 CryptoJS from "crypto-js";
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
- sensitiveFields.forEach((field) => {
2218
- if (input[field]) {
2219
- input[field] = CryptoJS.AES.encrypt(input[field], process.env.NEXTAUTH_SECRET).toString();
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 CryptoJS2 from "crypto-js";
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 bytes = CryptoJS2.AES.decrypt(authenticationResult.user?.anthropic_token, process.env.NEXTAUTH_SECRET);
4053
- const anthropicApiKey = bytes.toString(CryptoJS2.enc.Utf8);
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" assert { type: "json" };
4983
- import models from "tiktoken/model_to_encoding.json" assert { type: "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