@exulu/backend 0.3.10 → 0.3.12

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
@@ -494,7 +494,7 @@ var agentsSchema = {
494
494
  // src/registry/utils/map-types.ts
495
495
  var mapType = (t, type, name, defaultValue) => {
496
496
  if (type === "text") {
497
- t.string(name, 255);
497
+ t.text(name);
498
498
  return;
499
499
  }
500
500
  if (type === "longText") {
@@ -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;
@@ -1798,13 +1798,13 @@ var ExuluContext = class {
1798
1798
  return await db2.schema.createTable(tableName, (table) => {
1799
1799
  console.log("[EXULU] Creating fields for table.", this.fields);
1800
1800
  table.uuid("id").primary().defaultTo(db2.fn.uuid());
1801
- table.string("name", 100);
1801
+ table.text("name");
1802
1802
  table.text("description");
1803
- table.string("tags", 100);
1803
+ table.text("tags");
1804
1804
  table.boolean("archived").defaultTo(false);
1805
- table.string("external_id", 100);
1805
+ table.text("external_id");
1806
1806
  table.integer("textLength");
1807
- table.string("source", 100);
1807
+ table.text("source");
1808
1808
  for (const field of this.fields) {
1809
1809
  const { type, name } = field;
1810
1810
  if (!type || !name) {
@@ -2617,7 +2617,6 @@ var import_express5 = require("@as-integrations/express5");
2617
2617
 
2618
2618
  // src/registry/uppy.ts
2619
2619
  var import_express = require("express");
2620
- var import_body_parser = __toESM(require("body-parser"), 1);
2621
2620
  var createUppyRoutes = async (app) => {
2622
2621
  const {
2623
2622
  S3Client,
@@ -2678,7 +2677,6 @@ var createUppyRoutes = async (app) => {
2678
2677
  });
2679
2678
  return stsClient;
2680
2679
  }
2681
- app.use(import_body_parser.default.urlencoded({ extended: true }), import_body_parser.default.json());
2682
2680
  app.get("/s3/list", async (req, res, next) => {
2683
2681
  req.accepts;
2684
2682
  const apikey = req.headers["exulu-api-key"] || null;
@@ -3010,6 +3008,8 @@ var createUppyRoutes = async (app) => {
3010
3008
 
3011
3009
  // src/registry/routes.ts
3012
3010
  var import_utils2 = require("@apollo/utils.keyvaluecache");
3011
+ var import_body_parser = __toESM(require("body-parser"), 1);
3012
+ var REQUEST_SIZE_LIMIT = "50mb";
3013
3013
  var global_queues = {
3014
3014
  logs_cleaner: "logs-cleaner"
3015
3015
  };
@@ -3054,7 +3054,10 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3054
3054
  optionsSuccessStatus: 200
3055
3055
  // some legacy browsers (IE11, various SmartTVs) choke on 204
3056
3056
  };
3057
+ app.use(import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }));
3057
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 }));
3058
3061
  console.log(`
3059
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
3060
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
@@ -3062,6 +3065,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3062
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
3063
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
3064
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
+
3065
3069
  `);
3066
3070
  console.log("Agents:");
3067
3071
  console.table(agents.map((agent) => {
@@ -3122,7 +3126,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3122
3126
  app.use(
3123
3127
  "/graphql",
3124
3128
  (0, import_cors.default)(corsOptions),
3125
- import_express3.default.json(),
3129
+ import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }),
3126
3130
  (0, import_express5.expressMiddleware)(server, {
3127
3131
  context: async ({ req }) => {
3128
3132
  const authenticationResult = await requestValidators.authenticate(req);
@@ -3974,6 +3978,73 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3974
3978
  }
3975
3979
  console.log("Routes:");
3976
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
+ });
3977
4048
  return app;
3978
4049
  };
3979
4050
  var preprocessInputs = async (data) => {
@@ -4231,14 +4302,15 @@ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamable
4231
4302
  var import_types = require("@modelcontextprotocol/sdk/types.js");
4232
4303
  var import_zod3 = require("zod");
4233
4304
  var import_express4 = require("express");
4305
+ var SESSION_ID_HEADER = "mcp-session-id";
4234
4306
  var ExuluMCP = class {
4235
4307
  server;
4236
4308
  transports = {};
4237
4309
  express;
4238
4310
  constructor() {
4239
4311
  }
4240
- create = async ({ express: express2, contexts, embedders, agents, workflows, config, tools }) => {
4241
- this.express = express2;
4312
+ create = async ({ express: express3, contexts, embedders, agents, workflows, config, tools }) => {
4313
+ this.express = express3;
4242
4314
  if (!this.server) {
4243
4315
  console.log("[EXULU] Creating MCP server.");
4244
4316
  this.server = new import_mcp.McpServer({
@@ -4247,14 +4319,21 @@ var ExuluMCP = class {
4247
4319
  });
4248
4320
  }
4249
4321
  this.server.registerTool(
4250
- "add",
4322
+ "getAgents",
4251
4323
  {
4252
- title: "Addition Tool",
4253
- description: "Add two numbers",
4254
- inputSchema: { a: import_zod3.z.number(), b: import_zod3.z.number() }
4324
+ title: "Get agents",
4325
+ description: "Retrieves a list of all available agents"
4255
4326
  },
4256
- async ({ a, b }) => ({
4257
- 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
+ }]
4258
4337
  })
4259
4338
  );
4260
4339
  this.server.registerResource(
@@ -4303,7 +4382,12 @@ ${code}`
4303
4382
  }
4304
4383
  console.log("[EXULU] Wiring up MCP server routes to express app.");
4305
4384
  this.express.post("/mcp", async (req, res) => {
4306
- 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);
4307
4391
  let transport;
4308
4392
  if (sessionId && this.transports[sessionId]) {
4309
4393
  transport = this.transports[sessionId];
@@ -4323,27 +4407,20 @@ ${code}`
4323
4407
  delete this.transports[transport.sessionId];
4324
4408
  }
4325
4409
  };
4326
- const server = new import_mcp.McpServer({
4327
- name: "example-server",
4328
- version: "1.0.0"
4329
- });
4330
- await server.connect(transport);
4410
+ await this.server.connect(transport);
4331
4411
  } else {
4332
4412
  res.status(400).json({
4333
- jsonrpc: "2.0",
4334
- error: {
4335
- code: -32e3,
4336
- message: "Bad Request: No valid session ID provided"
4337
- },
4338
- id: null
4413
+ error: "Bad Request: No valid session ID provided"
4339
4414
  });
4340
4415
  return;
4341
4416
  }
4342
4417
  await transport.handleRequest(req, res, req.body);
4343
4418
  });
4344
4419
  const handleSessionRequest = async (req, res) => {
4345
- const sessionId = req.headers["mcp-session-id"];
4420
+ console.log("handleSessionRequest", req.body);
4421
+ const sessionId = req.headers[SESSION_ID_HEADER];
4346
4422
  if (!sessionId || !this.transports[sessionId]) {
4423
+ console.log("Invalid or missing session ID");
4347
4424
  res.status(400).send("Invalid or missing session ID");
4348
4425
  return;
4349
4426
  }
@@ -4365,6 +4442,7 @@ ${code}`
4365
4442
  };
4366
4443
 
4367
4444
  // src/registry/index.ts
4445
+ var import_express7 = __toESM(require("express"), 1);
4368
4446
  var ExuluApp = class {
4369
4447
  _agents = [];
4370
4448
  _workflows = [];
@@ -4373,6 +4451,7 @@ var ExuluApp = class {
4373
4451
  _queues = [];
4374
4452
  _contexts = {};
4375
4453
  _tools = [];
4454
+ _expressApp = null;
4376
4455
  constructor() {
4377
4456
  }
4378
4457
  // Factory function so we can async initialize the
@@ -4389,7 +4468,19 @@ var ExuluApp = class {
4389
4468
  ...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
4390
4469
  ];
4391
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;
4392
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
+ }
4393
4484
  embedder(id) {
4394
4485
  return this._embedders.find((x) => x.id === id);
4395
4486
  }
@@ -4435,7 +4526,11 @@ var ExuluApp = class {
4435
4526
  };
4436
4527
  server = {
4437
4528
  express: {
4438
- init: async (app) => {
4529
+ init: async () => {
4530
+ if (!this._expressApp) {
4531
+ throw new Error("Express app not initialized");
4532
+ }
4533
+ const app = this._expressApp;
4439
4534
  await createExpressRoutes(
4440
4535
  app,
4441
4536
  this._agents,
@@ -5681,6 +5776,10 @@ var nav = [
5681
5776
  label: "Agents",
5682
5777
  value: "agents"
5683
5778
  },
5779
+ {
5780
+ label: "Start Claude Code",
5781
+ value: "claude-code"
5782
+ },
5684
5783
  {
5685
5784
  label: "Exit",
5686
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
@@ -450,7 +450,7 @@ var agentsSchema = {
450
450
  // src/registry/utils/map-types.ts
451
451
  var mapType = (t, type, name, defaultValue) => {
452
452
  if (type === "text") {
453
- t.string(name, 255);
453
+ t.text(name);
454
454
  return;
455
455
  }
456
456
  if (type === "longText") {
@@ -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;
@@ -1754,13 +1754,13 @@ var ExuluContext = class {
1754
1754
  return await db2.schema.createTable(tableName, (table) => {
1755
1755
  console.log("[EXULU] Creating fields for table.", this.fields);
1756
1756
  table.uuid("id").primary().defaultTo(db2.fn.uuid());
1757
- table.string("name", 100);
1757
+ table.text("name");
1758
1758
  table.text("description");
1759
- table.string("tags", 100);
1759
+ table.text("tags");
1760
1760
  table.boolean("archived").defaultTo(false);
1761
- table.string("external_id", 100);
1761
+ table.text("external_id");
1762
1762
  table.integer("textLength");
1763
- table.string("source", 100);
1763
+ table.text("source");
1764
1764
  for (const field of this.fields) {
1765
1765
  const { type, name } = field;
1766
1766
  if (!type || !name) {
@@ -2573,7 +2573,6 @@ import { expressMiddleware } from "@as-integrations/express5";
2573
2573
 
2574
2574
  // src/registry/uppy.ts
2575
2575
  import "express";
2576
- import bodyParser from "body-parser";
2577
2576
  var createUppyRoutes = async (app) => {
2578
2577
  const {
2579
2578
  S3Client,
@@ -2634,7 +2633,6 @@ var createUppyRoutes = async (app) => {
2634
2633
  });
2635
2634
  return stsClient;
2636
2635
  }
2637
- app.use(bodyParser.urlencoded({ extended: true }), bodyParser.json());
2638
2636
  app.get("/s3/list", async (req, res, next) => {
2639
2637
  req.accepts;
2640
2638
  const apikey = req.headers["exulu-api-key"] || null;
@@ -2966,6 +2964,8 @@ var createUppyRoutes = async (app) => {
2966
2964
 
2967
2965
  // src/registry/routes.ts
2968
2966
  import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
2967
+ import bodyParser from "body-parser";
2968
+ var REQUEST_SIZE_LIMIT = "50mb";
2969
2969
  var global_queues = {
2970
2970
  logs_cleaner: "logs-cleaner"
2971
2971
  };
@@ -3010,7 +3010,10 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3010
3010
  optionsSuccessStatus: 200
3011
3011
  // some legacy browsers (IE11, various SmartTVs) choke on 204
3012
3012
  };
3013
+ app.use(express.json({ limit: REQUEST_SIZE_LIMIT }));
3013
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 }));
3014
3017
  console.log(`
3015
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
3016
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
@@ -3018,6 +3021,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3018
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
3019
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
3020
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
+
3021
3025
  `);
3022
3026
  console.log("Agents:");
3023
3027
  console.table(agents.map((agent) => {
@@ -3078,7 +3082,7 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3078
3082
  app.use(
3079
3083
  "/graphql",
3080
3084
  cors(corsOptions),
3081
- express.json(),
3085
+ express.json({ limit: REQUEST_SIZE_LIMIT }),
3082
3086
  expressMiddleware(server, {
3083
3087
  context: async ({ req }) => {
3084
3088
  const authenticationResult = await requestValidators.authenticate(req);
@@ -3930,6 +3934,73 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
3930
3934
  }
3931
3935
  console.log("Routes:");
3932
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
+ });
3933
4004
  return app;
3934
4005
  };
3935
4006
  var preprocessInputs = async (data) => {
@@ -4187,14 +4258,15 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
4187
4258
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
4188
4259
  import { z as z2 } from "zod";
4189
4260
  import "express";
4261
+ var SESSION_ID_HEADER = "mcp-session-id";
4190
4262
  var ExuluMCP = class {
4191
4263
  server;
4192
4264
  transports = {};
4193
4265
  express;
4194
4266
  constructor() {
4195
4267
  }
4196
- create = async ({ express: express2, contexts, embedders, agents, workflows, config, tools }) => {
4197
- this.express = express2;
4268
+ create = async ({ express: express3, contexts, embedders, agents, workflows, config, tools }) => {
4269
+ this.express = express3;
4198
4270
  if (!this.server) {
4199
4271
  console.log("[EXULU] Creating MCP server.");
4200
4272
  this.server = new McpServer({
@@ -4203,14 +4275,21 @@ var ExuluMCP = class {
4203
4275
  });
4204
4276
  }
4205
4277
  this.server.registerTool(
4206
- "add",
4278
+ "getAgents",
4207
4279
  {
4208
- title: "Addition Tool",
4209
- description: "Add two numbers",
4210
- inputSchema: { a: z2.number(), b: z2.number() }
4280
+ title: "Get agents",
4281
+ description: "Retrieves a list of all available agents"
4211
4282
  },
4212
- async ({ a, b }) => ({
4213
- 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
+ }]
4214
4293
  })
4215
4294
  );
4216
4295
  this.server.registerResource(
@@ -4259,7 +4338,12 @@ ${code}`
4259
4338
  }
4260
4339
  console.log("[EXULU] Wiring up MCP server routes to express app.");
4261
4340
  this.express.post("/mcp", async (req, res) => {
4262
- 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);
4263
4347
  let transport;
4264
4348
  if (sessionId && this.transports[sessionId]) {
4265
4349
  transport = this.transports[sessionId];
@@ -4279,27 +4363,20 @@ ${code}`
4279
4363
  delete this.transports[transport.sessionId];
4280
4364
  }
4281
4365
  };
4282
- const server = new McpServer({
4283
- name: "example-server",
4284
- version: "1.0.0"
4285
- });
4286
- await server.connect(transport);
4366
+ await this.server.connect(transport);
4287
4367
  } else {
4288
4368
  res.status(400).json({
4289
- jsonrpc: "2.0",
4290
- error: {
4291
- code: -32e3,
4292
- message: "Bad Request: No valid session ID provided"
4293
- },
4294
- id: null
4369
+ error: "Bad Request: No valid session ID provided"
4295
4370
  });
4296
4371
  return;
4297
4372
  }
4298
4373
  await transport.handleRequest(req, res, req.body);
4299
4374
  });
4300
4375
  const handleSessionRequest = async (req, res) => {
4301
- const sessionId = req.headers["mcp-session-id"];
4376
+ console.log("handleSessionRequest", req.body);
4377
+ const sessionId = req.headers[SESSION_ID_HEADER];
4302
4378
  if (!sessionId || !this.transports[sessionId]) {
4379
+ console.log("Invalid or missing session ID");
4303
4380
  res.status(400).send("Invalid or missing session ID");
4304
4381
  return;
4305
4382
  }
@@ -4321,6 +4398,7 @@ ${code}`
4321
4398
  };
4322
4399
 
4323
4400
  // src/registry/index.ts
4401
+ import express2 from "express";
4324
4402
  var ExuluApp = class {
4325
4403
  _agents = [];
4326
4404
  _workflows = [];
@@ -4329,6 +4407,7 @@ var ExuluApp = class {
4329
4407
  _queues = [];
4330
4408
  _contexts = {};
4331
4409
  _tools = [];
4410
+ _expressApp = null;
4332
4411
  constructor() {
4333
4412
  }
4334
4413
  // Factory function so we can async initialize the
@@ -4345,7 +4424,19 @@ var ExuluApp = class {
4345
4424
  ...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
4346
4425
  ];
4347
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;
4348
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
+ }
4349
4440
  embedder(id) {
4350
4441
  return this._embedders.find((x) => x.id === id);
4351
4442
  }
@@ -4391,7 +4482,11 @@ var ExuluApp = class {
4391
4482
  };
4392
4483
  server = {
4393
4484
  express: {
4394
- init: async (app) => {
4485
+ init: async () => {
4486
+ if (!this._expressApp) {
4487
+ throw new Error("Express app not initialized");
4488
+ }
4489
+ const app = this._expressApp;
4395
4490
  await createExpressRoutes(
4396
4491
  app,
4397
4492
  this._agents,
@@ -5637,6 +5732,10 @@ var nav = [
5637
5732
  label: "Agents",
5638
5733
  value: "agents"
5639
5734
  },
5735
+ {
5736
+ label: "Start Claude Code",
5737
+ value: "claude-code"
5738
+ },
5640
5739
  {
5641
5740
  label: "Exit",
5642
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.10",
4
+ "version": "0.3.12",
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",