@exulu/backend 0.3.9 → 0.3.11

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.cjs CHANGED
@@ -1038,7 +1038,7 @@ var ExuluAgent = class {
1038
1038
  streaming = false;
1039
1039
  rateLimit;
1040
1040
  config;
1041
- // private memory: Memory | undefined; // TODO remove mastra and do own implementation
1041
+ // private memory: Memory | undefined; // TODO do own implementation
1042
1042
  tools;
1043
1043
  evals;
1044
1044
  model;
@@ -1389,10 +1389,6 @@ var calculateStatistics = (items, method) => {
1389
1389
  if (method === "cosineDistance") {
1390
1390
  methodProperty = "cosine_distance";
1391
1391
  }
1392
- const sorted = items.sort((a, b) => a[methodProperty] - b[methodProperty]);
1393
- const median = sorted[Math.floor(items.length / 2)];
1394
- const max = sorted[sorted.length - 1];
1395
- const min = sorted[0];
1396
1392
  const average = items.reduce((acc, item) => {
1397
1393
  return acc + item[methodProperty];
1398
1394
  }, 0) / items.length;
@@ -1400,9 +1396,6 @@ var calculateStatistics = (items, method) => {
1400
1396
  return acc + item[methodProperty];
1401
1397
  }, 0);
1402
1398
  return {
1403
- max,
1404
- min,
1405
- median,
1406
1399
  average,
1407
1400
  total
1408
1401
  };
@@ -1774,15 +1767,9 @@ var ExuluContext = class {
1774
1767
  return;
1775
1768
  }
1776
1769
  const {
1777
- max,
1778
- min,
1779
- median,
1780
1770
  average,
1781
1771
  total
1782
1772
  } = calculateStatistics(item.chunks, method ?? "cosineDistance");
1783
- item.maxRelevance = max;
1784
- item.minRelevance = min;
1785
- item.medianRelevance = median;
1786
1773
  item.averageRelevance = average;
1787
1774
  item.totalRelevance = total;
1788
1775
  });
