@exulu/backend 1.36.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/dist/index.cjs +279 -128
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +279 -128
- package/package.json +3 -2
- package/types/models/context.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -687,25 +687,11 @@ var requestValidators = {
|
|
|
687
687
|
message: "Missing body."
|
|
688
688
|
};
|
|
689
689
|
}
|
|
690
|
-
if (!req.
|
|
690
|
+
if (!req.body.message && !req.body.messages) {
|
|
691
691
|
return {
|
|
692
692
|
error: true,
|
|
693
693
|
code: 400,
|
|
694
|
-
message: 'Missing "
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
if (!req.headers["session"]) {
|
|
698
|
-
return {
|
|
699
|
-
error: true,
|
|
700
|
-
code: 400,
|
|
701
|
-
message: 'Missing "session" property in headers.'
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
if (!req.body.message) {
|
|
705
|
-
return {
|
|
706
|
-
error: true,
|
|
707
|
-
code: 400,
|
|
708
|
-
message: 'Missing "message" property in body.'
|
|
694
|
+
message: 'Missing "message" or "messages" property in body.'
|
|
709
695
|
};
|
|
710
696
|
}
|
|
711
697
|
return {
|
|
@@ -737,6 +723,12 @@ var agentMessagesSchema = {
|
|
|
737
723
|
name: "user",
|
|
738
724
|
type: "number"
|
|
739
725
|
},
|
|
726
|
+
{
|
|
727
|
+
name: "message_id",
|
|
728
|
+
type: "text",
|
|
729
|
+
index: true,
|
|
730
|
+
unique: true
|
|
731
|
+
},
|
|
740
732
|
{
|
|
741
733
|
name: "session",
|
|
742
734
|
type: "text"
|
|
@@ -2371,9 +2363,11 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2371
2363
|
const name = args.field?.replace("_s3key", "");
|
|
2372
2364
|
console.log("[EXULU] name", name);
|
|
2373
2365
|
console.log("[EXULU] fields", exists.fields.map((field2) => field2.name));
|
|
2374
|
-
const field = exists.fields.find((field2) =>
|
|
2366
|
+
const field = exists.fields.find((field2) => {
|
|
2367
|
+
return field2.name.replace("_s3key", "") === name;
|
|
2368
|
+
});
|
|
2375
2369
|
if (!field) {
|
|
2376
|
-
throw new Error(`Field ${name} not found in context ${exists.id}.`);
|
|
2370
|
+
throw new Error(`Field ${name} not found in context ${exists.id}].`);
|
|
2377
2371
|
}
|
|
2378
2372
|
if (!field.processor) {
|
|
2379
2373
|
throw new Error(`Processor not set for field ${args.field} in context ${exists.id}.`);
|
|
@@ -2448,7 +2442,8 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2448
2442
|
item,
|
|
2449
2443
|
config,
|
|
2450
2444
|
context.user.id,
|
|
2451
|
-
context.user.role?.id
|
|
2445
|
+
context.user.role?.id,
|
|
2446
|
+
item.external_id || item.id ? true : false
|
|
2452
2447
|
);
|
|
2453
2448
|
if (job) {
|
|
2454
2449
|
jobs.push(job);
|
|
@@ -2535,22 +2530,30 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2535
2530
|
if (!id) {
|
|
2536
2531
|
throw new Error(`Context ${table.id} not found.`);
|
|
2537
2532
|
}
|
|
2538
|
-
let query = db3.from(getTableName(id)).select("id");
|
|
2539
2533
|
if (args.where) {
|
|
2534
|
+
let query = db3.from(getTableName(id)).select("id");
|
|
2540
2535
|
query = applyFilters(query, args.where, table);
|
|
2536
|
+
const items = await query;
|
|
2537
|
+
if (items.length === 0) {
|
|
2538
|
+
throw new Error("No items found to delete chunks for.");
|
|
2539
|
+
}
|
|
2540
|
+
for (const item of items) {
|
|
2541
|
+
await db3.from(getChunksTableName(id)).where({ source: item.id }).delete();
|
|
2542
|
+
}
|
|
2543
|
+
return {
|
|
2544
|
+
message: "Chunks deleted successfully.",
|
|
2545
|
+
items: items.length,
|
|
2546
|
+
jobs: []
|
|
2547
|
+
};
|
|
2548
|
+
} else {
|
|
2549
|
+
const count = await db3.from(getChunksTableName(id)).count();
|
|
2550
|
+
await db3.from(getChunksTableName(id)).truncate();
|
|
2551
|
+
return {
|
|
2552
|
+
message: "Chunks deleted successfully.",
|
|
2553
|
+
items: parseInt(count[0].count),
|
|
2554
|
+
jobs: []
|
|
2555
|
+
};
|
|
2541
2556
|
}
|
|
2542
|
-
const items = await query;
|
|
2543
|
-
if (items.length === 0) {
|
|
2544
|
-
throw new Error("No items found to delete chunks for.");
|
|
2545
|
-
}
|
|
2546
|
-
for (const item of items) {
|
|
2547
|
-
await db3.from(getChunksTableName(id)).where({ source: item.id }).delete();
|
|
2548
|
-
}
|
|
2549
|
-
return {
|
|
2550
|
-
message: "Chunks deleted successfully.",
|
|
2551
|
-
items: items.length,
|
|
2552
|
-
jobs: []
|
|
2553
|
-
};
|
|
2554
2557
|
};
|
|
2555
2558
|
}
|
|
2556
2559
|
return mutations;
|
|
@@ -2825,6 +2828,13 @@ var postprocessDeletion = async ({
|
|
|
2825
2828
|
}
|
|
2826
2829
|
return result;
|
|
2827
2830
|
}
|
|
2831
|
+
if (table.type === "agent_sessions") {
|
|
2832
|
+
if (!result.id) {
|
|
2833
|
+
return result;
|
|
2834
|
+
}
|
|
2835
|
+
const { db: db3 } = await postgresClient();
|
|
2836
|
+
await db3.from("agent_messages").where({ session: result.id }).where({ session: result.id }).delete();
|
|
2837
|
+
}
|
|
2828
2838
|
}
|
|
2829
2839
|
return result;
|
|
2830
2840
|
};
|
|
@@ -3148,7 +3158,7 @@ var vectorSearch = async ({
|
|
|
3148
3158
|
items = await itemsQuery;
|
|
3149
3159
|
break;
|
|
3150
3160
|
case "hybridSearch":
|
|
3151
|
-
const matchCount = Math.min(limit * 5,
|
|
3161
|
+
const matchCount = Math.min(limit * 5, 100);
|
|
3152
3162
|
const fullTextWeight = 1;
|
|
3153
3163
|
const semanticWeight = 1;
|
|
3154
3164
|
const rrfK = 50;
|
|
@@ -3175,7 +3185,7 @@ var vectorSearch = async ({
|
|
|
3175
3185
|
FROM ${chunksTable} c
|
|
3176
3186
|
WHERE c.embedding IS NOT NULL
|
|
3177
3187
|
ORDER BY rank_ix
|
|
3178
|
-
LIMIT LEAST(?,
|
|
3188
|
+
LIMIT LEAST(?, 50) * 2
|
|
3179
3189
|
)
|
|
3180
3190
|
SELECT
|
|
3181
3191
|
m.*,
|
|
@@ -3183,6 +3193,7 @@ var vectorSearch = async ({
|
|
|
3183
3193
|
c.source,
|
|
3184
3194
|
c.content,
|
|
3185
3195
|
c.chunk_index,
|
|
3196
|
+
c.metadata,
|
|
3186
3197
|
c."createdAt" AS chunk_created_at,
|
|
3187
3198
|
c."updatedAt" AS chunk_updated_at,
|
|
3188
3199
|
vector_dims(c.embedding) as embedding_size,
|
|
@@ -3206,7 +3217,7 @@ var vectorSearch = async ({
|
|
|
3206
3217
|
JOIN ${mainTable} m
|
|
3207
3218
|
ON m.id = c.source
|
|
3208
3219
|
ORDER BY hybrid_score DESC
|
|
3209
|
-
LIMIT LEAST(?,
|
|
3220
|
+
LIMIT LEAST(?, 50)
|
|
3210
3221
|
OFFSET 0
|
|
3211
3222
|
`;
|
|
3212
3223
|
const bindings = [
|
|
@@ -3232,6 +3243,7 @@ var vectorSearch = async ({
|
|
|
3232
3243
|
];
|
|
3233
3244
|
items = await db3.raw(hybridSQL, bindings).then((r) => r.rows ?? r);
|
|
3234
3245
|
}
|
|
3246
|
+
console.log("[EXULU] Vector search results:", items?.length);
|
|
3235
3247
|
const seenSources = /* @__PURE__ */ new Map();
|
|
3236
3248
|
items = items.reduce((acc, item) => {
|
|
3237
3249
|
if (!seenSources.has(item.source)) {
|
|
@@ -3249,6 +3261,7 @@ var vectorSearch = async ({
|
|
|
3249
3261
|
chunk_index: item.chunk_index,
|
|
3250
3262
|
chunk_id: item.chunk_id,
|
|
3251
3263
|
source: item.source,
|
|
3264
|
+
metadata: item.metadata,
|
|
3252
3265
|
chunk_created_at: item.chunk_created_at,
|
|
3253
3266
|
chunk_updated_at: item.chunk_updated_at,
|
|
3254
3267
|
embedding_size: item.embedding_size,
|
|
@@ -3265,6 +3278,7 @@ var vectorSearch = async ({
|
|
|
3265
3278
|
chunk_id: item.chunk_id,
|
|
3266
3279
|
chunk_created_at: item.chunk_created_at,
|
|
3267
3280
|
embedding_size: item.embedding_size,
|
|
3281
|
+
metadata: item.metadata,
|
|
3268
3282
|
source: item.source,
|
|
3269
3283
|
chunk_updated_at: item.chunk_updated_at,
|
|
3270
3284
|
...method === "cosineDistance" && { cosine_distance: item.cosine_distance },
|
|
@@ -3274,6 +3288,7 @@ var vectorSearch = async ({
|
|
|
3274
3288
|
}
|
|
3275
3289
|
return acc;
|
|
3276
3290
|
}, []);
|
|
3291
|
+
console.log("[EXULU] Vector search results after deduplication:", items?.length);
|
|
3277
3292
|
items.forEach((item) => {
|
|
3278
3293
|
if (!item.chunks?.length) {
|
|
3279
3294
|
return;
|
|
@@ -3305,7 +3320,7 @@ var vectorSearch = async ({
|
|
|
3305
3320
|
if (resultReranker && query) {
|
|
3306
3321
|
items = await resultReranker(items);
|
|
3307
3322
|
}
|
|
3308
|
-
|
|
3323
|
+
console.log("[EXULU] Vector search results after slicing:", items?.length);
|
|
3309
3324
|
await updateStatistic({
|
|
3310
3325
|
name: "count",
|
|
3311
3326
|
label: table.name.singular,
|
|
@@ -3967,6 +3982,10 @@ type PageInfo {
|
|
|
3967
3982
|
}
|
|
3968
3983
|
};
|
|
3969
3984
|
}));
|
|
3985
|
+
let embedderQueue = void 0;
|
|
3986
|
+
if (data.embedder?.queue) {
|
|
3987
|
+
embedderQueue = await data.embedder.queue;
|
|
3988
|
+
}
|
|
3970
3989
|
const clean = {
|
|
3971
3990
|
id: data.id,
|
|
3972
3991
|
name: data.name,
|
|
@@ -3974,7 +3993,8 @@ type PageInfo {
|
|
|
3974
3993
|
embedder: data.embedder ? {
|
|
3975
3994
|
name: data.embedder.name,
|
|
3976
3995
|
id: data.embedder.id,
|
|
3977
|
-
config: data.embedder?.config || void 0
|
|
3996
|
+
config: data.embedder?.config || void 0,
|
|
3997
|
+
queue: embedderQueue?.queue.name || void 0
|
|
3978
3998
|
} : void 0,
|
|
3979
3999
|
slug: "/contexts/" + data.id,
|
|
3980
4000
|
active: data.active,
|
|
@@ -4161,6 +4181,7 @@ type ItemChunks {
|
|
|
4161
4181
|
chunk_created_at: Date
|
|
4162
4182
|
chunk_updated_at: Date
|
|
4163
4183
|
embedding_size: Float
|
|
4184
|
+
metadata: JSON
|
|
4164
4185
|
}
|
|
4165
4186
|
|
|
4166
4187
|
type Provider {
|
|
@@ -4201,6 +4222,7 @@ type Embedder {
|
|
|
4201
4222
|
name: String!
|
|
4202
4223
|
id: ID!
|
|
4203
4224
|
config: [EmbedderConfig!]
|
|
4225
|
+
queue: String
|
|
4204
4226
|
}
|
|
4205
4227
|
type EmbedderConfig {
|
|
4206
4228
|
name: String!
|
|
@@ -4392,10 +4414,21 @@ var getPresignedUrl = async (key, config) => {
|
|
|
4392
4414
|
if (!config.fileUploads) {
|
|
4393
4415
|
throw new Error("File uploads are not configured");
|
|
4394
4416
|
}
|
|
4417
|
+
let bucket = config.fileUploads.s3Bucket;
|
|
4418
|
+
if (key.includes("[bucket:")) {
|
|
4419
|
+
console.log("[EXULU] key includes [bucket:name]", key);
|
|
4420
|
+
bucket = key.split("[bucket:")[1]?.split("]")[0] || "";
|
|
4421
|
+
if (!bucket?.length) {
|
|
4422
|
+
throw new Error("Invalid key, does not contain a bucket name like '[bucket:name]'.");
|
|
4423
|
+
}
|
|
4424
|
+
key = key.split("]")[1] || "";
|
|
4425
|
+
console.log("[EXULU] bucket", bucket);
|
|
4426
|
+
console.log("[EXULU] key", key);
|
|
4427
|
+
}
|
|
4395
4428
|
const url = await getSignedUrl(
|
|
4396
4429
|
getS3Client(config),
|
|
4397
4430
|
new GetObjectCommand({
|
|
4398
|
-
Bucket:
|
|
4431
|
+
Bucket: bucket,
|
|
4399
4432
|
Key: key
|
|
4400
4433
|
}),
|
|
4401
4434
|
{ expiresIn }
|
|
@@ -4432,7 +4465,7 @@ var uploadFile = async (user, file, key, config, options = {}) => {
|
|
|
4432
4465
|
ContentLength: file.byteLength
|
|
4433
4466
|
});
|
|
4434
4467
|
await client2.send(command);
|
|
4435
|
-
return
|
|
4468
|
+
return fullKey;
|
|
4436
4469
|
};
|
|
4437
4470
|
var createUppyRoutes = async (app, config) => {
|
|
4438
4471
|
if (!config.fileUploads) {
|
|
@@ -4503,29 +4536,24 @@ var createUppyRoutes = async (app, config) => {
|
|
|
4503
4536
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
4504
4537
|
return;
|
|
4505
4538
|
}
|
|
4506
|
-
|
|
4539
|
+
let { key } = req.query;
|
|
4507
4540
|
if (typeof key !== "string" || key.trim() === "") {
|
|
4508
4541
|
res.status(400).json({ error: "Missing or invalid `key` query parameter." });
|
|
4509
4542
|
return;
|
|
4510
4543
|
}
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
return;
|
|
4521
|
-
}
|
|
4522
|
-
if (authenticationResult.user.type !== "api" && !key.includes(authenticationResult.user.id.toString())) {
|
|
4523
|
-
res.status(405).json({ error: "Not allowed to access the files in the folder based on authenticated user." });
|
|
4524
|
-
return;
|
|
4544
|
+
let bucket = config.fileUploads.s3Bucket;
|
|
4545
|
+
if (key.includes("[bucket:")) {
|
|
4546
|
+
console.log("[EXULU] key includes [bucket:name]", key);
|
|
4547
|
+
bucket = key.split("[bucket:")[1]?.split("]")[0] || "";
|
|
4548
|
+
if (!bucket?.length) {
|
|
4549
|
+
throw new Error("Invalid key, does not contain a bucket name like '[bucket:name]'.");
|
|
4550
|
+
}
|
|
4551
|
+
key = key.split("]")[1] || "";
|
|
4552
|
+
console.log("[EXULU] bucket", bucket);
|
|
4525
4553
|
}
|
|
4526
4554
|
const client2 = getS3Client(config);
|
|
4527
4555
|
const command = new DeleteObjectCommand({
|
|
4528
|
-
Bucket:
|
|
4556
|
+
Bucket: bucket,
|
|
4529
4557
|
Key: key
|
|
4530
4558
|
});
|
|
4531
4559
|
await client2.send(command);
|
|
@@ -4554,19 +4582,6 @@ var createUppyRoutes = async (app, config) => {
|
|
|
4554
4582
|
res.status(400).json({ error: "Missing or invalid `key` query parameter." });
|
|
4555
4583
|
return;
|
|
4556
4584
|
}
|
|
4557
|
-
const userPrefix = extractUserPrefix(key);
|
|
4558
|
-
if (!userPrefix) {
|
|
4559
|
-
res.status(405).json({ error: 'Invalid key, does not contain a user prefix like "<user_id>/<key>.' });
|
|
4560
|
-
return;
|
|
4561
|
-
}
|
|
4562
|
-
if (userPrefix !== authenticationResult.user.id.toString()) {
|
|
4563
|
-
res.status(405).json({ error: "Not allowed to access the files in the folder based on authenticated user." });
|
|
4564
|
-
return;
|
|
4565
|
-
}
|
|
4566
|
-
if (authenticationResult.user.type !== "api" && !key.includes(authenticationResult.user.id.toString())) {
|
|
4567
|
-
res.status(405).json({ error: "Not allowed to access the files in the folder based on authenticated user." });
|
|
4568
|
-
return;
|
|
4569
|
-
}
|
|
4570
4585
|
try {
|
|
4571
4586
|
const url = await getPresignedUrl(key, config);
|
|
4572
4587
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -4596,11 +4611,24 @@ var createUppyRoutes = async (app, config) => {
|
|
|
4596
4611
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
4597
4612
|
return;
|
|
4598
4613
|
}
|
|
4599
|
-
|
|
4614
|
+
let { key } = req.body;
|
|
4615
|
+
let bucket = config.fileUploads.s3Bucket;
|
|
4616
|
+
if (key.includes("[bucket:")) {
|
|
4617
|
+
console.log("[EXULU] key includes [bucket:name]", key);
|
|
4618
|
+
bucket = key.split("[bucket:")[1]?.split("]")[0] || "";
|
|
4619
|
+
console.log("[EXULU] bucket", bucket);
|
|
4620
|
+
if (!bucket?.length) {
|
|
4621
|
+
throw new Error("Invalid key, does not contain a bucket name like '[bucket:name]'.");
|
|
4622
|
+
}
|
|
4623
|
+
key = key.split("]")[1] || "";
|
|
4624
|
+
console.log("[EXULU] key", key);
|
|
4625
|
+
}
|
|
4600
4626
|
console.log("[EXULU] Getting object metadata from s3", key);
|
|
4627
|
+
console.log("[EXULU] bucket", bucket);
|
|
4628
|
+
console.log("[EXULU] key", key);
|
|
4601
4629
|
const client2 = getS3Client(config);
|
|
4602
4630
|
const command = new HeadObjectCommand({
|
|
4603
|
-
Bucket:
|
|
4631
|
+
Bucket: bucket,
|
|
4604
4632
|
Key: key
|
|
4605
4633
|
});
|
|
4606
4634
|
const response = await client2.send(command);
|
|
@@ -4918,7 +4946,7 @@ function sanitizeToolName(name) {
|
|
|
4918
4946
|
}
|
|
4919
4947
|
return sanitized;
|
|
4920
4948
|
}
|
|
4921
|
-
var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providerapikey, contexts, user, exuluConfig, sessionID) => {
|
|
4949
|
+
var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providerapikey, contexts, user, exuluConfig, sessionID, req) => {
|
|
4922
4950
|
if (!currentTools) return {};
|
|
4923
4951
|
if (!allExuluTools) return {};
|
|
4924
4952
|
if (!contexts) {
|
|
@@ -5005,6 +5033,7 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
|
|
|
5005
5033
|
const response = await cur.tool.execute({
|
|
5006
5034
|
...inputs,
|
|
5007
5035
|
sessionID,
|
|
5036
|
+
req,
|
|
5008
5037
|
// Convert config to object format if a config object
|
|
5009
5038
|
// is available, after we added the .value property
|
|
5010
5039
|
// by hydrating it from the variables table.
|
|
@@ -5014,6 +5043,7 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
|
|
|
5014
5043
|
user,
|
|
5015
5044
|
contexts: contextsMap,
|
|
5016
5045
|
upload,
|
|
5046
|
+
exuluConfig,
|
|
5017
5047
|
config: config ? config.config.reduce((acc, curr) => {
|
|
5018
5048
|
acc[curr.name] = curr.value;
|
|
5019
5049
|
return acc;
|
|
@@ -5235,6 +5265,7 @@ var ExuluAgent2 = class {
|
|
|
5235
5265
|
};
|
|
5236
5266
|
generateSync = async ({
|
|
5237
5267
|
prompt,
|
|
5268
|
+
req,
|
|
5238
5269
|
user,
|
|
5239
5270
|
session,
|
|
5240
5271
|
inputMessages,
|
|
@@ -5316,7 +5347,8 @@ var ExuluAgent2 = class {
|
|
|
5316
5347
|
contexts,
|
|
5317
5348
|
user,
|
|
5318
5349
|
exuluConfig,
|
|
5319
|
-
session
|
|
5350
|
+
session,
|
|
5351
|
+
req
|
|
5320
5352
|
),
|
|
5321
5353
|
stopWhen: [stepCountIs(2)]
|
|
5322
5354
|
});
|
|
@@ -5375,7 +5407,8 @@ var ExuluAgent2 = class {
|
|
|
5375
5407
|
contexts,
|
|
5376
5408
|
user,
|
|
5377
5409
|
exuluConfig,
|
|
5378
|
-
session
|
|
5410
|
+
session,
|
|
5411
|
+
req
|
|
5379
5412
|
),
|
|
5380
5413
|
stopWhen: [stepCountIs(2)]
|
|
5381
5414
|
});
|
|
@@ -5427,7 +5460,8 @@ var ExuluAgent2 = class {
|
|
|
5427
5460
|
providerapikey,
|
|
5428
5461
|
contexts,
|
|
5429
5462
|
exuluConfig,
|
|
5430
|
-
instructions
|
|
5463
|
+
instructions,
|
|
5464
|
+
req
|
|
5431
5465
|
}) => {
|
|
5432
5466
|
if (!this.model) {
|
|
5433
5467
|
console.error("[EXULU] Model is required for streaming.");
|
|
@@ -5450,7 +5484,7 @@ var ExuluAgent2 = class {
|
|
|
5450
5484
|
console.log("[EXULU] loading previous messages from session: " + session);
|
|
5451
5485
|
const previousMessages2 = await getAgentMessages({
|
|
5452
5486
|
session,
|
|
5453
|
-
user: user
|
|
5487
|
+
user: user?.id,
|
|
5454
5488
|
limit: 50,
|
|
5455
5489
|
page: 1
|
|
5456
5490
|
});
|
|
@@ -5489,7 +5523,8 @@ var ExuluAgent2 = class {
|
|
|
5489
5523
|
contexts,
|
|
5490
5524
|
user,
|
|
5491
5525
|
exuluConfig,
|
|
5492
|
-
session
|
|
5526
|
+
session,
|
|
5527
|
+
req
|
|
5493
5528
|
),
|
|
5494
5529
|
onError: (error) => {
|
|
5495
5530
|
console.error("[EXULU] chat stream error.", error);
|
|
@@ -5507,7 +5542,7 @@ var ExuluAgent2 = class {
|
|
|
5507
5542
|
var getAgentMessages = async ({ session, user, limit, page }) => {
|
|
5508
5543
|
const { db: db3 } = await postgresClient();
|
|
5509
5544
|
console.log("[EXULU] getting agent messages for session: " + session + " and user: " + user + " and page: " + page);
|
|
5510
|
-
const query = db3.from("agent_messages").where({ session, user }).limit(limit);
|
|
5545
|
+
const query = db3.from("agent_messages").where({ session, user: user || null }).limit(limit);
|
|
5511
5546
|
if (page > 0) {
|
|
5512
5547
|
query.offset((page - 1) * limit);
|
|
5513
5548
|
}
|
|
@@ -5526,12 +5561,15 @@ var getSession = async ({ sessionID }) => {
|
|
|
5526
5561
|
var saveChat = async ({ session, user, messages }) => {
|
|
5527
5562
|
const { db: db3 } = await postgresClient();
|
|
5528
5563
|
const promises = messages.map((message) => {
|
|
5529
|
-
|
|
5564
|
+
const mutation = db3.from("agent_messages").insert({
|
|
5530
5565
|
session,
|
|
5531
5566
|
user,
|
|
5532
5567
|
content: JSON.stringify(message),
|
|
5568
|
+
message_id: message.id,
|
|
5533
5569
|
title: message.role === "user" ? "User" : "Assistant"
|
|
5534
|
-
});
|
|
5570
|
+
}).returning("id");
|
|
5571
|
+
mutation.onConflict("message_id").merge();
|
|
5572
|
+
return mutation;
|
|
5535
5573
|
});
|
|
5536
5574
|
await Promise.all(promises);
|
|
5537
5575
|
};
|
|
@@ -5574,19 +5612,36 @@ var ExuluEmbedder = class {
|
|
|
5574
5612
|
});
|
|
5575
5613
|
for (const config of this.config || []) {
|
|
5576
5614
|
const name = config.name;
|
|
5615
|
+
const setting = variables.find((v) => v.name === name);
|
|
5616
|
+
if (!setting) {
|
|
5617
|
+
throw new Error("Setting value not found for embedder setting: " + name + ", for context: " + context + " and embedder: " + this.id + ". Make sure to set the value for this setting in the embedder settings.");
|
|
5618
|
+
}
|
|
5577
5619
|
const {
|
|
5578
5620
|
value: variableName,
|
|
5579
5621
|
id
|
|
5580
|
-
} =
|
|
5622
|
+
} = setting;
|
|
5581
5623
|
let value = "";
|
|
5582
5624
|
console.log("[EXULU] variable name", variableName);
|
|
5583
5625
|
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
5584
5626
|
if (!variable) {
|
|
5585
5627
|
throw new Error("Variable not found for embedder setting: " + name + " in context: " + context + " and embedder: " + this.id);
|
|
5586
5628
|
}
|
|
5629
|
+
console.log("[EXULU] variable", variable);
|
|
5587
5630
|
if (variable.encrypted) {
|
|
5588
|
-
|
|
5589
|
-
|
|
5631
|
+
if (!process.env.NEXTAUTH_SECRET) {
|
|
5632
|
+
throw new Error("NEXTAUTH_SECRET environment variable is not set, cannot decrypt variable: " + name);
|
|
5633
|
+
}
|
|
5634
|
+
try {
|
|
5635
|
+
const bytes = CryptoJS2.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
5636
|
+
const decrypted = bytes.toString(CryptoJS2.enc.Utf8);
|
|
5637
|
+
if (!decrypted) {
|
|
5638
|
+
throw new Error("Decryption returned empty string - invalid key or corrupted data");
|
|
5639
|
+
}
|
|
5640
|
+
value = decrypted;
|
|
5641
|
+
console.log("[EXULU] successfully decrypted value for", name);
|
|
5642
|
+
} catch (error) {
|
|
5643
|
+
throw new Error(`Failed to decrypt variable "${name}" for embedder setting in context "${context}": ${error instanceof Error ? error.message : "Unknown error"}. Verify that NEXTAUTH_SECRET matches the key used during encryption.`);
|
|
5644
|
+
}
|
|
5590
5645
|
} else {
|
|
5591
5646
|
value = variable.value;
|
|
5592
5647
|
}
|
|
@@ -5745,7 +5800,9 @@ var ExuluContext = class {
|
|
|
5745
5800
|
processField = async (trigger, user, role, item, config) => {
|
|
5746
5801
|
console.log("[EXULU] processing field", item.field, " in context", this.id);
|
|
5747
5802
|
console.log("[EXULU] fields", this.fields.map((field2) => field2.name));
|
|
5748
|
-
const field = this.fields.find((field2) =>
|
|
5803
|
+
const field = this.fields.find((field2) => {
|
|
5804
|
+
return field2.name.replace("_s3key", "") === item.field.replace("_s3key", "");
|
|
5805
|
+
});
|
|
5749
5806
|
if (!field || !field.processor) {
|
|
5750
5807
|
console.error("[EXULU] field not found or processor not set for field", item.field, " in context", this.id);
|
|
5751
5808
|
throw new Error("Field not found or processor not set for field " + item.field + " in context " + this.id);
|
|
@@ -5755,7 +5812,7 @@ var ExuluContext = class {
|
|
|
5755
5812
|
if (queue?.queue.name) {
|
|
5756
5813
|
console.log("[EXULU] processor is in queue mode, scheduling job.");
|
|
5757
5814
|
const job = await bullmqDecorator({
|
|
5758
|
-
timeoutInSeconds: field.processor?.config?.timeoutInSeconds ||
|
|
5815
|
+
timeoutInSeconds: field.processor?.config?.timeoutInSeconds || 600,
|
|
5759
5816
|
label: `${this.name} ${field.name} data processor`,
|
|
5760
5817
|
processor: `${this.id}-${field.name}`,
|
|
5761
5818
|
context: this.id,
|
|
@@ -5846,6 +5903,7 @@ var ExuluContext = class {
|
|
|
5846
5903
|
if (chunks?.length) {
|
|
5847
5904
|
await db3.from(getChunksTableName(this.id)).insert(chunks.map((chunk) => ({
|
|
5848
5905
|
source,
|
|
5906
|
+
metadata: chunk.metadata,
|
|
5849
5907
|
content: chunk.content,
|
|
5850
5908
|
chunk_index: chunk.index,
|
|
5851
5909
|
embedding: pgvector2.toSql(chunk.vector)
|
|
@@ -5874,15 +5932,27 @@ var ExuluContext = class {
|
|
|
5874
5932
|
}
|
|
5875
5933
|
).returning("id");
|
|
5876
5934
|
if (upsert) {
|
|
5877
|
-
|
|
5935
|
+
if (item.external_id) {
|
|
5936
|
+
mutation.onConflict("external_id").merge();
|
|
5937
|
+
} else if (item.id) {
|
|
5938
|
+
mutation.onConflict("id").merge();
|
|
5939
|
+
} else {
|
|
5940
|
+
throw new Error("Either id or external_id must be provided for upsert");
|
|
5941
|
+
}
|
|
5878
5942
|
}
|
|
5879
5943
|
const results = await mutation;
|
|
5880
5944
|
if (!results[0]) {
|
|
5881
5945
|
throw new Error("Failed to create item.");
|
|
5882
5946
|
}
|
|
5947
|
+
console.log("[EXULU] context configuration", this.configuration);
|
|
5883
5948
|
if (this.embedder && (this.configuration.calculateVectors === "onUpdate" || this.configuration.calculateVectors === "always")) {
|
|
5949
|
+
console.log("[EXULU] generating embeddings for item", results[0].id);
|
|
5884
5950
|
const { job } = await this.embeddings.generate.one({
|
|
5885
|
-
item:
|
|
5951
|
+
item: {
|
|
5952
|
+
...item,
|
|
5953
|
+
// important we need to full record here with all fields for the embedder
|
|
5954
|
+
id: results[0].id
|
|
5955
|
+
},
|
|
5886
5956
|
user,
|
|
5887
5957
|
role,
|
|
5888
5958
|
trigger: "api",
|
|
@@ -5925,7 +5995,7 @@ var ExuluContext = class {
|
|
|
5925
5995
|
if (this.embedder && (this.configuration.calculateVectors === "onUpdate" || this.configuration.calculateVectors === "always")) {
|
|
5926
5996
|
const { job } = await this.embeddings.generate.one({
|
|
5927
5997
|
item: record,
|
|
5928
|
-
// important we need to full record here with all fields
|
|
5998
|
+
// important we need to full record here with all fields for the embedder
|
|
5929
5999
|
user,
|
|
5930
6000
|
role,
|
|
5931
6001
|
trigger: "api",
|
|
@@ -5942,10 +6012,13 @@ var ExuluContext = class {
|
|
|
5942
6012
|
};
|
|
5943
6013
|
};
|
|
5944
6014
|
deleteItem = async (item, user, role) => {
|
|
5945
|
-
if (!item.id) {
|
|
5946
|
-
throw new Error("Item id is required for deleting item.");
|
|
5947
|
-
}
|
|
5948
6015
|
const { db: db3 } = await postgresClient();
|
|
6016
|
+
if (!item.id?.length && item?.external_id) {
|
|
6017
|
+
item = await db3.from(getTableName(this.id)).where({ external_id: item.external_id }).first();
|
|
6018
|
+
if (!item || !item.id) {
|
|
6019
|
+
throw new Error(`Item not found for external id ${item?.external_id || "undefined"}.`);
|
|
6020
|
+
}
|
|
6021
|
+
}
|
|
5949
6022
|
await db3.from(getTableName(this.id)).where({ id: item.id }).delete();
|
|
5950
6023
|
if (!this.embedder) {
|
|
5951
6024
|
return {
|
|
@@ -6050,14 +6123,13 @@ var ExuluContext = class {
|
|
|
6050
6123
|
table.text("description");
|
|
6051
6124
|
table.text("tags");
|
|
6052
6125
|
table.boolean("archived").defaultTo(false);
|
|
6053
|
-
table.text("external_id");
|
|
6126
|
+
table.text("external_id").unique();
|
|
6054
6127
|
table.text("created_by");
|
|
6055
6128
|
table.text("ttl");
|
|
6056
6129
|
table.text("rights_mode").defaultTo(this.configuration?.defaultRightsMode ?? "private");
|
|
6057
6130
|
table.integer("textlength");
|
|
6058
6131
|
table.text("source");
|
|
6059
6132
|
table.timestamp("embeddings_updated_at");
|
|
6060
|
-
table.unique(["id", "external_id"]);
|
|
6061
6133
|
for (const field of this.fields) {
|
|
6062
6134
|
let { type, name, unique } = field;
|
|
6063
6135
|
if (!type || !name) {
|
|
@@ -6120,7 +6192,7 @@ var ExuluContext = class {
|
|
|
6120
6192
|
const { db: db3 } = await postgresClient();
|
|
6121
6193
|
const result = await vectorSearch({
|
|
6122
6194
|
page: 1,
|
|
6123
|
-
limit:
|
|
6195
|
+
limit: 50,
|
|
6124
6196
|
query,
|
|
6125
6197
|
filters: [],
|
|
6126
6198
|
user,
|
|
@@ -6148,7 +6220,6 @@ var ExuluContext = class {
|
|
|
6148
6220
|
};
|
|
6149
6221
|
};
|
|
6150
6222
|
var updateStatistic = async (statistic) => {
|
|
6151
|
-
console.log("[EXULU] updating statistic", statistic);
|
|
6152
6223
|
const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
6153
6224
|
const { db: db3 } = await postgresClient();
|
|
6154
6225
|
const existing = await db3.from("tracking").where({
|
|
@@ -6273,6 +6344,7 @@ var CLAUDE_MESSAGES = {
|
|
|
6273
6344
|
|
|
6274
6345
|
// src/registry/routes.ts
|
|
6275
6346
|
import { createIdGenerator } from "ai";
|
|
6347
|
+
import cookieParser from "cookie-parser";
|
|
6276
6348
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
6277
6349
|
var global_queues = {
|
|
6278
6350
|
eval_runs: "eval_runs"
|
|
@@ -6309,6 +6381,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
|
|
|
6309
6381
|
app.use(cors(corsOptions));
|
|
6310
6382
|
app.use(bodyParser.urlencoded({ extended: true, limit: REQUEST_SIZE_LIMIT }));
|
|
6311
6383
|
app.use(bodyParser.json({ limit: REQUEST_SIZE_LIMIT }));
|
|
6384
|
+
app.use(cookieParser());
|
|
6312
6385
|
console.log(`
|
|
6313
6386
|
\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
|
|
6314
6387
|
\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
|
|
@@ -6530,8 +6603,9 @@ Mood: friendly and intelligent.
|
|
|
6530
6603
|
res.status(requestValidationResult.code || 500).json({ detail: `${requestValidationResult.message}` });
|
|
6531
6604
|
return;
|
|
6532
6605
|
}
|
|
6606
|
+
console.log("[EXULU] agentInstance.rights_mode", agentInstance.rights_mode);
|
|
6533
6607
|
const authenticationResult = await requestValidators.authenticate(req);
|
|
6534
|
-
if (!authenticationResult.user?.id) {
|
|
6608
|
+
if (!authenticationResult.user?.id && agentInstance.rights_mode !== "public") {
|
|
6535
6609
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
6536
6610
|
return;
|
|
6537
6611
|
}
|
|
@@ -6555,7 +6629,7 @@ Mood: friendly and intelligent.
|
|
|
6555
6629
|
return;
|
|
6556
6630
|
}
|
|
6557
6631
|
}
|
|
6558
|
-
if (user
|
|
6632
|
+
if (user?.type !== "api" && !user?.super_admin && req.body.resourceId !== user?.id) {
|
|
6559
6633
|
res.status(400).json({
|
|
6560
6634
|
message: "The provided user id in the resourceId field is not the same as the authenticated user. Only super admins and API users can impersonate other users."
|
|
6561
6635
|
});
|
|
@@ -6576,7 +6650,6 @@ Mood: friendly and intelligent.
|
|
|
6576
6650
|
return;
|
|
6577
6651
|
}
|
|
6578
6652
|
providerapikey = variable.value;
|
|
6579
|
-
console.log("[EXULU] encrypted value", providerapikey);
|
|
6580
6653
|
if (!variable.encrypted) {
|
|
6581
6654
|
res.status(400).json({
|
|
6582
6655
|
message: "Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys."
|
|
@@ -6586,7 +6659,6 @@ Mood: friendly and intelligent.
|
|
|
6586
6659
|
if (variable.encrypted) {
|
|
6587
6660
|
const bytes = CryptoJS3.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
6588
6661
|
providerapikey = bytes.toString(CryptoJS3.enc.Utf8);
|
|
6589
|
-
console.log("[EXULU] decrypted value", providerapikey);
|
|
6590
6662
|
}
|
|
6591
6663
|
}
|
|
6592
6664
|
if (!!headers.stream) {
|
|
@@ -6594,17 +6666,27 @@ Mood: friendly and intelligent.
|
|
|
6594
6666
|
label: agent.name,
|
|
6595
6667
|
trigger: "agent"
|
|
6596
6668
|
};
|
|
6669
|
+
let previousMessages = [];
|
|
6670
|
+
let message;
|
|
6671
|
+
if (!req.body.message && !headers.session && req.body.messages) {
|
|
6672
|
+
message = req.body.messages[req.body.messages.length - 1];
|
|
6673
|
+
previousMessages = req.body.messages.slice(0, -1);
|
|
6674
|
+
} else {
|
|
6675
|
+
message = req.body.message;
|
|
6676
|
+
}
|
|
6597
6677
|
const result = await agent.generateStream({
|
|
6598
6678
|
contexts,
|
|
6599
6679
|
user,
|
|
6600
6680
|
instructions: agentInstance.instructions,
|
|
6601
6681
|
session: headers.session,
|
|
6602
|
-
message
|
|
6682
|
+
message,
|
|
6683
|
+
previousMessages,
|
|
6603
6684
|
currentTools: enabledTools,
|
|
6604
6685
|
allExuluTools: tools,
|
|
6605
6686
|
providerapikey,
|
|
6606
6687
|
toolConfigs: agentInstance.tools,
|
|
6607
|
-
exuluConfig: config
|
|
6688
|
+
exuluConfig: config,
|
|
6689
|
+
req
|
|
6608
6690
|
});
|
|
6609
6691
|
result.stream.consumeStream();
|
|
6610
6692
|
result.stream.pipeUIMessageStreamToResponse(res, {
|
|
@@ -6631,11 +6713,12 @@ Mood: friendly and intelligent.
|
|
|
6631
6713
|
size: 16
|
|
6632
6714
|
}),
|
|
6633
6715
|
onFinish: async ({ messages, isContinuation, isAborted, responseMessage }) => {
|
|
6634
|
-
|
|
6716
|
+
console.log("[EXULU] onFinish", messages?.map((msg) => msg.parts?.map((part) => part.type === "text" ? part.text : null)).join("\n"));
|
|
6717
|
+
if (headers.session && user?.id) {
|
|
6635
6718
|
await saveChat({
|
|
6636
6719
|
session: headers.session,
|
|
6637
6720
|
user: user.id,
|
|
6638
|
-
messages
|
|
6721
|
+
messages
|
|
6639
6722
|
});
|
|
6640
6723
|
}
|
|
6641
6724
|
const metadata = messages[messages.length - 1]?.metadata;
|
|
@@ -6652,7 +6735,7 @@ Mood: friendly and intelligent.
|
|
|
6652
6735
|
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
6653
6736
|
trigger: statistics.trigger,
|
|
6654
6737
|
count: 1,
|
|
6655
|
-
user: user
|
|
6738
|
+
user: user?.id,
|
|
6656
6739
|
role: user?.role?.id
|
|
6657
6740
|
}),
|
|
6658
6741
|
...metadata?.inputTokens ? [
|
|
@@ -6662,7 +6745,7 @@ Mood: friendly and intelligent.
|
|
|
6662
6745
|
type: STATISTICS_TYPE_ENUM.AGENT_RUN,
|
|
6663
6746
|
trigger: statistics.trigger,
|
|
6664
6747
|
count: metadata?.inputTokens,
|
|
6665
|
-
user: user
|
|
6748
|
+
user: user?.id,
|
|
6666
6749
|
role: user?.role?.id
|
|
6667
6750
|
})
|
|
6668
6751
|
] : [],
|
|
@@ -6683,6 +6766,7 @@ Mood: friendly and intelligent.
|
|
|
6683
6766
|
} else {
|
|
6684
6767
|
const response = await agent.generateSync({
|
|
6685
6768
|
user,
|
|
6769
|
+
req,
|
|
6686
6770
|
instructions: agentInstance.instructions,
|
|
6687
6771
|
session: headers.session,
|
|
6688
6772
|
inputMessages: [req.body.message],
|
|
@@ -7021,7 +7105,7 @@ var createWorkers = async (agents, queues2, config, contexts, evals, tools, trac
|
|
|
7021
7105
|
}));
|
|
7022
7106
|
const { db: db3 } = await postgresClient();
|
|
7023
7107
|
const data = bullmqJob.data;
|
|
7024
|
-
const timeoutInSeconds = data.timeoutInSeconds ||
|
|
7108
|
+
const timeoutInSeconds = data.timeoutInSeconds || 600;
|
|
7025
7109
|
const timeoutMs = timeoutInSeconds * 1e3;
|
|
7026
7110
|
const timeoutPromise = new Promise((_, reject) => {
|
|
7027
7111
|
setTimeout(() => {
|
|
@@ -7075,7 +7159,9 @@ var createWorkers = async (agents, queues2, config, contexts, evals, tools, trac
|
|
|
7075
7159
|
if (!context) {
|
|
7076
7160
|
throw new Error(`Context ${data.context} not found in the registry.`);
|
|
7077
7161
|
}
|
|
7078
|
-
const field = context.fields.find((field2) =>
|
|
7162
|
+
const field = context.fields.find((field2) => {
|
|
7163
|
+
return field2.name.replace("_s3key", "") === data.inputs.field.replace("_s3key", "");
|
|
7164
|
+
});
|
|
7079
7165
|
if (!field) {
|
|
7080
7166
|
throw new Error(`Field ${data.inputs.field} not found in the context ${data.context}.`);
|
|
7081
7167
|
}
|
|
@@ -7350,7 +7436,13 @@ var createWorkers = async (agents, queues2, config, contexts, evals, tools, trac
|
|
|
7350
7436
|
let jobs = [];
|
|
7351
7437
|
let items = [];
|
|
7352
7438
|
for (const item of result) {
|
|
7353
|
-
const { item: createdItem, job } = await context.createItem(
|
|
7439
|
+
const { item: createdItem, job } = await context.createItem(
|
|
7440
|
+
item,
|
|
7441
|
+
config,
|
|
7442
|
+
data.user,
|
|
7443
|
+
data.role,
|
|
7444
|
+
item.external_id || item.id ? true : false
|
|
7445
|
+
);
|
|
7354
7446
|
if (job) {
|
|
7355
7447
|
jobs.push(job);
|
|
7356
7448
|
console.log(`[EXULU] Scheduled job through source update job for item ${createdItem.id} (Job ID: ${job})`, logMetadata2(bullmqJob.name, {
|
|
@@ -7404,14 +7496,12 @@ var createWorkers = async (agents, queues2, config, contexts, evals, tools, trac
|
|
|
7404
7496
|
}
|
|
7405
7497
|
);
|
|
7406
7498
|
worker.on("completed", async (job, returnvalue) => {
|
|
7407
|
-
console.log(`[EXULU] completed job ${job.id}.`,
|
|
7408
|
-
result: returnvalue
|
|
7409
|
-
}));
|
|
7499
|
+
console.log(`[EXULU] completed job ${job.id}.`, returnvalue);
|
|
7410
7500
|
const { db: db3 } = await postgresClient();
|
|
7411
7501
|
await db3.from("job_results").where({ job_id: job.id }).update({
|
|
7412
7502
|
state: JOB_STATUS_ENUM.completed,
|
|
7413
|
-
result: returnvalue.result,
|
|
7414
|
-
metadata: returnvalue.metadata
|
|
7503
|
+
result: returnvalue.result ? JSON.stringify(returnvalue.result) : null,
|
|
7504
|
+
metadata: returnvalue.metadata ? JSON.stringify(returnvalue.metadata) : null
|
|
7415
7505
|
});
|
|
7416
7506
|
});
|
|
7417
7507
|
worker.on("failed", async (job, error, prev) => {
|
|
@@ -8095,7 +8185,6 @@ var claudeSonnet45Agent = new ExuluAgent2({
|
|
|
8095
8185
|
|
|
8096
8186
|
// src/templates/agents/google/vertex/index.ts
|
|
8097
8187
|
import { createVertex } from "@ai-sdk/google-vertex";
|
|
8098
|
-
import "@ai-sdk/google-vertex";
|
|
8099
8188
|
var vertexAuthenticationInformation = `
|
|
8100
8189
|
### Vertex Authentication Setup (Google Auth)
|
|
8101
8190
|
|
|
@@ -8150,7 +8239,6 @@ var vertexGemini25FlashAgent = new ExuluAgent2({
|
|
|
8150
8239
|
instructions: "",
|
|
8151
8240
|
model: {
|
|
8152
8241
|
create: ({ apiKey }) => {
|
|
8153
|
-
console.log("[EXULU] apiKey", apiKey);
|
|
8154
8242
|
if (!apiKey) {
|
|
8155
8243
|
throw new Error("Auth credentials not found for Google Vertex agent, make sure you have set the provider api key to a valid google authentication json.");
|
|
8156
8244
|
}
|
|
@@ -8161,8 +8249,45 @@ var vertexGemini25FlashAgent = new ExuluAgent2({
|
|
|
8161
8249
|
if (!googleAuthPayload.location) {
|
|
8162
8250
|
throw new Error("Location not set in authentication json for Google Vertex Gemini 2.5 Flash agent, should be for example 'europe-west1'");
|
|
8163
8251
|
}
|
|
8164
|
-
const
|
|
8165
|
-
const model =
|
|
8252
|
+
const vertex = createVertex(googleAuthPayload);
|
|
8253
|
+
const model = vertex("gemini-2.5-flash");
|
|
8254
|
+
return model;
|
|
8255
|
+
}
|
|
8256
|
+
}
|
|
8257
|
+
}
|
|
8258
|
+
});
|
|
8259
|
+
var vertexGemini20FlashAgent = new ExuluAgent2({
|
|
8260
|
+
id: `default_vertex_gemini_2_0_flash_agent`,
|
|
8261
|
+
name: `GEMINI-2.0-FLASH`,
|
|
8262
|
+
provider: "vertex",
|
|
8263
|
+
description: `Google Vertex Gemini 2.0 Flash model. High intelligence and capability. Moderately Fast.`,
|
|
8264
|
+
type: "agent",
|
|
8265
|
+
capabilities: {
|
|
8266
|
+
text: true,
|
|
8267
|
+
images: [".png", ".jpg", ".jpeg", ".webp"],
|
|
8268
|
+
files: [".pdf", ".txt"],
|
|
8269
|
+
audio: [".mpeg", ".mp3", ".m4a", ".wav", ".mp4"],
|
|
8270
|
+
video: [".mp4", ".mpeg"]
|
|
8271
|
+
},
|
|
8272
|
+
authenticationInformation: vertexAuthenticationInformation,
|
|
8273
|
+
maxContextLength: 1048576,
|
|
8274
|
+
config: {
|
|
8275
|
+
name: `GEMINI-2.0-FLASH`,
|
|
8276
|
+
instructions: "",
|
|
8277
|
+
model: {
|
|
8278
|
+
create: ({ apiKey }) => {
|
|
8279
|
+
if (!apiKey) {
|
|
8280
|
+
throw new Error("Auth credentials not found for Google Vertex agent, make sure you have set the provider api key to a valid google authentication json.");
|
|
8281
|
+
}
|
|
8282
|
+
const googleAuthPayload = JSON.parse(apiKey || "{}");
|
|
8283
|
+
if (!googleAuthPayload) {
|
|
8284
|
+
throw new Error("API key not found for Google Vertex Gemini 2.0 Flash agent.");
|
|
8285
|
+
}
|
|
8286
|
+
if (!googleAuthPayload.location) {
|
|
8287
|
+
throw new Error("Location not set in authentication json for Google Vertex Gemini 2.0 Flash agent, should be for example 'europe-west1'");
|
|
8288
|
+
}
|
|
8289
|
+
const vertex = createVertex(googleAuthPayload);
|
|
8290
|
+
const model = vertex("gemini-2.0-flash");
|
|
8166
8291
|
return model;
|
|
8167
8292
|
}
|
|
8168
8293
|
}
|
|
@@ -8188,7 +8313,6 @@ var vertexGemini3ProAgent = new ExuluAgent2({
|
|
|
8188
8313
|
instructions: "",
|
|
8189
8314
|
model: {
|
|
8190
8315
|
create: ({ apiKey }) => {
|
|
8191
|
-
console.log("[EXULU] apiKey", apiKey);
|
|
8192
8316
|
if (!apiKey) {
|
|
8193
8317
|
throw new Error("Auth credentials not found for Google Vertex agent, make sure you have set the provider api key to a valid google authentication json.");
|
|
8194
8318
|
}
|
|
@@ -8199,8 +8323,8 @@ var vertexGemini3ProAgent = new ExuluAgent2({
|
|
|
8199
8323
|
if (!googleAuthPayload.location) {
|
|
8200
8324
|
throw new Error("Location not set in authentication json for Google Vertex Gemini 3 Pro agent, should be for example 'europe-west1'");
|
|
8201
8325
|
}
|
|
8202
|
-
const
|
|
8203
|
-
const model =
|
|
8326
|
+
const vertex = createVertex(googleAuthPayload);
|
|
8327
|
+
const model = vertex("gemini-3-pro-preview");
|
|
8204
8328
|
return model;
|
|
8205
8329
|
}
|
|
8206
8330
|
}
|
|
@@ -9290,6 +9414,32 @@ var mathTools = [
|
|
|
9290
9414
|
degreesToRadiansTool
|
|
9291
9415
|
];
|
|
9292
9416
|
|
|
9417
|
+
// src/templates/tools/preview-pdf.ts
|
|
9418
|
+
import { z as z5 } from "zod";
|
|
9419
|
+
var previewPdfTool = new ExuluTool2({
|
|
9420
|
+
id: "preview_pdf",
|
|
9421
|
+
name: "Preview PDF",
|
|
9422
|
+
description: "Used to display a PDF file in an iframe web view",
|
|
9423
|
+
type: "function",
|
|
9424
|
+
config: [],
|
|
9425
|
+
inputSchema: z5.object({
|
|
9426
|
+
s3key: z5.string().describe("The S3 key of the PDF file to preview, can also optionally include a [bucket:name] to specify the bucket."),
|
|
9427
|
+
page: z5.number().describe("The page number to preview, defaults to 1.").optional()
|
|
9428
|
+
}),
|
|
9429
|
+
execute: async ({ s3key, page, exuluConfig }) => {
|
|
9430
|
+
const url = await getPresignedUrl(s3key, exuluConfig);
|
|
9431
|
+
if (!url) {
|
|
9432
|
+
throw new Error("No URL provided for PDF preview");
|
|
9433
|
+
}
|
|
9434
|
+
return {
|
|
9435
|
+
result: JSON.stringify({
|
|
9436
|
+
url,
|
|
9437
|
+
page: page ?? 1
|
|
9438
|
+
})
|
|
9439
|
+
};
|
|
9440
|
+
}
|
|
9441
|
+
});
|
|
9442
|
+
|
|
9293
9443
|
// src/templates/tools/todo/todowrite.txt
|
|
9294
9444
|
var todowrite_default = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
9295
9445
|
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
@@ -9476,12 +9626,12 @@ Usage:
|
|
|
9476
9626
|
- If no todos exist yet, an empty list will be returned`;
|
|
9477
9627
|
|
|
9478
9628
|
// src/templates/tools/todo/todo.ts
|
|
9479
|
-
import
|
|
9480
|
-
var TodoSchema =
|
|
9481
|
-
content:
|
|
9482
|
-
status:
|
|
9483
|
-
priority:
|
|
9484
|
-
id:
|
|
9629
|
+
import z6 from "zod";
|
|
9630
|
+
var TodoSchema = z6.object({
|
|
9631
|
+
content: z6.string().describe("Brief description of the task"),
|
|
9632
|
+
status: z6.string().describe("Current status of the task: pending, in_progress, completed, cancelled"),
|
|
9633
|
+
priority: z6.string().describe("Priority level of the task: high, medium, low"),
|
|
9634
|
+
id: z6.string().describe("Unique identifier for the todo item")
|
|
9485
9635
|
});
|
|
9486
9636
|
var TodoWriteTool = new ExuluTool2({
|
|
9487
9637
|
id: "todo_write",
|
|
@@ -9494,8 +9644,8 @@ var TodoWriteTool = new ExuluTool2({
|
|
|
9494
9644
|
description: "The description of the todo list, if set overwrites the default description.",
|
|
9495
9645
|
default: todowrite_default
|
|
9496
9646
|
}],
|
|
9497
|
-
inputSchema:
|
|
9498
|
-
todos:
|
|
9647
|
+
inputSchema: z6.object({
|
|
9648
|
+
todos: z6.array(TodoSchema).describe("The updated todo list")
|
|
9499
9649
|
}),
|
|
9500
9650
|
execute: async (inputs) => {
|
|
9501
9651
|
const { sessionID, todos, user } = inputs;
|
|
@@ -9526,7 +9676,7 @@ var TodoReadTool = new ExuluTool2({
|
|
|
9526
9676
|
id: "todo_read",
|
|
9527
9677
|
name: "Todo Read",
|
|
9528
9678
|
description: "Use this tool to read your todo list",
|
|
9529
|
-
inputSchema:
|
|
9679
|
+
inputSchema: z6.object({}),
|
|
9530
9680
|
type: "function",
|
|
9531
9681
|
category: "todo",
|
|
9532
9682
|
config: [{
|
|
@@ -9638,6 +9788,7 @@ var ExuluApp = class {
|
|
|
9638
9788
|
this._tools = [
|
|
9639
9789
|
...tools ?? [],
|
|
9640
9790
|
...mathTools,
|
|
9791
|
+
...[previewPdfTool],
|
|
9641
9792
|
...todoTools,
|
|
9642
9793
|
// Add contexts as tools
|
|
9643
9794
|
...Object.values(contexts || {}).map((context) => context.tool())
|