@exulu/backend 1.34.0 → 1.35.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # [1.34.0](https://github.com/Qventu/exulu-backend/compare/v1.33.0...v1.34.0) (2025-11-17)
1
+ # [1.35.0](https://github.com/Qventu/exulu-backend/compare/v1.34.1...v1.35.0) (2025-11-18)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * add MCP prompt library integration and JSON filtering enhancements ([bb29681](https://github.com/Qventu/exulu-backend/commit/bb296812f559e197b17fb0255e47dda72c64ed3c))
6
+ * add Google Vertex AI agent support and enhance embedder configuration system ([9668c10](https://github.com/Qventu/exulu-backend/commit/9668c1093e9bc00f64a4a0b2e1137625ca0b2396))
package/dist/index.cjs CHANGED
@@ -1379,6 +1379,35 @@ var platformConfigurationsSchema = {
1379
1379
  }
1380
1380
  ]
1381
1381
  };
1382
+ var embedderSettingsSchema = {
1383
+ type: "embedder_settings",
1384
+ name: {
1385
+ plural: "embedder_settings",
1386
+ singular: "embedder_setting"
1387
+ },
1388
+ RBAC: false,
1389
+ fields: [
1390
+ {
1391
+ name: "context",
1392
+ type: "text"
1393
+ // id of the ExuluContext class
1394
+ },
1395
+ {
1396
+ name: "embedder",
1397
+ type: "text"
1398
+ // id of the ExuluEmbedder class
1399
+ },
1400
+ {
1401
+ name: "name",
1402
+ type: "text"
1403
+ },
1404
+ {
1405
+ name: "value",
1406
+ type: "text"
1407
+ // reference to an exulu variable
1408
+ }
1409
+ ]
1410
+ };
1382
1411
  var promptLibrarySchema = {
1383
1412
  type: "prompt_library",
1384
1413
  name: {
@@ -1487,6 +1516,7 @@ var coreSchemas = {
1487
1516
  platformConfigurationsSchema: () => addCoreFields(platformConfigurationsSchema),
1488
1517
  jobResultsSchema: () => addCoreFields(jobResultsSchema),
1489
1518
  promptLibrarySchema: () => addCoreFields(promptLibrarySchema),
1519
+ embedderSettingsSchema: () => addCoreFields(embedderSettingsSchema),
1490
1520
  promptFavoritesSchema: () => addCoreFields(promptFavoritesSchema)
1491
1521
  };
1492
1522
  }
@@ -1866,6 +1896,7 @@ ${enumValues}
1866
1896
  fields.push(" capabilities: AgentCapabilities");
1867
1897
  fields.push(" maxContextLength: Int");
1868
1898
  fields.push(" provider: String");
1899
+ fields.push(" authenticationInformation: String");
1869
1900
  fields.push(" slug: String");
1870
1901
  }
1871
1902
  const rbacField = table.RBAC ? " RBAC: RBACData" : "";
@@ -2664,7 +2695,8 @@ var backendAgentFields = [
2664
2695
  "streaming",
2665
2696
  "capabilities",
2666
2697
  "maxContextLength",
2667
- "provider"
2698
+ "provider",
2699
+ "authenticationInformation"
2668
2700
  ];
