@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 +129 -43
- package/dist/index.d.cts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.js +129 -43
- package/package.json +4 -1
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
|
|
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.
|
|
1801
|
+
table.text("name");
|
|
1815
1802
|
table.text("description");
|
|
1816
|
-
table.
|
|
1803
|
+
table.text("tags");
|
|
1817
1804
|
table.boolean("archived").defaultTo(false);
|
|
1818
|
-
table.string("external_id",
|
|
1805
|
+
table.string("external_id", 255);
|
|
1819
1806
|
table.integer("textLength");
|
|
1820
|
-
table.
|
|
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:
|
|
4254
|
-
this.express =
|
|
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
|
-
"
|
|
4322
|
+
"getAgents",
|
|
4264
4323
|
{
|
|
4265
|
-
title: "
|
|
4266
|
-
description: "
|
|
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 (
|
|
4270
|
-
content:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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<
|
|
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<
|
|
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
|
|
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.
|
|
1757
|
+
table.text("name");
|
|
1771
1758
|
table.text("description");
|
|
1772
|
-
table.
|
|
1759
|
+
table.text("tags");
|
|
1773
1760
|
table.boolean("archived").defaultTo(false);
|
|
1774
|
-
table.string("external_id",
|
|
1761
|
+
table.string("external_id", 255);
|
|
1775
1762
|
table.integer("textLength");
|
|
1776
|
-
table.
|
|
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:
|
|
4210
|
-
this.express =
|
|
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
|
-
"
|
|
4278
|
+
"getAgents",
|
|
4220
4279
|
{
|
|
4221
|
-
title: "
|
|
4222
|
-
description: "
|
|
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 (
|
|
4226
|
-
content:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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.
|
|
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",
|