@exulu/backend 1.30.0 → 1.30.2

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.30.0](https://github.com/Qventu/exulu-backend/compare/v1.29.0...v1.30.0) (2025-10-28)
1
+ ## [1.30.2](https://github.com/Qventu/exulu-backend/compare/v1.30.1...v1.30.2) (2025-11-04)
2
2
 
3
3
 
4
- ### Features
4
+ ### Bug Fixes
5
5
 
6
- * add tool categorization system with search and pagination ([686b125](https://github.com/Qventu/exulu-backend/commit/686b1259001e7464e7fca8a5ab900170376db02b))
6
+ * add stack log to queue error ([22372bd](https://github.com/Qventu/exulu-backend/commit/22372bd103acaf8346301f9bd7fa3b8ce843b432))
package/dist/index.cjs CHANGED
@@ -437,7 +437,8 @@ var sanitizeName = (name) => {
437
437
 
438
438
  // src/registry/classes.ts
439
439
  var import_crypto_js2 = __toESM(require("crypto-js"), 1);
440
- var import_express2 = require("express");
440
+ var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
441
+ var import_mcp_stdio = require("ai/mcp-stdio");
441
442
 
442
443
  // src/registry/utils/graphql.ts
443
444
  var import_schema = require("@graphql-tools/schema");
@@ -2428,7 +2429,7 @@ var applyAccessControl = (table, user, query) => {
2428
2429
  console.log("[EXULU] table.name.plural", table.name.plural);
2429
2430
  if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2430
2431
  console.error("==== Access control error: no role found or no access to entity type. ====");
2431
- return query.where("id", "=", "0");
2432
+ throw new Error("Access control error: no role found or no access to entity type.");
2432
2433
  }
2433
2434
  const hasRBAC = table.RBAC === true;
2434
2435
  console.log("[EXULU] hasRBAC", hasRBAC);
@@ -4631,6 +4632,7 @@ var createUppyRoutes = async (app, config) => {
4631
4632
  };
4632
4633
 
4633
4634
  // src/registry/classes.ts
4635
+ var import_streamableHttp2 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
4634
4636
  var s3Client2;
4635
4637
  function sanitizeToolName(name) {
4636
4638
  if (typeof name !== "string") return "";
@@ -4649,12 +4651,6 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4649
4651
  name: sanitizeToolName(tool2.name)
4650
4652
  })) : [];
4651
4653
  console.log("[EXULU] Sanitized tools", sanitizedTools.map((x) => x.name + " (" + x.id + ")"));
4652
- const askForConfirmation = {
4653
- description: "Ask the user for confirmation.",
4654
- inputSchema: import_zod.z.object({
4655
- message: import_zod.z.string().describe("The message to ask for confirmation.")
4656
- })
4657
- };
4658
4654
  return {
4659
4655
  ...sanitizedTools?.reduce(
4660
4656
  (prev, cur) => ({
@@ -4753,8 +4749,8 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4753
4749
  }
4754
4750
  }),
4755
4751
  {}
4756
- ),
4757
- askForConfirmation
4752
+ )
4753
+ // askForConfirmation
4758
4754
  };
4759
4755
  };
4760
4756
  var hydrateVariables = async (tool2) => {
@@ -5792,7 +5788,6 @@ var ExuluContext = class {
5792
5788
  };
5793
5789
  };
5794
5790
  var updateStatistic = async (statistic) => {
5795
- console.log("[EXULU] Updating statistic", statistic);
5796
5791
  const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5797
5792
  const { db: db3 } = await postgresClient();
5798
5793
  const existing = await db3.from("tracking").where({
@@ -5803,7 +5798,6 @@ var updateStatistic = async (statistic) => {
5803
5798
  type: statistic.type,
5804
5799
  createdAt: currentDate
5805
5800
  }).first();
5806
- console.log("[EXULU] Existing", existing);
5807
5801
  if (!existing) {
5808
5802
  await db3.from("tracking").insert({
5809
5803
  name: statistic.name,
@@ -5874,11 +5868,11 @@ var getMimeType = (type) => {
5874
5868
  };
5875
5869
 
5876
5870
  // src/registry/index.ts
5877
- var import_express7 = require("express");
5871
+ var import_express6 = require("express");
5878
5872
 
5879
5873
  // src/registry/routes.ts
5880
- var import_express3 = require("express");
5881
- var import_express4 = __toESM(require("express"), 1);
5874
+ var import_express2 = require("express");
5875
+ var import_express3 = __toESM(require("express"), 1);
5882
5876
  var import_server2 = require("@apollo/server");
5883
5877
  var import_cors = __toESM(require("cors"), 1);
5884
5878
  var import_reflect_metadata = require("reflect-metadata");
@@ -5945,7 +5939,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
5945
5939
  optionsSuccessStatus: 200
5946
5940
  // some legacy browsers (IE11, various SmartTVs) choke on 204
5947
5941
  };
5948
- app.use(import_express4.default.json({ limit: REQUEST_SIZE_LIMIT }));
5942
+ app.use(import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }));
5949
5943
  app.use((0, import_cors.default)(corsOptions));
5950
5944
  app.use(import_body_parser.default.urlencoded({ extended: true, limit: REQUEST_SIZE_LIMIT }));
5951
5945
  app.use(import_body_parser.default.json({ limit: REQUEST_SIZE_LIMIT }));
@@ -5985,7 +5979,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
5985
5979
  app.use(
5986
5980
  "/graphql",
5987
5981
  (0, import_cors.default)(corsOptions),
5988
- import_express4.default.json({ limit: REQUEST_SIZE_LIMIT }),
5982
+ import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }),
5989
5983
  (0, import_express5.expressMiddleware)(server, {
5990
5984
  context: async ({ req }) => {
5991
5985
  console.info("[EXULU] Incoming graphql request", {
@@ -6361,7 +6355,7 @@ Mood: friendly and intelligent.
6361
6355
  }
6362
6356
  });
6363
6357
  });
6364
- app.use("/gateway/anthropic/:id", import_express4.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
6358
+ app.use("/gateway/anthropic/:id", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
6365
6359
  try {
6366
6360
  if (!req.body.tools) {
6367
6361
  req.body.tools = [];
@@ -6502,7 +6496,7 @@ data: ${JSON.stringify(event)}
6502
6496
  }
6503
6497
  }
6504
6498
  });
6505
- app.use(import_express4.default.static("public"));
6499
+ app.use(import_express3.default.static("public"));
6506
6500
  return app;
6507
6501
  };
6508
6502
  var createCustomAnthropicStreamingMessage = (message) => {
@@ -7204,10 +7198,10 @@ function getAverage(arr) {
7204
7198
  // src/mcp/index.ts
7205
7199
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
7206
7200
  var import_node_crypto4 = require("crypto");
7207
- var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7201
+ var import_streamableHttp3 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7208
7202
  var import_types = require("@modelcontextprotocol/sdk/types.js");
7209
7203
  var import_zod2 = require("zod");
7210
- var import_express6 = require("express");
7204
+ var import_express4 = require("express");
7211
7205
  var import_api3 = require("@opentelemetry/api");
7212
7206
  var SESSION_ID_HEADER = "mcp-session-id";
7213
7207
  var ExuluMCP = class {
@@ -7294,7 +7288,7 @@ ${code}`
7294
7288
  if (sessionId && this.transports[sessionId]) {
7295
7289
  transport = this.transports[sessionId];
7296
7290
  } else if (!sessionId && (0, import_types.isInitializeRequest)(req.body)) {
7297
- transport = new import_streamableHttp.StreamableHTTPServerTransport({
7291
+ transport = new import_streamableHttp3.StreamableHTTPServerTransport({
7298
7292
  sessionIdGenerator: () => (0, import_node_crypto4.randomUUID)(),
7299
7293
  onsessioninitialized: (sessionId2) => {
7300
7294
  this.transports[sessionId2] = transport;
@@ -7335,7 +7329,7 @@ ${code}`
7335
7329
  };
7336
7330
 
7337
7331
  // src/registry/index.ts
7338
- var import_express8 = __toESM(require("express"), 1);
7332
+ var import_express7 = __toESM(require("express"), 1);
7339
7333
 
7340
7334
  // src/templates/agents/anthropic/claude.ts
7341
7335
  var import_anthropic = require("@ai-sdk/anthropic");
@@ -7801,6 +7795,7 @@ var ExuluQueues = class {
7801
7795
  }
7802
7796
  if (!redisServer.host?.length || !redisServer.port?.length) {
7803
7797
  console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or embedder (look for ExuluQueues.register().use() ).`);
7798
+ console.error(new Error().stack);
7804
7799
  throw new Error(`[EXULU] no redis server configured.`);
7805
7800
  }
7806
7801
  const newQueue = new import_bullmq5.Queue(
@@ -8539,10 +8534,10 @@ var ExuluApp = class {
8539
8534
  // Factory function so we can async
8540
8535
  // initialize the MCP server if needed.
8541
8536
  create = async ({ contexts, agents, config, tools, evals }) => {
8542
- this._evals = [
8537
+ this._evals = redisServer.host?.length && redisServer.port?.length ? [
8543
8538
  llmAsJudgeEval,
8544
8539
  ...evals ?? []
8545
- ];
8540
+ ] : [];
8546
8541
  this._contexts = {
8547
8542
  ...contexts,
8548
8543
  codeStandardsContext,
@@ -8572,6 +8567,7 @@ var ExuluApp = class {
8572
8567
  // Because agents are stored in the database, we add those as tools
8573
8568
  // at request time, not during ExuluApp initialization. We add them
8574
8569
  // in the grahql tools resolver.
8570
+ // ...mcpTools
8575
8571
  ];
8576
8572
  const checks = [
8577
8573
  ...Object.keys(this._contexts || {}).map((x) => ({
@@ -8610,7 +8606,7 @@ var ExuluApp = class {
8610
8606
  express = {
8611
8607
  init: async () => {
8612
8608
  if (!this._expressApp) {
8613
- this._expressApp = (0, import_express8.default)();
8609
+ this._expressApp = (0, import_express7.default)();
8614
8610
  await this.server.express.init();
8615
8611
  console.log("[EXULU] Express app initialized.");
8616
8612
  }
package/dist/index.js CHANGED
@@ -385,7 +385,8 @@ var sanitizeName = (name) => {
385
385
 
386
386
  // src/registry/classes.ts
387
387
  import CryptoJS2 from "crypto-js";
388
- import "express";
388
+ import "@modelcontextprotocol/sdk/client/streamableHttp.js";
389
+ import "ai/mcp-stdio";
389
390
 
390
391
  // src/registry/utils/graphql.ts
391
392
  import { makeExecutableSchema } from "@graphql-tools/schema";
@@ -2376,7 +2377,7 @@ var applyAccessControl = (table, user, query) => {
2376
2377
  console.log("[EXULU] table.name.plural", table.name.plural);
2377
2378
  if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2378
2379
  console.error("==== Access control error: no role found or no access to entity type. ====");
2379
- return query.where("id", "=", "0");
2380
+ throw new Error("Access control error: no role found or no access to entity type.");
2380
2381
  }
2381
2382
  const hasRBAC = table.RBAC === true;
2382
2383
  console.log("[EXULU] hasRBAC", hasRBAC);
@@ -4598,6 +4599,7 @@ var createUppyRoutes = async (app, config) => {
4598
4599
  };
4599
4600
 
4600
4601
  // src/registry/classes.ts
4602
+ import "@modelcontextprotocol/sdk/server/streamableHttp.js";
4601
4603
  var s3Client2;
4602
4604
  function sanitizeToolName(name) {
4603
4605
  if (typeof name !== "string") return "";
@@ -4616,12 +4618,6 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4616
4618
  name: sanitizeToolName(tool2.name)
4617
4619
  })) : [];
4618
4620
  console.log("[EXULU] Sanitized tools", sanitizedTools.map((x) => x.name + " (" + x.id + ")"));
4619
- const askForConfirmation = {
4620
- description: "Ask the user for confirmation.",
4621
- inputSchema: z.object({
4622
- message: z.string().describe("The message to ask for confirmation.")
4623
- })
4624
- };
4625
4621
  return {
4626
4622
  ...sanitizedTools?.reduce(
4627
4623
  (prev, cur) => ({
@@ -4720,8 +4716,8 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4720
4716
  }
4721
4717
  }),
4722
4718
  {}
4723
- ),
4724
- askForConfirmation
4719
+ )
4720
+ // askForConfirmation
4725
4721
  };
4726
4722
  };
4727
4723
  var hydrateVariables = async (tool2) => {
@@ -5759,7 +5755,6 @@ var ExuluContext = class {
5759
5755
  };
5760
5756
  };
5761
5757
  var updateStatistic = async (statistic) => {
5762
- console.log("[EXULU] Updating statistic", statistic);
5763
5758
  const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5764
5759
  const { db: db3 } = await postgresClient();
5765
5760
  const existing = await db3.from("tracking").where({
@@ -5770,7 +5765,6 @@ var updateStatistic = async (statistic) => {
5770
5765
  type: statistic.type,
5771
5766
  createdAt: currentDate
5772
5767
  }).first();
5773
- console.log("[EXULU] Existing", existing);
5774
5768
  if (!existing) {
5775
5769
  await db3.from("tracking").insert({
5776
5770
  name: statistic.name,
@@ -5882,7 +5876,7 @@ var CLAUDE_MESSAGES = {
5882
5876
  };
5883
5877
 
5884
5878
  // src/registry/routes.ts
5885
- import { createIdGenerator as createIdGenerator2 } from "ai";
5879
+ import { createIdGenerator } from "ai";
5886
5880
  var REQUEST_SIZE_LIMIT = "50mb";
5887
5881
  var global_queues = {
5888
5882
  eval_runs: "eval_runs"
@@ -6237,7 +6231,7 @@ Mood: friendly and intelligent.
6237
6231
  console.error("[EXULU] chat response error.", error);
6238
6232
  return errorHandler(error);
6239
6233
  },
6240
- generateMessageId: createIdGenerator2({
6234
+ generateMessageId: createIdGenerator({
6241
6235
  prefix: "msg_",
6242
6236
  size: 16
6243
6237
  }),
@@ -7171,7 +7165,7 @@ function getAverage(arr) {
7171
7165
  // src/mcp/index.ts
7172
7166
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
7173
7167
  import { randomUUID as randomUUID4 } from "crypto";
7174
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7168
+ import { StreamableHTTPServerTransport as StreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7175
7169
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
7176
7170
  import { z as z2 } from "zod";
7177
7171
  import "express";
@@ -7261,7 +7255,7 @@ ${code}`
7261
7255
  if (sessionId && this.transports[sessionId]) {
7262
7256
  transport = this.transports[sessionId];
7263
7257
  } else if (!sessionId && isInitializeRequest(req.body)) {
7264
- transport = new StreamableHTTPServerTransport({
7258
+ transport = new StreamableHTTPServerTransport2({
7265
7259
  sessionIdGenerator: () => randomUUID4(),
7266
7260
  onsessioninitialized: (sessionId2) => {
7267
7261
  this.transports[sessionId2] = transport;
@@ -7768,6 +7762,7 @@ var ExuluQueues = class {
7768
7762
  }
7769
7763
  if (!redisServer.host?.length || !redisServer.port?.length) {
7770
7764
  console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or embedder (look for ExuluQueues.register().use() ).`);
7765
+ console.error(new Error().stack);
7771
7766
  throw new Error(`[EXULU] no redis server configured.`);
7772
7767
  }
7773
7768
  const newQueue = new Queue3(
@@ -8506,10 +8501,10 @@ var ExuluApp = class {
8506
8501
  // Factory function so we can async
8507
8502
  // initialize the MCP server if needed.
8508
8503
  create = async ({ contexts, agents, config, tools, evals }) => {
8509
- this._evals = [
8504
+ this._evals = redisServer.host?.length && redisServer.port?.length ? [
8510
8505
  llmAsJudgeEval,
8511
8506
  ...evals ?? []
8512
- ];
8507
+ ] : [];
8513
8508
  this._contexts = {
8514
8509
  ...contexts,
8515
8510
  codeStandardsContext,
@@ -8539,6 +8534,7 @@ var ExuluApp = class {
8539
8534
  // Because agents are stored in the database, we add those as tools
8540
8535
  // at request time, not during ExuluApp initialization. We add them
8541
8536
  // in the grahql tools resolver.
8537
+ // ...mcpTools
8542
8538
  ];
8543
8539
  const checks = [
8544
8540
  ...Object.keys(this._contexts || {}).map((x) => ({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exulu/backend",
3
3
  "author": "Qventu Bv.",
4
- "version": "1.30.0",
4
+ "version": "1.30.2",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
7
7
  "publishConfig": {