@exulu/backend 1.8.1 → 1.9.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 +3 -3
- package/dist/index.cjs +117 -57
- package/dist/index.d.cts +23 -8
- package/dist/index.d.ts +23 -8
- package/dist/index.js +118 -58
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# [1.9.0](https://github.com/Qventu/exulu-backend/compare/v1.8.1...v1.9.0) (2025-08-13)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### Features
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* improve scroll behaviour in chat and add apiKeyProvider to agents ([505155b](https://github.com/Qventu/exulu-backend/commit/505155b853707cefb1a5205f78064845391473d9))
|
|
7
7
|
|
|
8
8
|
# [1.1.0](https://github.com/Qventu/exulu-backend/compare/v1.0.1...v1.1.0) (2025-07-30)
|
|
9
9
|
|
package/dist/index.cjs
CHANGED
|
@@ -446,37 +446,6 @@ var ExuluEvalUtils = {
|
|
|
446
446
|
}
|
|
447
447
|
};
|
|
448
448
|
|
|
449
|
-
// src/registry/utils/claude-messages.ts
|
|
450
|
-
var CLAUDE_MESSAGES = {
|
|
451
|
-
anthropic_token_variable_not_encrypted: `
|
|
452
|
-
\x1B[41m -- Anthropic token variable set by your admin is not encrypted. This poses a security risk. Please contact your admin to fix the variable used for your key. --
|
|
453
|
-
\x1B[0m`,
|
|
454
|
-
anthropic_token_variable_not_found: `
|
|
455
|
-
\x1B[41m -- Anthropic token variable not found. Please contact to fix the variable used for your key. --
|
|
456
|
-
\x1B[0m`,
|
|
457
|
-
authentication_error: `
|
|
458
|
-
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
459
|
-
\x1B[0m`,
|
|
460
|
-
missing_body: `
|
|
461
|
-
\x1B[41m -- Missing body Anthropic response. --
|
|
462
|
-
\x1B[0m`,
|
|
463
|
-
missing_nextauth_secret: `
|
|
464
|
-
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
465
|
-
\x1B[0m`,
|
|
466
|
-
not_enabled: `
|
|
467
|
-
\x1B[31m
|
|
468
|
-
\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
|
|
469
|
-
\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
|
|
470
|
-
\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
471
|
-
\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
|
|
472
|
-
\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
|
|
473
|
-
\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
|
|
474
|
-
Intelligence Management Platform
|
|
475
|
-
\x1B[0m
|
|
476
|
-
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
477
|
-
\x1B[0m`
|
|
478
|
-
};
|
|
479
|
-
|
|
480
449
|
// src/registry/classes.ts
|
|
481
450
|
var import_crypto_js = __toESM(require("crypto-js"), 1);
|
|
482
451
|
function sanitizeToolName(name) {
|
|
@@ -488,12 +457,13 @@ function sanitizeToolName(name) {
|
|
|
488
457
|
}
|
|
489
458
|
return sanitized;
|
|
490
459
|
}
|
|
491
|
-
var convertToolsArrayToObject = (tools, configs) => {
|
|
460
|
+
var convertToolsArrayToObject = (tools, configs, providerApiKey) => {
|
|
492
461
|
if (!tools) return {};
|
|
493
462
|
const sanitizedTools = tools ? tools.map((tool2) => ({
|
|
494
463
|
...tool2,
|
|
495
464
|
name: sanitizeToolName(tool2.name)
|
|
496
465
|
})) : [];
|
|
466
|
+
console.log("[EXULU] Sanitized tools", sanitizedTools);
|
|
497
467
|
const askForConfirmation = {
|
|
498
468
|
description: "Ask the user for confirmation.",
|
|
499
469
|
parameters: import_zod2.z.object({
|
|
@@ -515,11 +485,13 @@ var convertToolsArrayToObject = (tools, configs) => {
|
|
|
515
485
|
if (config) {
|
|
516
486
|
config = await hydrateVariables(config || []);
|
|
517
487
|
}
|
|
488
|
+
console.log("[EXULU] Config", config);
|
|
518
489
|
return await cur.tool.execute({
|
|
519
490
|
...inputs,
|
|
520
491
|
// Convert config to object format if a config object
|
|
521
492
|
// is available, after we added the .value property
|
|
522
493
|
// by hydrating it from the variables table.
|
|
494
|
+
providerApiKey,
|
|
523
495
|
config: config ? config.config.reduce((acc, curr) => {
|
|
524
496
|
acc[curr.name] = curr.value;
|
|
525
497
|
return acc;
|
|
@@ -616,9 +588,10 @@ var ExuluAgent = class {
|
|
|
616
588
|
}),
|
|
617
589
|
description: `A function that calls an AI agent named: ${this.name}. The agent does the following: ${this.description}.`,
|
|
618
590
|
config: [],
|
|
619
|
-
execute: async ({ prompt }) => {
|
|
591
|
+
execute: async ({ prompt, config, providerApiKey }) => {
|
|
620
592
|
return await this.generateSync({
|
|
621
593
|
prompt,
|
|
594
|
+
providerApiKey,
|
|
622
595
|
statistics: {
|
|
623
596
|
label: "",
|
|
624
597
|
trigger: "tool"
|
|
@@ -627,7 +600,7 @@ var ExuluAgent = class {
|
|
|
627
600
|
}
|
|
628
601
|
});
|
|
629
602
|
};
|
|
630
|
-
generateSync = async ({ messages, prompt, tools, statistics,
|
|
603
|
+
generateSync = async ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }) => {
|
|
631
604
|
if (!this.model) {
|
|
632
605
|
throw new Error("Model is required for streaming.");
|
|
633
606
|
}
|
|
@@ -637,13 +610,17 @@ var ExuluAgent = class {
|
|
|
637
610
|
if (prompt && messages) {
|
|
638
611
|
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
639
612
|
}
|
|
613
|
+
const model = this.model.create({
|
|
614
|
+
apiKey: providerApiKey
|
|
615
|
+
});
|
|
640
616
|
const { text } = await (0, import_ai.generateText)({
|
|
641
|
-
model
|
|
617
|
+
model,
|
|
618
|
+
// Should be a LanguageModelV1
|
|
642
619
|
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
643
620
|
messages,
|
|
644
621
|
prompt,
|
|
645
622
|
maxRetries: 2,
|
|
646
|
-
tools: convertToolsArrayToObject(tools,
|
|
623
|
+
tools: convertToolsArrayToObject(tools, toolConfigs, providerApiKey),
|
|
647
624
|
maxSteps: 5
|
|
648
625
|
});
|
|
649
626
|
if (statistics) {
|
|
@@ -657,7 +634,7 @@ var ExuluAgent = class {
|
|
|
657
634
|
}
|
|
658
635
|
return text;
|
|
659
636
|
};
|
|
660
|
-
generateStream = ({ messages, prompt, tools, statistics,
|
|
637
|
+
generateStream = ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }) => {
|
|
661
638
|
if (!this.model) {
|
|
662
639
|
throw new Error("Model is required for streaming.");
|
|
663
640
|
}
|
|
@@ -667,13 +644,19 @@ var ExuluAgent = class {
|
|
|
667
644
|
if (prompt && messages) {
|
|
668
645
|
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
669
646
|
}
|
|
647
|
+
const model = this.model.create({
|
|
648
|
+
apiKey: providerApiKey
|
|
649
|
+
});
|
|
650
|
+
console.log("[EXULU] Model provider key", providerApiKey);
|
|
651
|
+
console.log("[EXULU] Tool configs", toolConfigs);
|
|
670
652
|
return (0, import_ai.streamText)({
|
|
671
|
-
model
|
|
653
|
+
model,
|
|
654
|
+
// Should be a LanguageModelV1
|
|
672
655
|
messages,
|
|
673
656
|
prompt,
|
|
674
657
|
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
675
658
|
maxRetries: 2,
|
|
676
|
-
tools: convertToolsArrayToObject(tools,
|
|
659
|
+
tools: convertToolsArrayToObject(tools, toolConfigs, providerApiKey),
|
|
677
660
|
maxSteps: 5,
|
|
678
661
|
onError: (error) => console.error("[EXULU] chat stream error.", error),
|
|
679
662
|
onFinish: async ({ response, usage }) => {
|
|
@@ -930,8 +913,23 @@ var ExuluEval = class {
|
|
|
930
913
|
if (!data.prompt) {
|
|
931
914
|
throw new Error("Prompt is required for running an agent.");
|
|
932
915
|
}
|
|
916
|
+
const { db: db4 } = await postgresClient();
|
|
917
|
+
const variableName = runner.agent.providerApiKey;
|
|
918
|
+
const variable = await db4.from("variables").where({ name: variableName }).first();
|
|
919
|
+
if (!variable) {
|
|
920
|
+
throw new Error(`Provider API key for variable "${runner.agent.providerApiKey}" not found.`);
|
|
921
|
+
}
|
|
922
|
+
let providerApiKey = variable.value;
|
|
923
|
+
if (!variable.encrypted) {
|
|
924
|
+
throw new Error(`Provider API key for variable "${runner.agent.providerApiKey}" is not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys.`);
|
|
925
|
+
}
|
|
926
|
+
if (variable.encrypted) {
|
|
927
|
+
const bytes = import_crypto_js.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
928
|
+
providerApiKey = bytes.toString(import_crypto_js.default.enc.Utf8);
|
|
929
|
+
}
|
|
933
930
|
const result = await runner.agent.generateSync({
|
|
934
|
-
prompt: data.prompt
|
|
931
|
+
prompt: data.prompt,
|
|
932
|
+
providerApiKey
|
|
935
933
|
});
|
|
936
934
|
data.result = result;
|
|
937
935
|
}
|
|
@@ -2675,6 +2673,10 @@ var agentsSchema = {
|
|
|
2675
2673
|
name: "description",
|
|
2676
2674
|
type: "text"
|
|
2677
2675
|
},
|
|
2676
|
+
{
|
|
2677
|
+
name: "providerApiKey",
|
|
2678
|
+
type: "text"
|
|
2679
|
+
},
|
|
2678
2680
|
{
|
|
2679
2681
|
name: "extensions",
|
|
2680
2682
|
type: "json"
|
|
@@ -3122,6 +3124,39 @@ var createUppyRoutes = async (app) => {
|
|
|
3122
3124
|
var import_utils2 = require("@apollo/utils.keyvaluecache");
|
|
3123
3125
|
var import_body_parser = __toESM(require("body-parser"), 1);
|
|
3124
3126
|
var import_crypto_js3 = __toESM(require("crypto-js"), 1);
|
|
3127
|
+
|
|
3128
|
+
// src/registry/utils/claude-messages.ts
|
|
3129
|
+
var CLAUDE_MESSAGES = {
|
|
3130
|
+
anthropic_token_variable_not_encrypted: `
|
|
3131
|
+
\x1B[41m -- Anthropic token variable set by your admin is not encrypted. This poses a security risk. Please contact your admin to fix the variable used for your key. --
|
|
3132
|
+
\x1B[0m`,
|
|
3133
|
+
anthropic_token_variable_not_found: `
|
|
3134
|
+
\x1B[41m -- Anthropic token variable not found. Please contact to fix the variable used for your key. --
|
|
3135
|
+
\x1B[0m`,
|
|
3136
|
+
authentication_error: `
|
|
3137
|
+
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
3138
|
+
\x1B[0m`,
|
|
3139
|
+
missing_body: `
|
|
3140
|
+
\x1B[41m -- Missing body Anthropic response. --
|
|
3141
|
+
\x1B[0m`,
|
|
3142
|
+
missing_nextauth_secret: `
|
|
3143
|
+
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
3144
|
+
\x1B[0m`,
|
|
3145
|
+
not_enabled: `
|
|
3146
|
+
\x1B[31m
|
|
3147
|
+
\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
|
|
3148
|
+
\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
|
|
3149
|
+
\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3150
|
+
\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
|
|
3151
|
+
\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
|
|
3152
|
+
\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
|
|
3153
|
+
Intelligence Management Platform
|
|
3154
|
+
\x1B[0m
|
|
3155
|
+
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
3156
|
+
\x1B[0m`
|
|
3157
|
+
};
|
|
3158
|
+
|
|
3159
|
+
// src/registry/routes.ts
|
|
3125
3160
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
3126
3161
|
var global_queues = {
|
|
3127
3162
|
logs_cleaner: "logs-cleaner"
|
|
@@ -3324,8 +3359,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3324
3359
|
name: agent.name,
|
|
3325
3360
|
id: agent.id,
|
|
3326
3361
|
description: agent.description,
|
|
3327
|
-
provider: backend?.model?.provider,
|
|
3328
|
-
model: backend?.model?.modelId,
|
|
3362
|
+
provider: backend?.model?.create({ apiKey: "" }).provider,
|
|
3363
|
+
model: backend?.model?.create({ apiKey: "" }).modelId,
|
|
3329
3364
|
active: agent.active,
|
|
3330
3365
|
public: agent.public,
|
|
3331
3366
|
type: agent.type,
|
|
@@ -3333,6 +3368,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3333
3368
|
rateLimit: backend?.rateLimit,
|
|
3334
3369
|
streaming: backend?.streaming,
|
|
3335
3370
|
capabilities: backend?.capabilities,
|
|
3371
|
+
providerApiKey: agent.providerApiKey,
|
|
3336
3372
|
// todo add contexts
|
|
3337
3373
|
availableTools: tools,
|
|
3338
3374
|
enabledTools: agent.tools
|
|
@@ -4057,13 +4093,33 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4057
4093
|
return;
|
|
4058
4094
|
}
|
|
4059
4095
|
console.log("[EXULU] agent tools", agentInstance.tools);
|
|
4060
|
-
const enabledTools = agentInstance.tools.map((
|
|
4096
|
+
const enabledTools = agentInstance.tools.map(({ config, toolId }) => tools.find(({ id }) => id === toolId)).filter(Boolean);
|
|
4061
4097
|
console.log("[EXULU] enabled tools", enabledTools);
|
|
4098
|
+
const variableName = agentInstance.providerApiKey;
|
|
4099
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
4100
|
+
if (!variable) {
|
|
4101
|
+
res.status(400).json({
|
|
4102
|
+
message: "Provider API key variable not found."
|
|
4103
|
+
});
|
|
4104
|
+
return;
|
|
4105
|
+
}
|
|
4106
|
+
let providerApiKey = variable.value;
|
|
4107
|
+
if (!variable.encrypted) {
|
|
4108
|
+
res.status(400).json({
|
|
4109
|
+
message: "Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys."
|
|
4110
|
+
});
|
|
4111
|
+
return;
|
|
4112
|
+
}
|
|
4113
|
+
if (variable.encrypted) {
|
|
4114
|
+
const bytes = import_crypto_js3.default.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
4115
|
+
providerApiKey = bytes.toString(import_crypto_js3.default.enc.Utf8);
|
|
4116
|
+
}
|
|
4062
4117
|
if (!!stream) {
|
|
4063
4118
|
const result = agent.generateStream({
|
|
4064
4119
|
messages: req.body.messages,
|
|
4065
4120
|
tools: enabledTools,
|
|
4066
|
-
|
|
4121
|
+
providerApiKey,
|
|
4122
|
+
toolConfigs: agentInstance.tools,
|
|
4067
4123
|
statistics: {
|
|
4068
4124
|
label: agent.name,
|
|
4069
4125
|
trigger: "agent"
|
|
@@ -4075,7 +4131,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4075
4131
|
const response = await agent.generateSync({
|
|
4076
4132
|
messages: req.body.messages,
|
|
4077
4133
|
tools: enabledTools.map((tool2) => tool2.tool),
|
|
4078
|
-
|
|
4134
|
+
providerApiKey,
|
|
4135
|
+
toolConfigs: agentInstance.tools,
|
|
4079
4136
|
statistics: {
|
|
4080
4137
|
label: agent.name,
|
|
4081
4138
|
trigger: "agent"
|
|
@@ -4690,7 +4747,6 @@ var claudeCodeAgent = new ExuluAgent({
|
|
|
4690
4747
|
|
|
4691
4748
|
// src/templates/agents/claude-opus-4.ts
|
|
4692
4749
|
var import_anthropic = require("@ai-sdk/anthropic");
|
|
4693
|
-
var import_zod4 = require("zod");
|
|
4694
4750
|
var agentId2 = "5434-5678-9143-2590";
|
|
4695
4751
|
var defaultAgent = new ExuluAgent({
|
|
4696
4752
|
id: `${agentId2}-default-claude-4-opus-agent`,
|
|
@@ -4708,17 +4764,21 @@ var defaultAgent = new ExuluAgent({
|
|
|
4708
4764
|
config: {
|
|
4709
4765
|
name: `Default agent`,
|
|
4710
4766
|
instructions: "You are a helpful assistant.",
|
|
4711
|
-
model:
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4767
|
+
model: {
|
|
4768
|
+
create: ({ apiKey }) => {
|
|
4769
|
+
const anthropic2 = (0, import_anthropic.createAnthropic)({
|
|
4770
|
+
apiKey
|
|
4771
|
+
});
|
|
4772
|
+
return anthropic2("claude-4-opus-20250514");
|
|
4773
|
+
}
|
|
4774
|
+
// todo add a field of type string that adds a dropdown list from which the user can select the model
|
|
4775
|
+
// todo for each model, check which provider is used, and require the admin to add one or multiple
|
|
4776
|
+
// API keys for the provider (which we can then auto-rotate).
|
|
4777
|
+
// todo also add custom fields for rate limiting, so the admin can set custom rate limits for the agent
|
|
4778
|
+
// and allow him/her to decide if the rate limit is per user or per agent.
|
|
4779
|
+
// todo finally allow switching on or off immutable audit logs on the agent. Which then enables OTEL
|
|
4780
|
+
// and stores the logs into the pre-defined storage.
|
|
4781
|
+
}
|
|
4722
4782
|
}
|
|
4723
4783
|
});
|
|
4724
4784
|
|
package/dist/index.d.cts
CHANGED
|
@@ -91,9 +91,16 @@ declare const ExuluZodFileType: ({ name, label, description, allowedFileTypes }:
|
|
|
91
91
|
type ExuluAgentConfig = {
|
|
92
92
|
name: string;
|
|
93
93
|
instructions: string;
|
|
94
|
-
model:
|
|
94
|
+
model: {
|
|
95
|
+
create: ({ apiKey }: {
|
|
96
|
+
apiKey: string;
|
|
97
|
+
}) => LanguageModelV1;
|
|
98
|
+
};
|
|
95
99
|
outputSchema?: ZodSchema;
|
|
96
|
-
custom?:
|
|
100
|
+
custom?: {
|
|
101
|
+
name: string;
|
|
102
|
+
description: string;
|
|
103
|
+
}[];
|
|
97
104
|
memory?: {
|
|
98
105
|
lastMessages: number;
|
|
99
106
|
vector: boolean;
|
|
@@ -141,7 +148,11 @@ declare class ExuluAgent {
|
|
|
141
148
|
rateLimit?: RateLimiterRule;
|
|
142
149
|
config?: ExuluAgentConfig | undefined;
|
|
143
150
|
evals?: ExuluAgentEval[];
|
|
144
|
-
model?:
|
|
151
|
+
model?: {
|
|
152
|
+
create: ({ apiKey }: {
|
|
153
|
+
apiKey: string;
|
|
154
|
+
}) => LanguageModelV1;
|
|
155
|
+
};
|
|
145
156
|
capabilities: {
|
|
146
157
|
images: string[];
|
|
147
158
|
files: string[];
|
|
@@ -150,19 +161,21 @@ declare class ExuluAgent {
|
|
|
150
161
|
};
|
|
151
162
|
constructor({ id, name, description, config, rateLimit, capabilities, type, evals }: ExuluAgentParams);
|
|
152
163
|
tool: () => ExuluTool;
|
|
153
|
-
generateSync: ({ messages, prompt, tools, statistics,
|
|
164
|
+
generateSync: ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }: {
|
|
154
165
|
messages?: Message[];
|
|
155
166
|
prompt?: string;
|
|
156
167
|
tools?: ExuluTool[];
|
|
157
168
|
statistics?: ExuluStatisticParams;
|
|
158
|
-
|
|
169
|
+
toolConfigs?: ExuluAgentToolConfig[];
|
|
170
|
+
providerApiKey: string;
|
|
159
171
|
}) => Promise<string>;
|
|
160
|
-
generateStream: ({ messages, prompt, tools, statistics,
|
|
172
|
+
generateStream: ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }: {
|
|
161
173
|
messages?: Message[];
|
|
162
174
|
prompt?: string;
|
|
163
175
|
tools?: ExuluTool[];
|
|
164
176
|
statistics?: ExuluStatisticParams;
|
|
165
|
-
|
|
177
|
+
toolConfigs?: ExuluAgentToolConfig[];
|
|
178
|
+
providerApiKey: string;
|
|
166
179
|
}) => ai.StreamTextResult<Record<string, Tool>, never>;
|
|
167
180
|
}
|
|
168
181
|
type VectorOperationResponse = Promise<{
|
|
@@ -268,7 +281,9 @@ type ExuluEvalRunnerInstance = {
|
|
|
268
281
|
type ExuluEvalRunner = ({ data, runner }: {
|
|
269
282
|
data: ExuluEvalInput;
|
|
270
283
|
runner: {
|
|
271
|
-
agent?: ExuluAgent
|
|
284
|
+
agent?: ExuluAgent & {
|
|
285
|
+
providerApiKey: string;
|
|
286
|
+
};
|
|
272
287
|
workflow?: ExuluWorkflow;
|
|
273
288
|
};
|
|
274
289
|
}) => Promise<{
|
package/dist/index.d.ts
CHANGED
|
@@ -91,9 +91,16 @@ declare const ExuluZodFileType: ({ name, label, description, allowedFileTypes }:
|
|
|
91
91
|
type ExuluAgentConfig = {
|
|
92
92
|
name: string;
|
|
93
93
|
instructions: string;
|
|
94
|
-
model:
|
|
94
|
+
model: {
|
|
95
|
+
create: ({ apiKey }: {
|
|
96
|
+
apiKey: string;
|
|
97
|
+
}) => LanguageModelV1;
|
|
98
|
+
};
|
|
95
99
|
outputSchema?: ZodSchema;
|
|
96
|
-
custom?:
|
|
100
|
+
custom?: {
|
|
101
|
+
name: string;
|
|
102
|
+
description: string;
|
|
103
|
+
}[];
|
|
97
104
|
memory?: {
|
|
98
105
|
lastMessages: number;
|
|
99
106
|
vector: boolean;
|
|
@@ -141,7 +148,11 @@ declare class ExuluAgent {
|
|
|
141
148
|
rateLimit?: RateLimiterRule;
|
|
142
149
|
config?: ExuluAgentConfig | undefined;
|
|
143
150
|
evals?: ExuluAgentEval[];
|
|
144
|
-
model?:
|
|
151
|
+
model?: {
|
|
152
|
+
create: ({ apiKey }: {
|
|
153
|
+
apiKey: string;
|
|
154
|
+
}) => LanguageModelV1;
|
|
155
|
+
};
|
|
145
156
|
capabilities: {
|
|
146
157
|
images: string[];
|
|
147
158
|
files: string[];
|
|
@@ -150,19 +161,21 @@ declare class ExuluAgent {
|
|
|
150
161
|
};
|
|
151
162
|
constructor({ id, name, description, config, rateLimit, capabilities, type, evals }: ExuluAgentParams);
|
|
152
163
|
tool: () => ExuluTool;
|
|
153
|
-
generateSync: ({ messages, prompt, tools, statistics,
|
|
164
|
+
generateSync: ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }: {
|
|
154
165
|
messages?: Message[];
|
|
155
166
|
prompt?: string;
|
|
156
167
|
tools?: ExuluTool[];
|
|
157
168
|
statistics?: ExuluStatisticParams;
|
|
158
|
-
|
|
169
|
+
toolConfigs?: ExuluAgentToolConfig[];
|
|
170
|
+
providerApiKey: string;
|
|
159
171
|
}) => Promise<string>;
|
|
160
|
-
generateStream: ({ messages, prompt, tools, statistics,
|
|
172
|
+
generateStream: ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }: {
|
|
161
173
|
messages?: Message[];
|
|
162
174
|
prompt?: string;
|
|
163
175
|
tools?: ExuluTool[];
|
|
164
176
|
statistics?: ExuluStatisticParams;
|
|
165
|
-
|
|
177
|
+
toolConfigs?: ExuluAgentToolConfig[];
|
|
178
|
+
providerApiKey: string;
|
|
166
179
|
}) => ai.StreamTextResult<Record<string, Tool>, never>;
|
|
167
180
|
}
|
|
168
181
|
type VectorOperationResponse = Promise<{
|
|
@@ -268,7 +281,9 @@ type ExuluEvalRunnerInstance = {
|
|
|
268
281
|
type ExuluEvalRunner = ({ data, runner }: {
|
|
269
282
|
data: ExuluEvalInput;
|
|
270
283
|
runner: {
|
|
271
|
-
agent?: ExuluAgent
|
|
284
|
+
agent?: ExuluAgent & {
|
|
285
|
+
providerApiKey: string;
|
|
286
|
+
};
|
|
272
287
|
workflow?: ExuluWorkflow;
|
|
273
288
|
};
|
|
274
289
|
}) => Promise<{
|
package/dist/index.js
CHANGED
|
@@ -403,37 +403,6 @@ var ExuluEvalUtils = {
|
|
|
403
403
|
}
|
|
404
404
|
};
|
|
405
405
|
|
|
406
|
-
// src/registry/utils/claude-messages.ts
|
|
407
|
-
var CLAUDE_MESSAGES = {
|
|
408
|
-
anthropic_token_variable_not_encrypted: `
|
|
409
|
-
\x1B[41m -- Anthropic token variable set by your admin is not encrypted. This poses a security risk. Please contact your admin to fix the variable used for your key. --
|
|
410
|
-
\x1B[0m`,
|
|
411
|
-
anthropic_token_variable_not_found: `
|
|
412
|
-
\x1B[41m -- Anthropic token variable not found. Please contact to fix the variable used for your key. --
|
|
413
|
-
\x1B[0m`,
|
|
414
|
-
authentication_error: `
|
|
415
|
-
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
416
|
-
\x1B[0m`,
|
|
417
|
-
missing_body: `
|
|
418
|
-
\x1B[41m -- Missing body Anthropic response. --
|
|
419
|
-
\x1B[0m`,
|
|
420
|
-
missing_nextauth_secret: `
|
|
421
|
-
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
422
|
-
\x1B[0m`,
|
|
423
|
-
not_enabled: `
|
|
424
|
-
\x1B[31m
|
|
425
|
-
\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
|
|
426
|
-
\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
|
|
427
|
-
\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
428
|
-
\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
|
|
429
|
-
\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
|
|
430
|
-
\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
|
|
431
|
-
Intelligence Management Platform
|
|
432
|
-
\x1B[0m
|
|
433
|
-
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
434
|
-
\x1B[0m`
|
|
435
|
-
};
|
|
436
|
-
|
|
437
406
|
// src/registry/classes.ts
|
|
438
407
|
import CryptoJS from "crypto-js";
|
|
439
408
|
function sanitizeToolName(name) {
|
|
@@ -445,12 +414,13 @@ function sanitizeToolName(name) {
|
|
|
445
414
|
}
|
|
446
415
|
return sanitized;
|
|
447
416
|
}
|
|
448
|
-
var convertToolsArrayToObject = (tools, configs) => {
|
|
417
|
+
var convertToolsArrayToObject = (tools, configs, providerApiKey) => {
|
|
449
418
|
if (!tools) return {};
|
|
450
419
|
const sanitizedTools = tools ? tools.map((tool2) => ({
|
|
451
420
|
...tool2,
|
|
452
421
|
name: sanitizeToolName(tool2.name)
|
|
453
422
|
})) : [];
|
|
423
|
+
console.log("[EXULU] Sanitized tools", sanitizedTools);
|
|
454
424
|
const askForConfirmation = {
|
|
455
425
|
description: "Ask the user for confirmation.",
|
|
456
426
|
parameters: z.object({
|
|
@@ -472,11 +442,13 @@ var convertToolsArrayToObject = (tools, configs) => {
|
|
|
472
442
|
if (config) {
|
|
473
443
|
config = await hydrateVariables(config || []);
|
|
474
444
|
}
|
|
445
|
+
console.log("[EXULU] Config", config);
|
|
475
446
|
return await cur.tool.execute({
|
|
476
447
|
...inputs,
|
|
477
448
|
// Convert config to object format if a config object
|
|
478
449
|
// is available, after we added the .value property
|
|
479
450
|
// by hydrating it from the variables table.
|
|
451
|
+
providerApiKey,
|
|
480
452
|
config: config ? config.config.reduce((acc, curr) => {
|
|
481
453
|
acc[curr.name] = curr.value;
|
|
482
454
|
return acc;
|
|
@@ -573,9 +545,10 @@ var ExuluAgent = class {
|
|
|
573
545
|
}),
|
|
574
546
|
description: `A function that calls an AI agent named: ${this.name}. The agent does the following: ${this.description}.`,
|
|
575
547
|
config: [],
|
|
576
|
-
execute: async ({ prompt }) => {
|
|
548
|
+
execute: async ({ prompt, config, providerApiKey }) => {
|
|
577
549
|
return await this.generateSync({
|
|
578
550
|
prompt,
|
|
551
|
+
providerApiKey,
|
|
579
552
|
statistics: {
|
|
580
553
|
label: "",
|
|
581
554
|
trigger: "tool"
|
|
@@ -584,7 +557,7 @@ var ExuluAgent = class {
|
|
|
584
557
|
}
|
|
585
558
|
});
|
|
586
559
|
};
|
|
587
|
-
generateSync = async ({ messages, prompt, tools, statistics,
|
|
560
|
+
generateSync = async ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }) => {
|
|
588
561
|
if (!this.model) {
|
|
589
562
|
throw new Error("Model is required for streaming.");
|
|
590
563
|
}
|
|
@@ -594,13 +567,17 @@ var ExuluAgent = class {
|
|
|
594
567
|
if (prompt && messages) {
|
|
595
568
|
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
596
569
|
}
|
|
570
|
+
const model = this.model.create({
|
|
571
|
+
apiKey: providerApiKey
|
|
572
|
+
});
|
|
597
573
|
const { text } = await generateText({
|
|
598
|
-
model
|
|
574
|
+
model,
|
|
575
|
+
// Should be a LanguageModelV1
|
|
599
576
|
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
600
577
|
messages,
|
|
601
578
|
prompt,
|
|
602
579
|
maxRetries: 2,
|
|
603
|
-
tools: convertToolsArrayToObject(tools,
|
|
580
|
+
tools: convertToolsArrayToObject(tools, toolConfigs, providerApiKey),
|
|
604
581
|
maxSteps: 5
|
|
605
582
|
});
|
|
606
583
|
if (statistics) {
|
|
@@ -614,7 +591,7 @@ var ExuluAgent = class {
|
|
|
614
591
|
}
|
|
615
592
|
return text;
|
|
616
593
|
};
|
|
617
|
-
generateStream = ({ messages, prompt, tools, statistics,
|
|
594
|
+
generateStream = ({ messages, prompt, tools, statistics, toolConfigs, providerApiKey }) => {
|
|
618
595
|
if (!this.model) {
|
|
619
596
|
throw new Error("Model is required for streaming.");
|
|
620
597
|
}
|
|
@@ -624,13 +601,19 @@ var ExuluAgent = class {
|
|
|
624
601
|
if (prompt && messages) {
|
|
625
602
|
throw new Error("Prompt and messages cannot be provided at the same time.");
|
|
626
603
|
}
|
|
604
|
+
const model = this.model.create({
|
|
605
|
+
apiKey: providerApiKey
|
|
606
|
+
});
|
|
607
|
+
console.log("[EXULU] Model provider key", providerApiKey);
|
|
608
|
+
console.log("[EXULU] Tool configs", toolConfigs);
|
|
627
609
|
return streamText({
|
|
628
|
-
model
|
|
610
|
+
model,
|
|
611
|
+
// Should be a LanguageModelV1
|
|
629
612
|
messages,
|
|
630
613
|
prompt,
|
|
631
614
|
system: "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.",
|
|
632
615
|
maxRetries: 2,
|
|
633
|
-
tools: convertToolsArrayToObject(tools,
|
|
616
|
+
tools: convertToolsArrayToObject(tools, toolConfigs, providerApiKey),
|
|
634
617
|
maxSteps: 5,
|
|
635
618
|
onError: (error) => console.error("[EXULU] chat stream error.", error),
|
|
636
619
|
onFinish: async ({ response, usage }) => {
|
|
@@ -887,8 +870,23 @@ var ExuluEval = class {
|
|
|
887
870
|
if (!data.prompt) {
|
|
888
871
|
throw new Error("Prompt is required for running an agent.");
|
|
889
872
|
}
|
|
873
|
+
const { db: db4 } = await postgresClient();
|
|
874
|
+
const variableName = runner.agent.providerApiKey;
|
|
875
|
+
const variable = await db4.from("variables").where({ name: variableName }).first();
|
|
876
|
+
if (!variable) {
|
|
877
|
+
throw new Error(`Provider API key for variable "${runner.agent.providerApiKey}" not found.`);
|
|
878
|
+
}
|
|
879
|
+
let providerApiKey = variable.value;
|
|
880
|
+
if (!variable.encrypted) {
|
|
881
|
+
throw new Error(`Provider API key for variable "${runner.agent.providerApiKey}" is not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys.`);
|
|
882
|
+
}
|
|
883
|
+
if (variable.encrypted) {
|
|
884
|
+
const bytes = CryptoJS.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
885
|
+
providerApiKey = bytes.toString(CryptoJS.enc.Utf8);
|
|
886
|
+
}
|
|
890
887
|
const result = await runner.agent.generateSync({
|
|
891
|
-
prompt: data.prompt
|
|
888
|
+
prompt: data.prompt,
|
|
889
|
+
providerApiKey
|
|
892
890
|
});
|
|
893
891
|
data.result = result;
|
|
894
892
|
}
|
|
@@ -2632,6 +2630,10 @@ var agentsSchema = {
|
|
|
2632
2630
|
name: "description",
|
|
2633
2631
|
type: "text"
|
|
2634
2632
|
},
|
|
2633
|
+
{
|
|
2634
|
+
name: "providerApiKey",
|
|
2635
|
+
type: "text"
|
|
2636
|
+
},
|
|
2635
2637
|
{
|
|
2636
2638
|
name: "extensions",
|
|
2637
2639
|
type: "json"
|
|
@@ -3079,6 +3081,39 @@ var createUppyRoutes = async (app) => {
|
|
|
3079
3081
|
import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
|
|
3080
3082
|
import bodyParser from "body-parser";
|
|
3081
3083
|
import CryptoJS3 from "crypto-js";
|
|
3084
|
+
|
|
3085
|
+
// src/registry/utils/claude-messages.ts
|
|
3086
|
+
var CLAUDE_MESSAGES = {
|
|
3087
|
+
anthropic_token_variable_not_encrypted: `
|
|
3088
|
+
\x1B[41m -- Anthropic token variable set by your admin is not encrypted. This poses a security risk. Please contact your admin to fix the variable used for your key. --
|
|
3089
|
+
\x1B[0m`,
|
|
3090
|
+
anthropic_token_variable_not_found: `
|
|
3091
|
+
\x1B[41m -- Anthropic token variable not found. Please contact to fix the variable used for your key. --
|
|
3092
|
+
\x1B[0m`,
|
|
3093
|
+
authentication_error: `
|
|
3094
|
+
\x1B[41m -- Authentication error please check your IMP token and try again. --
|
|
3095
|
+
\x1B[0m`,
|
|
3096
|
+
missing_body: `
|
|
3097
|
+
\x1B[41m -- Missing body Anthropic response. --
|
|
3098
|
+
\x1B[0m`,
|
|
3099
|
+
missing_nextauth_secret: `
|
|
3100
|
+
\x1B[41m -- Missing NEXTAUTH_SECRET in environment variables on the server. --
|
|
3101
|
+
\x1B[0m`,
|
|
3102
|
+
not_enabled: `
|
|
3103
|
+
\x1B[31m
|
|
3104
|
+
\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
|
|
3105
|
+
\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
|
|
3106
|
+
\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
3107
|
+
\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
|
|
3108
|
+
\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
|
|
3109
|
+
\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
|
|
3110
|
+
Intelligence Management Platform
|
|
3111
|
+
\x1B[0m
|
|
3112
|
+
\x1B[41m -- Your account has not been enabled to use Claude Code, please contact your admin or enable Claude Code in the user settings. --
|
|
3113
|
+
\x1B[0m`
|
|
3114
|
+
};
|
|
3115
|
+
|
|
3116
|
+
// src/registry/routes.ts
|
|
3082
3117
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
3083
3118
|
var global_queues = {
|
|
3084
3119
|
logs_cleaner: "logs-cleaner"
|
|
@@ -3281,8 +3316,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3281
3316
|
name: agent.name,
|
|
3282
3317
|
id: agent.id,
|
|
3283
3318
|
description: agent.description,
|
|
3284
|
-
provider: backend?.model?.provider,
|
|
3285
|
-
model: backend?.model?.modelId,
|
|
3319
|
+
provider: backend?.model?.create({ apiKey: "" }).provider,
|
|
3320
|
+
model: backend?.model?.create({ apiKey: "" }).modelId,
|
|
3286
3321
|
active: agent.active,
|
|
3287
3322
|
public: agent.public,
|
|
3288
3323
|
type: agent.type,
|
|
@@ -3290,6 +3325,7 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
3290
3325
|
rateLimit: backend?.rateLimit,
|
|
3291
3326
|
streaming: backend?.streaming,
|
|
3292
3327
|
capabilities: backend?.capabilities,
|
|
3328
|
+
providerApiKey: agent.providerApiKey,
|
|
3293
3329
|
// todo add contexts
|
|
3294
3330
|
availableTools: tools,
|
|
3295
3331
|
enabledTools: agent.tools
|
|
@@ -4014,13 +4050,33 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4014
4050
|
return;
|
|
4015
4051
|
}
|
|
4016
4052
|
console.log("[EXULU] agent tools", agentInstance.tools);
|
|
4017
|
-
const enabledTools = agentInstance.tools.map((
|
|
4053
|
+
const enabledTools = agentInstance.tools.map(({ config, toolId }) => tools.find(({ id }) => id === toolId)).filter(Boolean);
|
|
4018
4054
|
console.log("[EXULU] enabled tools", enabledTools);
|
|
4055
|
+
const variableName = agentInstance.providerApiKey;
|
|
4056
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
4057
|
+
if (!variable) {
|
|
4058
|
+
res.status(400).json({
|
|
4059
|
+
message: "Provider API key variable not found."
|
|
4060
|
+
});
|
|
4061
|
+
return;
|
|
4062
|
+
}
|
|
4063
|
+
let providerApiKey = variable.value;
|
|
4064
|
+
if (!variable.encrypted) {
|
|
4065
|
+
res.status(400).json({
|
|
4066
|
+
message: "Provider API key variable not encrypted, for security reasons you are only allowed to use encrypted variables for provider API keys."
|
|
4067
|
+
});
|
|
4068
|
+
return;
|
|
4069
|
+
}
|
|
4070
|
+
if (variable.encrypted) {
|
|
4071
|
+
const bytes = CryptoJS3.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
4072
|
+
providerApiKey = bytes.toString(CryptoJS3.enc.Utf8);
|
|
4073
|
+
}
|
|
4019
4074
|
if (!!stream) {
|
|
4020
4075
|
const result = agent.generateStream({
|
|
4021
4076
|
messages: req.body.messages,
|
|
4022
4077
|
tools: enabledTools,
|
|
4023
|
-
|
|
4078
|
+
providerApiKey,
|
|
4079
|
+
toolConfigs: agentInstance.tools,
|
|
4024
4080
|
statistics: {
|
|
4025
4081
|
label: agent.name,
|
|
4026
4082
|
trigger: "agent"
|
|
@@ -4032,7 +4088,8 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
|
|
|
4032
4088
|
const response = await agent.generateSync({
|
|
4033
4089
|
messages: req.body.messages,
|
|
4034
4090
|
tools: enabledTools.map((tool2) => tool2.tool),
|
|
4035
|
-
|
|
4091
|
+
providerApiKey,
|
|
4092
|
+
toolConfigs: agentInstance.tools,
|
|
4036
4093
|
statistics: {
|
|
4037
4094
|
label: agent.name,
|
|
4038
4095
|
trigger: "agent"
|
|
@@ -4646,8 +4703,7 @@ var claudeCodeAgent = new ExuluAgent({
|
|
|
4646
4703
|
});
|
|
4647
4704
|
|
|
4648
4705
|
// src/templates/agents/claude-opus-4.ts
|
|
4649
|
-
import {
|
|
4650
|
-
import { z as z3 } from "zod";
|
|
4706
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
4651
4707
|
var agentId2 = "5434-5678-9143-2590";
|
|
4652
4708
|
var defaultAgent = new ExuluAgent({
|
|
4653
4709
|
id: `${agentId2}-default-claude-4-opus-agent`,
|
|
@@ -4665,17 +4721,21 @@ var defaultAgent = new ExuluAgent({
|
|
|
4665
4721
|
config: {
|
|
4666
4722
|
name: `Default agent`,
|
|
4667
4723
|
instructions: "You are a helpful assistant.",
|
|
4668
|
-
model:
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4724
|
+
model: {
|
|
4725
|
+
create: ({ apiKey }) => {
|
|
4726
|
+
const anthropic2 = createAnthropic({
|
|
4727
|
+
apiKey
|
|
4728
|
+
});
|
|
4729
|
+
return anthropic2("claude-4-opus-20250514");
|
|
4730
|
+
}
|
|
4731
|
+
// todo add a field of type string that adds a dropdown list from which the user can select the model
|
|
4732
|
+
// todo for each model, check which provider is used, and require the admin to add one or multiple
|
|
4733
|
+
// API keys for the provider (which we can then auto-rotate).
|
|
4734
|
+
// todo also add custom fields for rate limiting, so the admin can set custom rate limits for the agent
|
|
4735
|
+
// and allow him/her to decide if the rate limit is per user or per agent.
|
|
4736
|
+
// todo finally allow switching on or off immutable audit logs on the agent. Which then enables OTEL
|
|
4737
|
+
// and stores the logs into the pre-defined storage.
|
|
4738
|
+
}
|
|
4679
4739
|
}
|
|
4680
4740
|
});
|
|
4681
4741
|
|