@@ -1811,13 +1798,13 @@ var ExuluContext = class {
1811
1798
  return await db2.schema.createTable(tableName, (table) => {
1812
1799
  console.log("[EXULU] Creating fields for table.", this.fields);
1813
1800
  table.uuid("id").primary().defaultTo(db2.fn.uuid());
1814
- table.string("name", 100);
1801
+ table.text("name");
1815
1802
  table.text("description");
1816
- table.string("tags", 100);
1803
+ table.text("tags");
1817
1804
  table.boolean("archived").defaultTo(false);
1818
- table.string("external_id", 100);
1805
+ table.string("external_id", 255);
1819
1806
  table.integer("textLength");
1820
- table.string("source", 100);
1807
+ table.text("source");
1821
1808
  for (const field of this.fields) {
1822
1809
  const { type, name } = field;
1823
1810
  if (!type || !name) {
@@ -2630,7 +2617,6 @@ var import_express5 = require("@as-integrations/express5");
2630
2617
 
2631
2618
  // src/registry/uppy.ts
2632
2619
  var import_express = require("express");
2633
- var import_body_parser = __toESM(require("body-parser"), 1);
2634
2620
  var createUppyRoutes = async (app) => {
2635
2621
  const {
2636
2622
  S3Client,
@@ -2691,7 +2677,6 @@ var createUppyRoutes = async (app) => {
2691
2677
  });
2692
2678
  return stsClient;
2693
2679
  }
2694
- app.use(import_body_parser.default.urlencoded({ extended: true }), import_body_parser.default.json());
2695
2680
  app.get("/s3/list", async (req, res, next) => {
2696
2681
  req.accepts;
2697
2682
  const apikey = req.headers["exulu-api-key"] || null;
@@ -3023,6 +3008,8 @@ var createUppyRoutes = async (app) => {
3023
3008
 
3024
3009
  // src/registry/routes.ts
3025
3010
  var import_utils2 = require("@apollo/utils.keyvaluecache");
3011
+ var import_body_parser = __toESM(require("body-parser"), 1);
3012
+ var REQUEST_SIZE_LIMIT = "50mb";
3026
3013
  var global_queues = {
3027
3014
  logs_cleaner: "logs-cleaner"
3028
3015
  };
@@ -3067,7 +3054,10 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3067
3054
  optionsSuccessStatus: 200
3068
3055
  // some legacy browsers (IE11, various SmartTVs) choke on 204
3069
3056
  };
3057
+ app.use(import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }));
3070
3058
  app.use((0, import_cors.default)(corsOptions));
3059
+ app.use(import_body_parser.default.urlencoded({ extended: true, limit: REQUEST_SIZE_LIMIT }));
3060
+ app.use(import_body_parser.default.json({ limit: REQUEST_SIZE_LIMIT }));
3071
3061
  console.log(`
3072
3062
  \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
3073
3063
  \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
@@ -3075,6 +3065,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3075
3065
  \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
3076
3066
  \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
3077
3067
  \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
3068
+
3078
3069
  `);
3079
3070
  console.log("Agents:");
3080
3071
  console.table(agents.map((agent) => {
@@ -3135,7 +3126,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3135
3126
  app.use(
3136
3127
  "/graphql",
3137
3128
  (0, import_cors.default)(corsOptions),
3138
- import_express3.default.json(),
3129
+ import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }),
3139
3130
  (0, import_express5.expressMiddleware)(server, {
3140
3131
  context: async ({ req }) => {
3141
3132
  const authenticationResult = await requestValidators.authenticate(req);
@@ -3987,6 +3978,73 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3987
3978
  }
3988
3979
  console.log("Routes:");
3989
3980
  console.table(routeLogs);
3981
+ const TARGET_API = "https://api.anthropic.com";
3982
+ app.use("/gateway/anthropic", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
3983
+ const path3 = req.url;
3984
+ const url = `${TARGET_API}${path3}`;
3985
+ console.log("[PROXY] Manual proxy to:", url);
3986
+ console.log("[PROXY] Method:", req.method);
3987
+ console.log("[PROXY] Headers:", Object.keys(req.headers));
3988
+ console.log("[PROXY] Request body length:", req.body ? req.body.length : 0);
3989
+ console.log("[PROXY] Request model name:", req.body.model);
3990
+ console.log("[PROXY] Request stream:", req.body.stream);
3991
+ console.log("[PROXY] API key:", req.headers["x-api-key"]);
3992
+ console.log("[PROXY] Request messages:", req.body.messages?.length);
3993
+ try {
3994
+ const headers = {
3995
+ "x-api-key": process.env.ANTHROPIC_API_KEY,
3996
+ "anthropic-version": "2023-06-01",
3997
+ "content-type": req.headers["content-type"] || "application/json"
3998
+ };
3999
+ if (req.headers["accept"]) headers["accept"] = req.headers["accept"];
4000
+ if (req.headers["user-agent"]) headers["user-agent"] = req.headers["user-agent"];
4001
+ console.log("[PROXY] Request body tools array length:", req.body.tools?.length);
4002
+ if (!req.body.tools) {
4003
+ req.body.tools = [];
4004
+ }
4005
+ if (req.headers["x-api-key"] === "PLACEHOLDER") {
4006
+ res.write(JSON.stringify({
4007
+ "type": "content_block_delta",
4008
+ "index": 0,
4009
+ "delta": {
4010
+ "type": "text_delta",
4011
+ "text": "Hello, world!"
4012
+ }
4013
+ }));
4014
+ res.end();
4015
+ return;
4016
+ }
4017
+ const response = await fetch(url, {
4018
+ method: req.method,
4019
+ headers,
4020
+ body: req.method !== "GET" ? JSON.stringify(req.body) : void 0
4021
+ });
4022
+ console.log("[PROXY] Response status:", response.status);
4023
+ response.headers.forEach((value, key) => {
4024
+ res.setHeader(key, value);
4025
+ });
4026
+ res.status(response.status);
4027
+ if (response.headers.get("content-type")?.includes("text/event-stream")) {
4028
+ const reader = response.body.getReader();
4029
+ const decoder = new TextDecoder();
4030
+ while (true) {
4031
+ const { done, value } = await reader.read();
4032
+ if (done) break;
4033
+ const chunk = decoder.decode(value, { stream: true });
4034
+ res.write(chunk);
4035
+ }
4036
+ res.end();
4037
+ } else {
4038
+ const data = await response.arrayBuffer();
4039
+ res.end(Buffer.from(data));
4040
+ }
4041
+ } catch (error) {
4042
+ console.error("[PROXY] Manual proxy error:", error);
4043
+ if (!res.headersSent) {
4044
+ res.status(500).json({ error: error.message });
4045
+ }
4046
+ }
4047
+ });
3990
4048
  return app;
3991
4049
  };
3992
4050
  var preprocessInputs = async (data) => {
@@ -4244,14 +4302,15 @@ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamable
4244
4302
  var import_types = require("@modelcontextprotocol/sdk/types.js");
4245
4303
  var import_zod3 = require("zod");
4246
4304
  var import_express4 = require("express");
4305
+ var SESSION_ID_HEADER = "mcp-session-id";
4247
4306
  var ExuluMCP = class {
4248
4307
  server;
4249
4308
  transports = {};
4250
4309
  express;
4251
4310
  constructor() {
4252
4311
  }
4253
- create = async ({ express: express2, contexts, embedders, agents, workflows, config, tools }) => {
4254
- this.express = express2;
4312
+ create = async ({ express: express3, contexts, embedders, agents, workflows, config, tools }) => {
4313
+ this.express = express3;
4255
4314
  if (!this.server) {
4256
4315
  console.log("[EXULU] Creating MCP server.");
4257
4316
  this.server = new import_mcp.McpServer({
@@ -4260,14 +4319,21 @@ var ExuluMCP = class {
4260
4319
  });
4261
4320
  }
4262
4321
  this.server.registerTool(
4263
- "add",
4322
+ "getAgents",
4264
4323
  {
4265
- title: "Addition Tool",
4266
- description: "Add two numbers",
4267
- inputSchema: { a: import_zod3.z.number(), b: import_zod3.z.number() }
4324
+ title: "Get agents",
4325
+ description: "Retrieves a list of all available agents"
4268
4326
  },
4269
- async ({ a, b }) => ({
4270
- content: [{ type: "text", text: String(a + b) }]
4327
+ async () => ({
4328
+ content: agents ? agents.map((agent) => {
4329
+ return {
4330
+ type: "text",
4331
+ text: `${agent.name} - ${agent.description}`
4332
+ };
4333
+ }) : [{
4334
+ type: "text",
4335
+ text: "No agents found."
4336
+ }]
4271
4337
  })
4272
4338
  );
4273
4339
  this.server.registerResource(
@@ -4316,7 +4382,12 @@ ${code}`
4316
4382
  }
4317
4383
  console.log("[EXULU] Wiring up MCP server routes to express app.");
4318
4384
  this.express.post("/mcp", async (req, res) => {
4319
- const sessionId = req.headers["mcp-session-id"];
4385
+ if (!this.server) {
4386
+ throw new Error("MCP server not initialized.");
4387
+ }
4388
+ const sessionId = req.headers[SESSION_ID_HEADER];
4389
+ console.log("sessionId!!", sessionId);
4390
+ console.log("req.headers!!", req.headers);
4320
4391
  let transport;
4321
4392
  if (sessionId && this.transports[sessionId]) {
4322
4393
  transport = this.transports[sessionId];
@@ -4336,27 +4407,20 @@ ${code}`
4336
4407
  delete this.transports[transport.sessionId];
4337
4408
  }
4338
4409
  };
4339
- const server = new import_mcp.McpServer({
4340
- name: "example-server",
4341
- version: "1.0.0"
4342
- });
4343
- await server.connect(transport);
4410
+ await this.server.connect(transport);
4344
4411
  } else {
4345
4412
  res.status(400).json({
4346
- jsonrpc: "2.0",
4347
- error: {
4348
- code: -32e3,
4349
- message: "Bad Request: No valid session ID provided"
4350
- },
4351
- id: null
4413
+ error: "Bad Request: No valid session ID provided"
4352
4414
  });
4353
4415
  return;
4354
4416
  }
4355
4417
  await transport.handleRequest(req, res, req.body);
4356
4418
  });
4357
4419
  const handleSessionRequest = async (req, res) => {
4358
- const sessionId = req.headers["mcp-session-id"];
4420
+ console.log("handleSessionRequest", req.body);
4421
+ const sessionId = req.headers[SESSION_ID_HEADER];
4359
4422
  if (!sessionId || !this.transports[sessionId]) {
4423
+ console.log("Invalid or missing session ID");
4360
4424
  res.status(400).send("Invalid or missing session ID");
4361
4425
  return;
4362
4426
  }
@@ -4378,6 +4442,7 @@ ${code}`
4378
4442
  };
4379
4443
 
4380
4444
  // src/registry/index.ts
4445
+ var import_express7 = __toESM(require("express"), 1);
4381
4446
  var ExuluApp = class {
4382
4447
  _agents = [];
4383
4448
  _workflows = [];
@@ -4386,6 +4451,7 @@ var ExuluApp = class {
4386
4451
  _queues = [];
4387
4452
  _contexts = {};
4388
4453
  _tools = [];
4454
+ _expressApp = null;
4389
4455
  constructor() {
4390
4456
  }
4391
4457
  // Factory function so we can async initialize the
@@ -4402,7 +4468,19 @@ var ExuluApp = class {
4402
4468
  ...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
4403
4469
  ];
4404
4470
  this._queues = [...new Set(queues2.filter((o) => !!o))];
4471
+ if (!this._expressApp) {
4472
+ this._expressApp = (0, import_express7.default)();
4473
+ await this.server.express.init();
4474
+ console.log("[EXULU] Express app initialized.");
4475
+ }
4476
+ return this._expressApp;
4405
4477
  };
4478
+ get expressApp() {
4479
+ if (!this._expressApp) {
4480
+ throw new Error("Express app not initialized, initialize it by calling await ExuluApp.create() first.");
4481
+ }
4482
+ return this._expressApp;
4483
+ }
4406
4484
  embedder(id) {
4407
4485
  return this._embedders.find((x) => x.id === id);
4408
4486
  }
@@ -4448,7 +4526,11 @@ var ExuluApp = class {
4448
4526
  };
4449
4527
  server = {
4450
4528
  express: {
4451
- init: async (app) => {
4529
+ init: async () => {
4530
+ if (!this._expressApp) {
4531
+ throw new Error("Express app not initialized");
4532
+ }
4533
+ const app = this._expressApp;
4452
4534
  await createExpressRoutes(
4453
4535
  app,
4454
4536
  this._agents,
@@ -5694,6 +5776,10 @@ var nav = [
5694
5776
  label: "Agents",
5695
5777
  value: "agents"
5696
5778
  },
5779
+ {
5780
+ label: "Start Claude Code",
5781
+ value: "claude-code"
5782
+ },
5697
5783
  {
5698
5784
  label: "Exit",
5699
5785
  value: "exit"
package/dist/index.d.cts CHANGED
@@ -92,6 +92,7 @@ type ExuluAgentConfig = {
92
92
  instructions: string;
93
93
  model: LanguageModelV1;
94
94
  outputSchema?: ZodSchema;
95
+ custom?: ZodSchema;
95
96
  memory?: {
96
97
  lastMessages: number;
97
98
  vector: boolean;
@@ -469,6 +470,7 @@ declare class ExuluApp {
469
470
  private _queues;
470
471
  private _contexts?;
471
472
  private _tools;
473
+ private _expressApp;
472
474
  constructor();
473
475
  create: ({ contexts, embedders, agents, workflows, config, tools }: {
474
476
  contexts?: Record<string, ExuluContext>;
@@ -477,7 +479,8 @@ declare class ExuluApp {
477
479
  agents?: ExuluAgent[];
478
480
  workflows?: ExuluWorkflow[];
479
481
  tools?: ExuluTool[];
480
- }) => Promise<void>;
482
+ }) => Promise<Express>;
483
+ get expressApp(): Express;
481
484
  embedder(id: string): ExuluEmbedder | undefined;
482
485
  tool(id: string): ExuluTool | undefined;
483
486
  tools(): ExuluTool[];
@@ -493,11 +496,7 @@ declare class ExuluApp {
493
496
  create: () => Promise<bullmq.Worker<any, any, string>[]>;
494
497
  };
495
498
  };
496
- server: {
497
- express: {
498
- init: (app: Express) => Promise<Express>;
499
- };
500
- };
499
+ private server;
501
500
  }
502
501
 
503
502
  type User = {
package/dist/index.d.ts CHANGED
@@ -92,6 +92,7 @@ type ExuluAgentConfig = {
92
92
  instructions: string;
93
93
  model: LanguageModelV1;
94
94
  outputSchema?: ZodSchema;
95
+ custom?: ZodSchema;
95
96
  memory?: {
96
97
  lastMessages: number;
97
98
  vector: boolean;
@@ -469,6 +470,7 @@ declare class ExuluApp {
469
470
  private _queues;
470
471
  private _contexts?;
471
472
  private _tools;
473
+ private _expressApp;
472
474
  constructor();
473
475
  create: ({ contexts, embedders, agents, workflows, config, tools }: {
474
476
  contexts?: Record<string, ExuluContext>;
@@ -477,7 +479,8 @@ declare class ExuluApp {
477
479
  agents?: ExuluAgent[];
478
480
  workflows?: ExuluWorkflow[];
479
481
  tools?: ExuluTool[];
480
- }) => Promise<void>;
482
+ }) => Promise<Express>;
483
+ get expressApp(): Express;
481
484
  embedder(id: string): ExuluEmbedder | undefined;
482
485
  tool(id: string): ExuluTool | undefined;
483
486
  tools(): ExuluTool[];
@@ -493,11 +496,7 @@ declare class ExuluApp {
493
496
  create: () => Promise<bullmq.Worker<any, any, string>[]>;
494
497
  };
495
498
  };
496
- server: {
497
- express: {
498
- init: (app: Express) => Promise<Express>;
499
- };
500
- };
499
+ private server;
501
500
  }
502
501
 
503
502
  type User = {
package/dist/index.js CHANGED
@@ -994,7 +994,7 @@ var ExuluAgent = class {
994
994
  streaming = false;
995
995
  rateLimit;
996
996
  config;
997
- // private memory: Memory | undefined; // TODO remove mastra and do own implementation
997
+ // private memory: Memory | undefined; // TODO do own implementation
998
998
  tools;
999
999
  evals;
1000
1000
  model;
@@ -1345,10 +1345,6 @@ var calculateStatistics = (items, method) => {
1345
1345
  if (method === "cosineDistance") {
1346
1346
  methodProperty = "cosine_distance";
1347
1347
  }
1348
- const sorted = items.sort((a, b) => a[methodProperty] - b[methodProperty]);
1349
- const median = sorted[Math.floor(items.length / 2)];
1350
- const max = sorted[sorted.length - 1];
1351
- const min = sorted[0];
1352
1348
  const average = items.reduce((acc, item) => {
1353
1349
  return acc + item[methodProperty];
1354
1350
  }, 0) / items.length;
@@ -1356,9 +1352,6 @@ var calculateStatistics = (items, method) => {
1356
1352
  return acc + item[methodProperty];
1357
1353
  }, 0);
1358
1354
  return {
1359
- max,
1360
- min,
1361
- median,
1362
1355
  average,
1363
1356
  total
1364
1357
  };
@@ -1730,15 +1723,9 @@ var ExuluContext = class {
1730
1723
  return;
1731
1724
  }
1732
1725
  const {
1733
- max,
1734
- min,
1735
- median,
1736
1726
  average,
1737
1727
  total
1738
1728
  } = calculateStatistics(item.chunks, method ?? "cosineDistance");
1739
- item.maxRelevance = max;
1740
- item.minRelevance = min;
1741
- item.medianRelevance = median;
1742
1729
  item.averageRelevance = average;
1743
1730
  item.totalRelevance = total;
1744
1731
  });
@@ -1767,13 +1754,13 @@ var ExuluContext = class {
1767
1754
  return await db2.schema.createTable(tableName, (table) => {
1768
1755
  console.log("[EXULU] Creating fields for table.", this.fields);
1769
1756
  table.uuid("id").primary().defaultTo(db2.fn.uuid());
1770
- table.string("name", 100);
1757
+ table.text("name");
1771
1758
  table.text("description");
1772
- table.string("tags", 100);
1759
+ table.text("tags");
1773
1760
  table.boolean("archived").defaultTo(false);
1774
- table.string("external_id", 100);
1761
+ table.string("external_id", 255);
1775
1762
  table.integer("textLength");
1776
- table.string("source", 100);
1763
+ table.text("source");
1777
1764
  for (const field of this.fields) {
1778
1765
  const { type, name } = field;
1779
1766
  if (!type || !name) {
@@ -2586,7 +2573,6 @@ import { expressMiddleware } from "@as-integrations/express5";
2586
2573
 
2587
2574
  // src/registry/uppy.ts
2588
2575
  import "express";
2589
- import bodyParser from "body-parser";
2590
2576
  var createUppyRoutes = async (app) => {
2591
2577
  const {
2592
2578
  S3Client,
@@ -2647,7 +2633,6 @@ var createUppyRoutes = async (app) => {
2647
2633
  });
2648
2634
  return stsClient;
2649
2635
  }
2650
- app.use(bodyParser.urlencoded({ extended: true }), bodyParser.json());
2651
2636
  app.get("/s3/list", async (req, res, next) => {
2652
2637
  req.accepts;
2653
2638
  const apikey = req.headers["exulu-api-key"] || null;
@@ -2979,6 +2964,8 @@ var createUppyRoutes = async (app) => {
2979
2964
 
2980
2965
  // src/registry/routes.ts
2981
2966
  import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
2967
+ import bodyParser from "body-parser";
2968
+ var REQUEST_SIZE_LIMIT = "50mb";
2982
2969
  var global_queues = {
2983
2970
  logs_cleaner: "logs-cleaner"
2984
2971
  };
@@ -3023,7 +3010,10 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3023
3010
  optionsSuccessStatus: 200
3024
3011
  // some legacy browsers (IE11, various SmartTVs) choke on 204
3025
3012
  };
3013
+ app.use(express.json({ limit: REQUEST_SIZE_LIMIT }));
3026
3014
  app.use(cors(corsOptions));
3015
+ app.use(bodyParser.urlencoded({ extended: true, limit: REQUEST_SIZE_LIMIT }));
3016
+ app.use(bodyParser.json({ limit: REQUEST_SIZE_LIMIT }));
3027
3017
  console.log(`
3028
3018
  \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
3029
3019
  \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
@@ -3031,6 +3021,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3031
3021
  \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
3032
3022
  \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
3033
3023
  \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
3024
+
3034
3025
  `);
3035
3026
  console.log("Agents:");
3036
3027
  console.table(agents.map((agent) => {
@@ -3091,7 +3082,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3091
3082
  app.use(
3092
3083
  "/graphql",
3093
3084
  cors(corsOptions),
3094
- express.json(),
3085
+ express.json({ limit: REQUEST_SIZE_LIMIT }),
3095
3086
  expressMiddleware(server, {
3096
3087
  context: async ({ req }) => {
3097
3088
  const authenticationResult = await requestValidators.authenticate(req);
@@ -3943,6 +3934,73 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3943
3934
  }
3944
3935
  console.log("Routes:");
3945
3936
  console.table(routeLogs);
3937
+ const TARGET_API = "https://api.anthropic.com";
3938
+ app.use("/gateway/anthropic", express.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
3939
+ const path3 = req.url;
3940
+ const url = `${TARGET_API}${path3}`;
3941
+ console.log("[PROXY] Manual proxy to:", url);
3942
+ console.log("[PROXY] Method:", req.method);
3943
+ console.log("[PROXY] Headers:", Object.keys(req.headers));
3944
+ console.log("[PROXY] Request body length:", req.body ? req.body.length : 0);
3945
+ console.log("[PROXY] Request model name:", req.body.model);
3946
+ console.log("[PROXY] Request stream:", req.body.stream);
3947
+ console.log("[PROXY] API key:", req.headers["x-api-key"]);
3948
+ console.log("[PROXY] Request messages:", req.body.messages?.length);
3949
+ try {
3950
+ const headers = {
3951
+ "x-api-key": process.env.ANTHROPIC_API_KEY,
3952
+ "anthropic-version": "2023-06-01",
3953
+ "content-type": req.headers["content-type"] || "application/json"
3954
+ };
3955
+ if (req.headers["accept"]) headers["accept"] = req.headers["accept"];
3956
+ if (req.headers["user-agent"]) headers["user-agent"] = req.headers["user-agent"];
3957
+ console.log("[PROXY] Request body tools array length:", req.body.tools?.length);
3958
+ if (!req.body.tools) {
3959
+ req.body.tools = [];
3960
+ }
3961
+ if (req.headers["x-api-key"] === "PLACEHOLDER") {
3962
+ res.write(JSON.stringify({
3963
+ "type": "content_block_delta",
3964
+ "index": 0,
3965
+ "delta": {
3966
+ "type": "text_delta",
3967
+ "text": "Hello, world!"
3968
+ }
3969
+ }));
3970
+ res.end();
3971
+ return;
3972
+ }
3973
+ const response = await fetch(url, {
3974
+ method: req.method,
3975
+ headers,
3976
+ body: req.method !== "GET" ? JSON.stringify(req.body) : void 0
3977
+ });
3978
+ console.log("[PROXY] Response status:", response.status);
3979
+ response.headers.forEach((value, key) => {
3980
+ res.setHeader(key, value);
3981
+ });
3982
+ res.status(response.status);
3983
+ if (response.headers.get("content-type")?.includes("text/event-stream")) {
3984
+ const reader = response.body.getReader();
3985
+ const decoder = new TextDecoder();
3986
+ while (true) {
3987
+ const { done, value } = await reader.read();
3988
+ if (done) break;
3989
+ const chunk = decoder.decode(value, { stream: true });
3990
+ res.write(chunk);
3991
+ }
3992
+ res.end();
3993
+ } else {
3994
+ const data = await response.arrayBuffer();
3995
+ res.end(Buffer.from(data));
3996
+ }
3997
+ } catch (error) {
3998
+ console.error("[PROXY] Manual proxy error:", error);
3999
+ if (!res.headersSent) {
4000
+ res.status(500).json({ error: error.message });
4001
+ }
4002
+ }
4003
+ });
3946
4004
  return app;
3947
4005
  };
3948
4006
  var preprocessInputs = async (data) => {
@@ -4200,14 +4258,15 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
4200
4258
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
4201
4259
  import { z as z2 } from "zod";
4202
4260
  import "express";
4261
+ var SESSION_ID_HEADER = "mcp-session-id";
4203
4262
  var ExuluMCP = class {
4204
4263
  server;
4205
4264
  transports = {};
4206
4265
  express;
4207
4266
  constructor() {
4208
4267
  }
4209
- create = async ({ express: express2, contexts, embedders, agents, workflows, config, tools }) => {
4210
- this.express = express2;
4268
+ create = async ({ express: express3, contexts, embedders, agents, workflows, config, tools }) => {
4269
+ this.express = express3;
4211
4270
  if (!this.server) {
4212
4271
  console.log("[EXULU] Creating MCP server.");
4213
4272
  this.server = new McpServer({
@@ -4216,14 +4275,21 @@ var ExuluMCP = class {
4216
4275
  });
4217
4276
  }
4218
4277
  this.server.registerTool(
4219
- "add",
4278
+ "getAgents",
4220
4279
  {
4221
- title: "Addition Tool",
4222
- description: "Add two numbers",
4223
- inputSchema: { a: z2.number(), b: z2.number() }
4280
+ title: "Get agents",
4281
+ description: "Retrieves a list of all available agents"
4224
4282
  },
4225
- async ({ a, b }) => ({
4226
- content: [{ type: "text", text: String(a + b) }]
4283
+ async () => ({
4284
+ content: agents ? agents.map((agent) => {
4285
+ return {
4286
+ type: "text",
4287
+ text: `${agent.name} - ${agent.description}`
4288
+ };
4289
+ }) : [{
4290
+ type: "text",
4291
+ text: "No agents found."
4292
+ }]
4227
4293
  })
4228
4294
  );
4229
4295
  this.server.registerResource(
@@ -4272,7 +4338,12 @@ ${code}`
4272
4338
  }
4273
4339
  console.log("[EXULU] Wiring up MCP server routes to express app.");
4274
4340
  this.express.post("/mcp", async (req, res) => {
4275
- const sessionId = req.headers["mcp-session-id"];
4341
+ if (!this.server) {
4342
+ throw new Error("MCP server not initialized.");
4343
+ }
4344
+ const sessionId = req.headers[SESSION_ID_HEADER];
4345
+ console.log("sessionId!!", sessionId);
4346
+ console.log("req.headers!!", req.headers);
4276
4347
  let transport;
4277
4348
  if (sessionId && this.transports[sessionId]) {
4278
4349
  transport = this.transports[sessionId];
@@ -4292,27 +4363,20 @@ ${code}`
4292
4363
  delete this.transports[transport.sessionId];
4293
4364
  }
4294
4365
  };
4295
- const server = new McpServer({
4296
- name: "example-server",
4297
- version: "1.0.0"
4298
- });
4299
- await server.connect(transport);
4366
+ await this.server.connect(transport);
4300
4367
  } else {
4301
4368
  res.status(400).json({
4302
- jsonrpc: "2.0",
4303
- error: {
4304
- code: -32e3,
4305
- message: "Bad Request: No valid session ID provided"
4306
- },
4307
- id: null
4369
+ error: "Bad Request: No valid session ID provided"
4308
4370
  });
4309
4371
  return;
4310
4372
  }
4311
4373
  await transport.handleRequest(req, res, req.body);
4312
4374
  });
4313
4375
  const handleSessionRequest = async (req, res) => {
4314
- const sessionId = req.headers["mcp-session-id"];
4376
+ console.log("handleSessionRequest", req.body);
4377
+ const sessionId = req.headers[SESSION_ID_HEADER];
4315
4378
  if (!sessionId || !this.transports[sessionId]) {
4379
+ console.log("Invalid or missing session ID");
4316
4380
  res.status(400).send("Invalid or missing session ID");
4317
4381
  return;
4318
4382
  }
@@ -4334,6 +4398,7 @@ ${code}`
4334
4398
  };
4335
4399
 
4336
4400
  // src/registry/index.ts
4401
+ import express2 from "express";
4337
4402
  var ExuluApp = class {
4338
4403
  _agents = [];
4339
4404
  _workflows = [];
@@ -4342,6 +4407,7 @@ var ExuluApp = class {
4342
4407
  _queues = [];
4343
4408
  _contexts = {};
4344
4409
  _tools = [];
4410
+ _expressApp = null;
4345
4411
  constructor() {
4346
4412
  }
4347
4413
  // Factory function so we can async initialize the
@@ -4358,7 +4424,19 @@ var ExuluApp = class {
4358
4424
  ...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
4359
4425
  ];
4360
4426
  this._queues = [...new Set(queues2.filter((o) => !!o))];
4427
+ if (!this._expressApp) {
4428
+ this._expressApp = express2();
4429
+ await this.server.express.init();
4430
+ console.log("[EXULU] Express app initialized.");
4431
+ }
4432
+ return this._expressApp;
4361
4433
  };
4434
+ get expressApp() {
4435
+ if (!this._expressApp) {
4436
+ throw new Error("Express app not initialized, initialize it by calling await ExuluApp.create() first.");
4437
+ }
4438
+ return this._expressApp;
4439
+ }
4362
4440
  embedder(id) {
4363
4441
  return this._embedders.find((x) => x.id === id);
4364
4442
  }
@@ -4404,7 +4482,11 @@ var ExuluApp = class {
4404
4482
  };
4405
4483
  server = {
4406
4484
  express: {
4407
- init: async (app) => {
4485
+ init: async () => {
4486
+ if (!this._expressApp) {
4487
+ throw new Error("Express app not initialized");
4488
+ }
4489
+ const app = this._expressApp;
4408
4490
  await createExpressRoutes(
4409
4491
  app,
4410
4492
  this._agents,
@@ -5650,6 +5732,10 @@ var nav = [
5650
5732
  label: "Agents",
5651
5733
  value: "agents"
5652
5734
  },
5735
+ {
5736
+ label: "Start Claude Code",
5737
+ value: "claude-code"
5738
+ },
5653
5739
  {
5654
5740
  label: "Exit",
5655
5741
  value: "exit"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exulu/backend",
3
3
  "author": "Qventu Bv.",
4
- "version": "0.3.9",
4
+ "version": "0.3.11",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
7
7
  "publishConfig": {
@@ -36,6 +36,8 @@
36
36
  "typescript": "^5.8.3"
37
37
  },
38
38
  "dependencies": {
39
+ "@ai-sdk/anthropic": "^1.2.12",
40
+ "@anthropic-ai/sdk": "^0.56.0",
39
41
  "@as-integrations/express5": "^1.0.0",
40
42
  "@aws-sdk/client-s3": "^3.338.0",
41
43
  "@aws-sdk/client-sts": "^3.338.0",
@@ -62,6 +64,7 @@
62
64
  "graphql": "^16.11.0",
63
65
  "graphql-tools": "^9.0.18",
64
66
  "graphql-type-json": "^0.3.2",
67
+ "http-proxy-middleware": "^3.0.5",
65
68
  "ink": "^6.0.0",
66
69
  "ink-big-text": "^2.0.0",
67
70
  "ink-gradient": "^3.0.0",