@exulu/backend 1.62.1 → 1.63.1
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/{catalog-BWE6SLE2.js → catalog-TBSPSN2N.js} +1 -1
- package/dist/{chunk-4TCN467I.js → chunk-IZOD2X2F.js} +88 -11
- package/dist/{chunk-ILAHW4UT.js → chunk-YCE44CMU.js} +14 -2
- package/dist/{convert-exulu-tools-to-ai-sdk-tools-FZ4ZCVBZ.js → convert-exulu-tools-to-ai-sdk-tools-THDKPKF3.js} +1 -1
- package/dist/index.cjs +196 -44
- package/dist/index.d.cts +17 -10
- package/dist/index.d.ts +17 -10
- package/dist/index.js +98 -35
- package/ee/rbac-resolver.ts +9 -1
- package/ee/rbac-update.ts +32 -1
- package/ee/schemas.ts +25 -0
- package/ee/workers.ts +1 -1
- package/package.json +1 -1
|
@@ -164,6 +164,7 @@ var checkRecordAccess = async (record, request, user) => {
|
|
|
164
164
|
const isPublic = record.rights_mode === "public";
|
|
165
165
|
const byUsers = record.rights_mode === "users";
|
|
166
166
|
const byRoles = record.rights_mode === "roles";
|
|
167
|
+
const byTeams = record.rights_mode === "teams";
|
|
167
168
|
const createdBy = typeof record.created_by === "string" ? record.created_by : record.created_by?.toString();
|
|
168
169
|
const isCreator = user ? createdBy === user.id.toString() : false;
|
|
169
170
|
const isAdmin = user ? user.super_admin : false;
|
|
@@ -209,6 +210,23 @@ var checkRecordAccess = async (record, request, user) => {
|
|
|
209
210
|
return true;
|
|
210
211
|
}
|
|
211
212
|
}
|
|
213
|
+
if (byTeams) {
|
|
214
|
+
if (!user) {
|
|
215
|
+
setRecordAccessCache(false);
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
hasAccess = record.RBAC?.teams?.find((x) => x.id === user.team?.id)?.rights || "none";
|
|
219
|
+
if (!hasAccess || hasAccess === "none" || hasAccess !== request) {
|
|
220
|
+
console.error(
|
|
221
|
+
`[EXULU] Your current team ${user.team?.name} does not have access to this record, current access type is: ${hasAccess}.`
|
|
222
|
+
);
|
|
223
|
+
setRecordAccessCache(false);
|
|
224
|
+
return false;
|
|
225
|
+
} else {
|
|
226
|
+
setRecordAccessCache(true);
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
212
230
|
setRecordAccessCache(false);
|
|
213
231
|
return false;
|
|
214
232
|
};
|
|
@@ -468,6 +486,12 @@ function buildTags(input) {
|
|
|
468
486
|
if (input.agent_name) {
|
|
469
487
|
candidates.push("agent_name_" + input.agent_name);
|
|
470
488
|
}
|
|
489
|
+
if (input.team_id) {
|
|
490
|
+
candidates.push("team_id_" + input.team_id);
|
|
491
|
+
}
|
|
492
|
+
if (input.team_name) {
|
|
493
|
+
candidates.push("team_name_" + input.team_name);
|
|
494
|
+
}
|
|
471
495
|
console.log("[EXULU] Candidates", candidates);
|
|
472
496
|
const out = [];
|
|
473
497
|
for (const candidate of candidates) {
|
|
@@ -571,17 +595,24 @@ var getLiteLLMProvider = ({
|
|
|
571
595
|
user,
|
|
572
596
|
role,
|
|
573
597
|
project,
|
|
574
|
-
agent
|
|
598
|
+
agent,
|
|
599
|
+
team
|
|
575
600
|
}) => {
|
|
576
601
|
if (_litellmProvider) return _litellmProvider;
|
|
577
602
|
const host = process.env.LITELLM_HOST ?? "127.0.0.1";
|
|
578
603
|
const port = process.env.LITELLM_PORT ?? "4000";
|
|
579
604
|
const masterKey = process.env.LITELLM_MASTER_KEY;
|
|
580
605
|
const tags = buildTags({
|
|
581
|
-
user,
|
|
582
|
-
role,
|
|
583
|
-
project,
|
|
584
|
-
agent
|
|
606
|
+
user_id: user?.id,
|
|
607
|
+
role_id: role?.id,
|
|
608
|
+
project_id: project?.id,
|
|
609
|
+
agent_id: agent?.id,
|
|
610
|
+
user_name: !user ? void 0 : user.type === "api" ? user.firstname ?? user.email : user.email,
|
|
611
|
+
role_name: role?.name,
|
|
612
|
+
project_name: project?.name,
|
|
613
|
+
agent_name: agent?.name,
|
|
614
|
+
team_id: team?.id,
|
|
615
|
+
team_name: team?.name
|
|
585
616
|
});
|
|
586
617
|
if (!masterKey) {
|
|
587
618
|
throw new ResolveModelError(
|
|
@@ -620,10 +651,11 @@ async function resolveModel(input) {
|
|
|
620
651
|
);
|
|
621
652
|
}
|
|
622
653
|
const litellm = getLiteLLMProvider({
|
|
623
|
-
user
|
|
624
|
-
role: user?.role
|
|
625
|
-
project
|
|
626
|
-
agent
|
|
654
|
+
user,
|
|
655
|
+
role: user?.role,
|
|
656
|
+
project,
|
|
657
|
+
agent,
|
|
658
|
+
team: user?.team
|
|
627
659
|
});
|
|
628
660
|
const languageModel2 = litellm(modelId);
|
|
629
661
|
const syntheticModel = {
|
|
@@ -765,12 +797,12 @@ var ExuluTool = class {
|
|
|
765
797
|
modelId: agent.model,
|
|
766
798
|
user,
|
|
767
799
|
providers,
|
|
768
|
-
agent
|
|
800
|
+
agent,
|
|
769
801
|
rbacBypass: true
|
|
770
802
|
});
|
|
771
803
|
providerapikey = resolved.apiKey;
|
|
772
804
|
}
|
|
773
|
-
const { convertExuluToolsToAiSdkTools: convertExuluToolsToAiSdkTools2 } = await import("./convert-exulu-tools-to-ai-sdk-tools-
|
|
805
|
+
const { convertExuluToolsToAiSdkTools: convertExuluToolsToAiSdkTools2 } = await import("./convert-exulu-tools-to-ai-sdk-tools-THDKPKF3.js");
|
|
774
806
|
const tools = await convertExuluToolsToAiSdkTools2(
|
|
775
807
|
[this],
|
|
776
808
|
[],
|
|
@@ -1233,6 +1265,12 @@ var authentication = async ({
|
|
|
1233
1265
|
user.role = role;
|
|
1234
1266
|
}
|
|
1235
1267
|
}
|
|
1268
|
+
if (user?.team) {
|
|
1269
|
+
const team = await db2.from("teams").select("*").where("id", user?.team).first();
|
|
1270
|
+
if (team) {
|
|
1271
|
+
user.team = team;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1236
1274
|
if (!user) {
|
|
1237
1275
|
return {
|
|
1238
1276
|
error: true,
|
|
@@ -2334,6 +2372,16 @@ var applyAccessControl = (table, query, user, field_prefix) => {
|
|
|
2334
2372
|
});
|
|
2335
2373
|
});
|
|
2336
2374
|
}
|
|
2375
|
+
if (user?.team) {
|
|
2376
|
+
const userTeamId = user.team.id;
|
|
2377
|
+
this.orWhere(function() {
|
|
2378
|
+
this.where(`${prefix}rights_mode`, "teams").whereExists(function() {
|
|
2379
|
+
this.select("*").from("rbac").whereRaw(
|
|
2380
|
+
"rbac.target_resource_id = " + (prefix ? prefix.slice(0, -1) : tableNamePlural) + ".id"
|
|
2381
|
+
).where("rbac.entity", table.name.singular).where("rbac.access_type", "Team").where("rbac.team_id", userTeamId);
|
|
2382
|
+
});
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2337
2385
|
});
|
|
2338
2386
|
} catch (error) {
|
|
2339
2387
|
console.error("Access control error:", error);
|
|
@@ -2546,6 +2594,26 @@ var rolesSchema = {
|
|
|
2546
2594
|
}
|
|
2547
2595
|
]
|
|
2548
2596
|
};
|
|
2597
|
+
var teamsSchema = {
|
|
2598
|
+
type: "teams",
|
|
2599
|
+
name: {
|
|
2600
|
+
plural: "teams",
|
|
2601
|
+
singular: "team"
|
|
2602
|
+
},
|
|
2603
|
+
fields: [
|
|
2604
|
+
{
|
|
2605
|
+
name: "name",
|
|
2606
|
+
type: "text",
|
|
2607
|
+
index: true,
|
|
2608
|
+
unique: true,
|
|
2609
|
+
required: true
|
|
2610
|
+
},
|
|
2611
|
+
{
|
|
2612
|
+
name: "description",
|
|
2613
|
+
type: "text"
|
|
2614
|
+
}
|
|
2615
|
+
]
|
|
2616
|
+
};
|
|
2549
2617
|
var statisticsSchema = {
|
|
2550
2618
|
type: "tracking",
|
|
2551
2619
|
name: {
|
|
@@ -2766,6 +2834,10 @@ var rbacSchema = {
|
|
|
2766
2834
|
name: "role_id",
|
|
2767
2835
|
type: "uuid"
|
|
2768
2836
|
},
|
|
2837
|
+
{
|
|
2838
|
+
name: "team_id",
|
|
2839
|
+
type: "uuid"
|
|
2840
|
+
},
|
|
2769
2841
|
{
|
|
2770
2842
|
name: "user_id",
|
|
2771
2843
|
type: "number"
|
|
@@ -3224,6 +3296,10 @@ var usersSchema = {
|
|
|
3224
3296
|
{
|
|
3225
3297
|
name: "role",
|
|
3226
3298
|
type: "uuid"
|
|
3299
|
+
},
|
|
3300
|
+
{
|
|
3301
|
+
name: "team",
|
|
3302
|
+
type: "uuid"
|
|
3227
3303
|
}
|
|
3228
3304
|
]
|
|
3229
3305
|
};
|
|
@@ -3502,6 +3578,7 @@ var coreSchemas = {
|
|
|
3502
3578
|
}
|
|
3503
3579
|
if (license["rbac"]) {
|
|
3504
3580
|
schemas.rolesSchema = () => addCoreFields(rolesSchema);
|
|
3581
|
+
schemas.teamsSchema = () => addCoreFields(teamsSchema);
|
|
3505
3582
|
schemas.rbacSchema = () => addCoreFields(rbacSchema);
|
|
3506
3583
|
}
|
|
3507
3584
|
if (license["evals"]) {
|
|
@@ -35,6 +35,8 @@ var fetchLiteLLMCatalog = async () => {
|
|
|
35
35
|
region: m.model_info?.region ?? null,
|
|
36
36
|
max_tokens: m.model_info?.max_tokens ?? null,
|
|
37
37
|
max_input_tokens: m.model_info?.max_input_tokens ?? null,
|
|
38
|
+
input_cost_per_million_tokens: m.model_info?.input_cost_per_token * 1e6,
|
|
39
|
+
output_cost_per_million_tokens: m.model_info?.output_cost_per_token * 1e6,
|
|
38
40
|
active: m.model_info?.active ?? true,
|
|
39
41
|
max_output_tokens: m.model_info?.max_output_tokens ?? null,
|
|
40
42
|
supports_vision: !!m.model_info?.supports_vision,
|
|
@@ -46,8 +48,18 @@ var fetchLiteLLMCatalog = async () => {
|
|
|
46
48
|
supports_edit: !!m.model_info?.supports_edit,
|
|
47
49
|
max_n: typeof m.model_info?.max_n === "number" ? m.model_info.max_n : null
|
|
48
50
|
}));
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
const map = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const item of items) {
|
|
53
|
+
const key = `${item.model_name}-${item.upstream_model}`;
|
|
54
|
+
if (map.has(key)) {
|
|
55
|
+
map.get(key).tags.push(...item.tags);
|
|
56
|
+
} else {
|
|
57
|
+
map.set(key, item);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const uniqueItems = Array.from(map.values());
|
|
61
|
+
_cache = { expiresAt: Date.now() + CACHE_TTL_MS, items: uniqueItems };
|
|
62
|
+
return uniqueItems.filter((m) => m.type !== "speech_to_text" && m.type !== "text_to_speech");
|
|
51
63
|
} catch (err) {
|
|
52
64
|
console.error("[EXULU] litellmCatalog: failed to fetch /model/info:", err);
|
|
53
65
|
return [];
|