2669
2701
  var removeAgentFields = (requestedFields) => {
2670
2702
  const filtered = requestedFields.filter((field) => !backendAgentFields.includes(field));
@@ -2732,6 +2764,9 @@ var addAgentFields = async (requestedFields, agents, result, tools, user) => {
2732
2764
  if (requestedFields.includes("maxContextLength")) {
2733
2765
  result.maxContextLength = backend?.maxContextLength || 0;
2734
2766
  }
2767
+ if (requestedFields.includes("authenticationInformation")) {
2768
+ result.authenticationInformation = backend?.authenticationInformation || "";
2769
+ }
2735
2770
  if (requestedFields.includes("provider")) {
2736
2771
  result.provider = backend?.provider || "";
2737
2772
  }
@@ -3130,7 +3165,7 @@ var vectorSearch = async ({
3130
3165
  itemsQuery.select(chunksTable + ".createdAt as chunk_created_at");
3131
3166
  itemsQuery.select(chunksTable + ".updatedAt as chunk_updated_at");
3132
3167
  itemsQuery.select(db3.raw("vector_dims(??) as embedding_size", [`${chunksTable}.embedding`]));
3133
- const { chunks } = await embedder.generateFromQuery(query, {
3168
+ const { chunks } = await embedder.generateFromQuery(context.id, query, {
3134
3169
  label: table.name.singular,
3135
3170
  trigger
3136
3171
  }, user.id, role);
@@ -3931,7 +3966,11 @@ type PageInfo {
3931
3966
  id: context2.id,
3932
3967
  name: context2.name,
3933
3968
  description: context2.description,
3934
- embedder: context2.embedder?.name || void 0,
3969
+ embedder: context2.embedder ? {
3970
+ name: context2.embedder.name,
3971
+ id: context2.embedder.id,
3972
+ config: context2.embedder?.config || void 0
3973
+ } : void 0,
3935
3974
  slug: "/contexts/" + context2.id,
3936
3975
  active: context2.active,
3937
3976
  sources,
@@ -3982,7 +4021,11 @@ type PageInfo {
3982
4021
  id: data.id,
3983
4022
  name: data.name,
3984
4023
  description: data.description,
3985
- embedder: data.embedder?.name || void 0,
4024
+ embedder: data.embedder ? {
4025
+ name: data.embedder.name,
4026
+ id: data.embedder.id,
4027
+ config: data.embedder?.config || void 0
4028
+ } : void 0,
3986
4029
  slug: "/contexts/" + data.id,
3987
4030
  active: data.active,
3988
4031
  sources,
@@ -4197,13 +4240,23 @@ type Context {
4197
4240
  id: ID!
4198
4241
  name: String!
4199
4242
  description: String
4200
- embedder: String
4243
+ embedder: Embedder
4201
4244
  slug: String
4202
4245
  active: Boolean
4203
4246
  fields: JSON
4204
4247
  configuration: JSON
4205
4248
  sources: [ContextSource!]
4206
4249
  }
4250
+ type Embedder {
4251
+ name: String!
4252
+ id: ID!
4253
+ config: [EmbedderConfig!]
4254
+ }
4255
+ type EmbedderConfig {
4256
+ name: String!
4257
+ description: String
4258
+ default: String
4259
+ }
4207
4260
 
4208
4261
  type ContextSource {
4209
4262
  id: String!
@@ -4892,6 +4945,9 @@ function sanitizeToolName(name) {
4892
4945
  var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providerapikey, contexts, user, exuluConfig, sessionID) => {
4893
4946
  if (!currentTools) return {};
4894
4947
  if (!allExuluTools) return {};
4948
+ if (!contexts) {
4949
+ contexts = [];
4950
+ }
4895
4951
  const sanitizedTools = currentTools ? currentTools.map((tool2) => ({
4896
4952
  ...tool2,
4897
4953
  name: sanitizeToolName(tool2.name)
@@ -5090,6 +5146,7 @@ var ExuluAgent2 = class {
5090
5146
  slug = "";
5091
5147
  type;
5092
5148
  streaming = false;
5149
+ authenticationInformation;
5093
5150
  maxContextLength;
5094
5151
  queue;
5095
5152
  rateLimit;
@@ -5097,12 +5154,13 @@ var ExuluAgent2 = class {
5097
5154
  // private memory: Memory | undefined; // TODO do own implementation
5098
5155
  model;
5099
5156
  capabilities;
5100
- constructor({ id, name, description, config, rateLimit, capabilities, type, maxContextLength, provider, queue }) {
5157
+ constructor({ id, name, description, config, rateLimit, capabilities, type, maxContextLength, provider, queue, authenticationInformation }) {
5101
5158
  this.id = id;
5102
5159
  this.name = name;
5103
5160
  this.description = description;
5104
5161
  this.rateLimit = rateLimit;
5105
5162
  this.provider = provider;
5163
+ this.authenticationInformation = authenticationInformation;
5106
5164
  this.config = config;
5107
5165
  this.type = type;
5108
5166
  this.maxContextLength = maxContextLength;
@@ -5121,15 +5179,13 @@ var ExuluAgent2 = class {
5121
5179
  if (!this.config?.model?.create) {
5122
5180
  return "";
5123
5181
  }
5124
- const model = this.config?.model?.create({ apiKey: "" });
5125
- return typeof model === "string" ? model : model?.provider || "";
5182
+ return this.provider;
5126
5183
  }
5127
5184
  get modelName() {
5128
5185
  if (!this.config?.model?.create) {
5129
5186
  return "";
5130
5187
  }
5131
- const model = this.config?.model?.create({ apiKey: "" });
5132
- return typeof model === "string" ? model : model?.modelId || "";
5188
+ return this.config?.name || "";
5133
5189
  }
5134
5190
  // Exports the agent as a tool that can be used by another agent
5135
5191
  tool = async (instance, agents) => {
@@ -5155,21 +5211,21 @@ var ExuluAgent2 = class {
5155
5211
  }
5156
5212
  let enabledTools = await getEnabledTools(agentInstance, allExuluTools, [], agents, user);
5157
5213
  const variableName = agentInstance.providerapikey;
5158
- if (!variableName) {
5159
- throw new Error("Provider API key variable not set for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool.");
5160
- }
5161
- const { db: db3 } = await postgresClient();
5162
- const variable = await db3.from("variables").where({ name: variableName }).first();
5163
- if (!variable) {
5164
- throw new Error("Provider API key variable not found for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool.");
5165
- }
5166
- let providerapikey = variable.value;
5167
- if (!variable.encrypted) {
5168
- throw new Error("Provider API key variable not encrypted for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool, for security reasons you are only allowed to use encrypted variables for provider API keys.");
5169
- }
5170
- if (variable.encrypted) {
5171
- const bytes = import_crypto_js2.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
5172
- providerapikey = bytes.toString(import_crypto_js2.default.enc.Utf8);
5214
+ let providerapikey;
5215
+ if (variableName) {
5216
+ const { db: db3 } = await postgresClient();
5217
+ const variable = await db3.from("variables").where({ name: variableName }).first();
5218
+ if (!variable) {
5219
+ throw new Error("Provider API key variable not found for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool.");
5220
+ }
5221
+ providerapikey = variable.value;
5222
+ if (!variable.encrypted) {
5223
+ throw new Error("Provider API key variable not encrypted for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool, for security reasons you are only allowed to use encrypted variables for provider API keys.");
5224
+ }
5225
+ if (variable.encrypted) {
5226
+ const bytes = import_crypto_js2.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
5227
+ providerapikey = bytes.toString(import_crypto_js2.default.enc.Utf8);
5228
+ }
5173
5229
  }
5174
5230
  console.log("[EXULU] Enabled tools for agent '" + agentInstance.name + " (" + agentInstance.id + ") that is being called as a tool", enabledTools.map((x) => x.name + " (" + x.id + ")"));
5175
5231
  console.log("[EXULU] Prompt for agent '" + agentInstance.name + "' that is being called as a tool", prompt.slice(0, 100) + "...");
@@ -5233,7 +5289,7 @@ var ExuluAgent2 = class {
5233
5289
  throw new Error("Prompt is required for generating with an output schema.");
5234
5290
  }
5235
5291
  const model = this.model.create({
5236
- apiKey: providerapikey
5292
+ ...providerapikey ? { apiKey: providerapikey } : {}
5237
5293
  });
5238
5294
  console.log("[EXULU] Model for agent: " + this.name, " created for generating sync.");
5239
5295
  let messages = inputMessages || [];
@@ -5410,7 +5466,7 @@ var ExuluAgent2 = class {
5410
5466
  throw new Error("Message is required for streaming.");
5411
5467
  }
5412
5468
  const model = this.model.create({
5413
- apiKey: providerapikey
5469
+ ...providerapikey ? { apiKey: providerapikey } : {}
5414
5470
  });
5415
5471
  let messages = [];
5416
5472
  let previousMessagesContent = previousMessages || [];
@@ -5511,11 +5567,13 @@ var ExuluEmbedder = class {
5511
5567
  generateEmbeddings;
5512
5568
  description;
5513
5569
  vectorDimensions;
5570
+ config;
5514
5571
  maxChunkSize;
5515
5572
  _chunker;
5516
- constructor({ id, name, description, generateEmbeddings, queue, vectorDimensions, maxChunkSize, chunker }) {
5573
+ constructor({ id, name, description, generateEmbeddings, queue, vectorDimensions, maxChunkSize, chunker, config }) {
5517
5574
  this.id = id;
5518
5575
  this.name = name;
5576
+ this.config = config;
5519
5577
  this.description = description;
5520
5578
  this.vectorDimensions = vectorDimensions;
5521
5579
  this.maxChunkSize = maxChunkSize;
@@ -5524,13 +5582,51 @@ var ExuluEmbedder = class {
5524
5582
  this.queue = queue;
5525
5583
  this.generateEmbeddings = generateEmbeddings;
5526
5584
  }
5527
- chunker = (item, maxChunkSize, config) => {
5585
+ chunker = async (context, item, maxChunkSize, config) => {
5528
5586
  const utils = {
5529
5587
  storage: new ExuluStorage({ config })
5530
5588
  };
5531
- return this._chunker(item, maxChunkSize, utils);
5589
+ const settings = await this.hydrateEmbedderConfig(context);
5590
+ return this._chunker(item, maxChunkSize, utils, settings);
5532
5591
  };
5533
- async generateFromQuery(query, statistics, user, role) {
5592
+ hydrateEmbedderConfig = async (context) => {
5593
+ const hydrated = [];
5594
+ const { db: db3 } = await postgresClient();
5595
+ const variables = await db3.from("embedder_settings").where({
5596
+ context,
5597
+ embedder: this.id
5598
+ });
5599
+ for (const config of this.config || []) {
5600
+ const name = config.name;
5601
+ const {
5602
+ value: variableName,
5603
+ id
5604
+ } = variables.find((v) => v.name === name);
5605
+ let value = "";
5606
+ console.log("[EXULU] variable name", variableName);
5607
+ const variable = await db3.from("variables").where({ name: variableName }).first();
5608
+ if (!variable) {
5609
+ throw new Error("Variable not found for embedder setting: " + name + " in context: " + context + " and embedder: " + this.id);
5610
+ }
5611
+ if (variable.encrypted) {
5612
+ const bytes = import_crypto_js2.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
5613
+ value = bytes.toString(import_crypto_js2.default.enc.Utf8);
5614
+ } else {
5615
+ value = variable.value;
5616
+ }
5617
+ console.log("[EXULU] variable value", value);
5618
+ hydrated.push({
5619
+ id: id || "",
5620
+ name,
5621
+ value: value || ""
5622
+ });
5623
+ }
5624
+ return hydrated.reduce((acc, curr) => {
5625
+ acc[curr.name] = curr.value;
5626
+ return acc;
5627
+ }, {});
5628
+ };
5629
+ async generateFromQuery(context, query, statistics, user, role) {
5534
5630
  if (statistics) {
5535
5631
  await updateStatistic({
5536
5632
  name: "count",
@@ -5542,6 +5638,7 @@ var ExuluEmbedder = class {
5542
5638
  role
5543
5639
  });
5544
5640
  }
5641
+ const settings = await this.hydrateEmbedderConfig(context);
5545
5642
  return await this.generateEmbeddings({
5546
5643
  item: {
5547
5644
  id: "placeholder"
@@ -5550,9 +5647,9 @@ var ExuluEmbedder = class {
5550
5647
  content: query,
5551
5648
  index: 1
5552
5649
  }]
5553
- });
5650
+ }, settings);
5554
5651
  }
5555
- async generateFromDocument(input, config, statistics, user, role) {
5652
+ async generateFromDocument(context, input, config, statistics, user, role) {
5556
5653
  if (statistics) {
5557
5654
  await updateStatistic({
5558
5655
  name: "count",
@@ -5570,9 +5667,18 @@ var ExuluEmbedder = class {
5570
5667
  if (!input.id) {
5571
5668
  throw new Error("Item id is required for generating embeddings.");
5572
5669
  }
5573
- const output = await this.chunker(input, this.maxChunkSize, config);
5670
+ const settings = await this.hydrateEmbedderConfig(context);
5671
+ const output = await this.chunker(
5672
+ context,
5673
+ input,
5674
+ this.maxChunkSize,
5675
+ config
5676
+ );
5574
5677
  console.log("[EXULU] Generating embeddings.");
5575
- return await this.generateEmbeddings(output);
5678
+ return await this.generateEmbeddings(
5679
+ output,
5680
+ settings
5681
+ );
5576
5682
  }
5577
5683
  };
5578
5684
  var ExuluTool2 = class {
@@ -5747,6 +5853,7 @@ var ExuluContext = class {
5747
5853
  }
5748
5854
  const { db: db3 } = await postgresClient();
5749
5855
  const { id: source, chunks } = await this.embedder.generateFromDocument(
5856
+ this.id,
5750
5857
  {
5751
5858
  ...item,
5752
5859
  id: item.id
@@ -6065,6 +6172,7 @@ var ExuluContext = class {
6065
6172
  };
6066
6173
  };
6067
6174
  var updateStatistic = async (statistic) => {
6175
+ console.log("[EXULU] updating statistic", statistic);
6068
6176
  const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
6069
6177
  const { db: db3 } = await postgresClient();
6070
6178
  const existing = await db3.from("tracking").where({
@@ -6209,6 +6317,7 @@ var {
6209
6317
  workflowTemplatesSchema: workflowTemplatesSchema2,
6210
6318
  rbacSchema: rbacSchema2,
6211
6319
  promptLibrarySchema: promptLibrarySchema2,
6320
+ embedderSettingsSchema: embedderSettingsSchema2,
6212
6321
  promptFavoritesSchema: promptFavoritesSchema2,
6213
6322
  statisticsSchema: statisticsSchema2
6214
6323
  } = coreSchemas.get();
@@ -6241,6 +6350,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
6241
6350
  projectsSchema2(),
6242
6351
  jobResultsSchema2(),
6243
6352
  promptLibrarySchema2(),
6353
+ embedderSettingsSchema2(),
6244
6354
  promptFavoritesSchema2(),
6245
6355
  evalRunsSchema2(),
6246
6356
  platformConfigurationsSchema2(),
@@ -6298,7 +6408,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
6298
6408
  const variable = await db3.from("variables").where({ name: "OPENAI_IMAGE_GENERATION_API_KEY" }).first();
6299
6409
  if (!variable) {
6300
6410
  res.status(400).json({
6301
- message: "Provider API key variable not found."
6411
+ message: "Provider API key variable not found for OpenAI image generation."
6302
6412
  });
6303
6413
  return;
6304
6414
  }
@@ -6478,24 +6588,30 @@ Mood: friendly and intelligent.
6478
6588
  console.log("[EXULU] agent tools", agentInstance.tools?.map((x) => x.name + " (" + x.id + ")"));
6479
6589
  const disabledTools = req.body.disabledTools ? req.body.disabledTools : [];
6480
6590
  let enabledTools = await getEnabledTools(agentInstance, tools, disabledTools, agents, user);
6591
+ let providerapikey;
6481
6592
  const variableName = agentInstance.providerapikey;
6482
- const variable = await db3.from("variables").where({ name: variableName }).first();
6483
- if (!variable) {
6484
- res.status(400).json({
6485
- message: "Provider API key variable not found."
6486
- });
6487
- return;
6488
- }
6489
- let providerapikey = variable.value;
6490
- if (!variable.encrypted) {
6491
- res.status(400).json({
6492
- message: "Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys."
6493
- });
6494
- return;
6495
- }
6496
- if (variable.encrypted) {
6497
- const bytes = import_crypto_js3.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
6498
- providerapikey = bytes.toString(import_crypto_js3.default.enc.Utf8);
6593
+ if (variableName) {
6594
+ console.log("[EXULU] provider api key variable name", variableName);
6595
+ const variable = await db3.from("variables").where({ name: variableName }).first();
6596
+ if (!variable) {
6597
+ res.status(400).json({
6598
+ message: "Provider API key variable not found for " + agentInstance.name + " (" + agentInstance.id + ")."
6599
+ });
6600
+ return;
6601
+ }
6602
+ providerapikey = variable.value;
6603
+ console.log("[EXULU] encrypted value", providerapikey);
6604
+ if (!variable.encrypted) {
6605
+ res.status(400).json({
6606
+ message: "Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys."
6607
+ });
6608
+ return;
6609
+ }
6610
+ if (variable.encrypted) {
6611
+ const bytes = import_crypto_js3.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
6612
+ providerapikey = bytes.toString(import_crypto_js3.default.enc.Utf8);
6613
+ console.log("[EXULU] decrypted value", providerapikey);
6614
+ }
6499
6615
  }
6500
6616
  if (!!headers.stream) {
6501
6617
  const statistics = {
@@ -6652,7 +6768,7 @@ Mood: friendly and intelligent.
6652
6768
  return;
6653
6769
  }
6654
6770
  let project = null;
6655
- if (!req.body.project || req.body.project === "DEFAULT") {
6771
+ if (!req.params.project || req.params.project === "DEFAULT") {
6656
6772
  project = null;
6657
6773
  } else {
6658
6774
  let projectQuery = db3("projects");
@@ -6929,10 +7045,11 @@ var createWorkers = async (agents, queues2, config, contexts, evals, tools, trac
6929
7045
  }));
6930
7046
  const { db: db3 } = await postgresClient();
6931
7047
  const data = bullmqJob.data;
6932
- const timeoutMs = data.timeoutInSeconds * 1e3;
7048
+ const timeoutInSeconds = data.timeoutInSeconds || 300;
7049
+ const timeoutMs = timeoutInSeconds * 1e3;
6933
7050
  const timeoutPromise = new Promise((_, reject) => {
6934
7051
  setTimeout(() => {
6935
- reject(new Error(`Timeout for job ${bullmqJob.id} reached after ${data.timeoutInSeconds}s`));
7052
+ reject(new Error(`Timeout for job ${bullmqJob.id} reached after ${timeoutInSeconds}s`));
6936
7053
  }, timeoutMs);
6937
7054
  });
6938
7055
  const workPromise = (async () => {
@@ -7458,17 +7575,20 @@ var processUiMessagesFlow = async ({
7458
7575
  console.log("[EXULU] enabled tools", enabledTools?.map((x) => x.name + " (" + x.id + ")"));
7459
7576
  const variableName = agentInstance.providerapikey;
7460
7577
  const { db: db3 } = await postgresClient();
7461
- const variable = await db3.from("variables").where({ name: variableName }).first();
7462
- if (!variable) {
7463
- throw new Error(`Provider API key variable not found for agent ${agentInstance.name} (${agentInstance.id}).`);
7464
- }
7465
- let providerapikey = variable.value;
7466
- if (!variable.encrypted) {
7467
- throw new Error(`Provider API key variable not encrypted for agent ${agentInstance.name} (${agentInstance.id}), for security reasons you are only allowed to use encrypted variables for provider API keys.`);
7468
- }
7469
- if (variable.encrypted) {
7470
- const bytes = import_crypto_js4.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
7471
- providerapikey = bytes.toString(import_crypto_js4.default.enc.Utf8);
7578
+ let providerapikey;
7579
+ if (variableName) {
7580
+ const variable = await db3.from("variables").where({ name: variableName }).first();
7581
+ if (!variable) {
7582
+ throw new Error(`Provider API key variable not found for agent ${agentInstance.name} (${agentInstance.id}).`);
7583
+ }
7584
+ providerapikey = variable.value;
7585
+ if (!variable.encrypted) {
7586
+ throw new Error(`Provider API key variable not encrypted for agent ${agentInstance.name} (${agentInstance.id}), for security reasons you are only allowed to use encrypted variables for provider API keys.`);
7587
+ }
7588
+ if (variable.encrypted) {
7589
+ const bytes = import_crypto_js4.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
7590
+ providerapikey = bytes.toString(import_crypto_js4.default.enc.Utf8);
7591
+ }
7472
7592
  }
7473
7593
  const messagesWithoutPlaceholder = inputMessages.filter(
7474
7594
  (message) => message.metadata?.type !== "placeholder"
@@ -7660,17 +7780,20 @@ var ExuluMCP = class {
7660
7780
  }
7661
7781
  const variableName = agentInstance.providerapikey;
7662
7782
  const { db: db3 } = await postgresClient();
7663
- const variable = await db3.from("variables").where({ name: variableName }).first();
7664
- if (!variable) {
7665
- throw new Error("Provider API key variable not found.");
7666
- }
7667
- let providerapikey = variable.value;
7668
- if (!variable.encrypted) {
7669
- throw new Error("Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys.");
7670
- }
7671
- if (variable.encrypted) {
7672
- const bytes = import_crypto_js5.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
7673
- providerapikey = bytes.toString(import_crypto_js5.default.enc.Utf8);
7783
+ let providerapikey;
7784
+ if (variableName) {
7785
+ const variable = await db3.from("variables").where({ name: variableName }).first();
7786
+ if (!variable) {
7787
+ throw new Error("Provider API key variable not found for " + agentInstance.name + " (" + agentInstance.id + ").");
7788
+ }
7789
+ providerapikey = variable.value;
7790
+ if (!variable.encrypted) {
7791
+ throw new Error("Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys.");
7792
+ }
7793
+ if (variable.encrypted) {
7794
+ const bytes = import_crypto_js5.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
7795
+ providerapikey = bytes.toString(import_crypto_js5.default.enc.Utf8);
7796
+ }
7674
7797
  }
7675
7798
  console.log("[EXULU] Enabled tools", enabledTools?.map((x) => x.name + " (" + x.id + ")"));
7676
7799
  for (const tool2 of enabledTools || []) {
@@ -7994,6 +8117,68 @@ var claudeSonnet45Agent = new ExuluAgent2({
7994
8117
  }
7995
8118
  });
7996
8119
 
8120
+ // src/templates/agents/google/vertex/index.ts
8121
+ var import_google_vertex = require("@ai-sdk/google-vertex");
8122
+ var wrapperJsonGoogleAuth = `{
8123
+ "project": "project-name",
8124
+ "location": "europe-west1",
8125
+ "googleAuthOptions": {
8126
+ "credentials": {
8127
+ "type": "service_account",
8128
+ "project_id": "XX-XXXX",
8129
+ "private_key_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
8130
+ "private_key": "-----BEGIN PRIVATE KEY-----
8131
+ .... your private key ....
8132
+ -----END PRIVATE KEY-----
8133
+ ",
8134
+ "client_email": "xxxx@xxxx.gserviceaccount.com",
8135
+ "client_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
8136
+ "universe_domain": "googleapis.com"
8137
+ }
8138
+ }
8139
+ }`;
8140
+ var vertexGemini25FlashAgent = new ExuluAgent2({
8141
+ id: `default_vertex_gemini_2_5_flash_agent`,
8142
+ name: `GEMINI-2.5-FLASH`,
8143
+ provider: "vertex",
8144
+ description: `Google Vertex Gemini 2.5 Flash model. Very high intelligence and capability. Moderately Fast.`,
8145
+ type: "agent",
8146
+ capabilities: {
8147
+ text: true,
8148
+ images: [".png", ".jpg", ".jpeg", ".webp"],
8149
+ files: [".pdf", ".txt"],
8150
+ audio: [".mpeg", ".mp3", ".m4a", ".wav", ".mp4"],
8151
+ video: [".mp4", ".mpeg"]
8152
+ },
8153
+ authenticationInformation: `Vertex uses Google Auth, to authenticate you need to visit
8154
+ https://console.cloud.google.com/apis/credentials, create a service account, go to 'keys'
8155
+ and download the resulting JSON file, and copy the contents of the JSON file into an
8156
+ encrypted authentication variable in your IMP Agent Instance like this: ${wrapperJsonGoogleAuth}.`,
8157
+ maxContextLength: 1048576,
8158
+ config: {
8159
+ name: `GEMINI-2.5-FLASH`,
8160
+ instructions: "",
8161
+ model: {
8162
+ create: ({ apiKey }) => {
8163
+ console.log("[EXULU] apiKey", apiKey);
8164
+ if (!apiKey) {
8165
+ throw new Error("Auth credentials not found for Google Vertex agent, make sure you have set the provider api key to a valid google authentication json.");
8166
+ }
8167
+ const googleAuthPayload = JSON.parse(apiKey || "{}");
8168
+ if (!googleAuthPayload) {
8169
+ throw new Error("API key not found for Google Vertex Gemini 2.5 Flash agent.");
8170
+ }
8171
+ if (!googleAuthPayload.location) {
8172
+ throw new Error("Location not set in authentication json for Google Vertex Gemini 2.5 Flash agent, should be for example 'europe-west1'");
8173
+ }
8174
+ const vertex = (0, import_google_vertex.createVertex)(googleAuthPayload);
8175
+ const model = vertex("gemini-2.5-flash");
8176
+ return model;
8177
+ }
8178
+ }
8179
+ }
8180
+ });
8181
+
7997
8182
  // src/templates/agents/openai/gpt.ts
7998
8183
  var import_openai2 = require("@ai-sdk/openai");
7999
8184
  var gpt5proAgent = new ExuluAgent2({
@@ -9407,6 +9592,7 @@ var ExuluApp = class {
9407
9592
  this._agents = [
9408
9593
  claudeSonnet4Agent,
9409
9594
  claudeOpus4Agent,
9595
+ vertexGemini25FlashAgent,
9410
9596
  claudeSonnet45Agent,
9411
9597
  gpt5MiniAgent,
9412
9598
  gpt5agent,
@@ -10886,6 +11072,7 @@ var {
10886
11072
  projectsSchema: projectsSchema3,
10887
11073
  jobResultsSchema: jobResultsSchema3,
10888
11074
  promptLibrarySchema: promptLibrarySchema3,
11075
+ embedderSettingsSchema: embedderSettingsSchema3,
10889
11076
  promptFavoritesSchema: promptFavoritesSchema3
10890
11077
  } = coreSchemas.get();
10891
11078
  var addMissingFields = async (knex, tableName, fields, skipFields = []) => {
@@ -10922,6 +11109,7 @@ var up = async function(knex) {
10922
11109
  projectsSchema3(),
10923
11110
  jobResultsSchema3(),
10924
11111
  promptLibrarySchema3(),
11112
+ embedderSettingsSchema3(),
10925
11113
  promptFavoritesSchema3(),
10926
11114
  rbacSchema3(),
10927
11115
  agentsSchema3(),
@@ -11143,6 +11331,9 @@ var ExuluDefaultAgents = {
11143
11331
  sonnet4: claudeSonnet4Agent,
11144
11332
  sonnet45: claudeSonnet45Agent
11145
11333
  },
11334
+ google: {
11335
+ vertexGemini25Flash: vertexGemini25FlashAgent
11336
+ },
11146
11337
  openai: {
11147
11338
  gpt5Mini: gpt5MiniAgent,
11148
11339
  gpt5: gpt5agent,