@exulu/backend 1.27.0 → 1.27.2
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 +265 -247
- package/dist/index.js +265 -247
- package/package.json +1 -1
- package/patch-older-releases-readme.md +42 -0
package/dist/index.cjs
CHANGED
|
@@ -47,7 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
ExuluTool: () => ExuluTool2,
|
|
48
48
|
ExuluUtils: () => ExuluUtils,
|
|
49
49
|
ExuluVariables: () => ExuluVariables,
|
|
50
|
-
db: () =>
|
|
50
|
+
db: () => db2
|
|
51
51
|
});
|
|
52
52
|
module.exports = __toCommonJS(index_exports);
|
|
53
53
|
var import_config = require("dotenv/config");
|
|
@@ -444,7 +444,7 @@ var authentication = async ({
|
|
|
444
444
|
apikey,
|
|
445
445
|
authtoken,
|
|
446
446
|
internalkey,
|
|
447
|
-
db:
|
|
447
|
+
db: db3
|
|
448
448
|
}) => {
|
|
449
449
|
if (internalkey) {
|
|
450
450
|
if (!process.env.INTERNAL_SECRET) {
|
|
@@ -490,9 +490,9 @@ var authentication = async ({
|
|
|
490
490
|
code: 401
|
|
491
491
|
};
|
|
492
492
|
}
|
|
493
|
-
const user = await
|
|
493
|
+
const user = await db3.from("users").select("*").where("email", authtoken?.email).first();
|
|
494
494
|
if (user?.role) {
|
|
495
|
-
const role = await
|
|
495
|
+
const role = await db3.from("roles").select("*").where("id", user?.role).first();
|
|
496
496
|
if (role) {
|
|
497
497
|
user.role = role;
|
|
498
498
|
}
|
|
@@ -519,7 +519,7 @@ var authentication = async ({
|
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
if (apikey) {
|
|
522
|
-
const users = await
|
|
522
|
+
const users = await db3.from("users").select("*").where("type", "api");
|
|
523
523
|
if (!users || users.length === 0) {
|
|
524
524
|
return {
|
|
525
525
|
error: true,
|
|
@@ -551,11 +551,11 @@ var authentication = async ({
|
|
|
551
551
|
const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
|
|
552
552
|
const isMatch = await import_bcryptjs.default.compare(request_key_compare_value, user_key_compare_value);
|
|
553
553
|
if (isMatch) {
|
|
554
|
-
await
|
|
554
|
+
await db3.from("users").where({ id: user.id }).update({
|
|
555
555
|
last_used: /* @__PURE__ */ new Date()
|
|
556
556
|
}).returning("id");
|
|
557
557
|
if (user?.role) {
|
|
558
|
-
const role = await
|
|
558
|
+
const role = await db3.from("roles").select("*").where("id", user?.role).first();
|
|
559
559
|
if (role) {
|
|
560
560
|
user.role = role;
|
|
561
561
|
}
|
|
@@ -585,7 +585,7 @@ var authentication = async ({
|
|
|
585
585
|
var requestValidators = {
|
|
586
586
|
authenticate: async (req) => {
|
|
587
587
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
588
|
-
const { db:
|
|
588
|
+
const { db: db3 } = await postgresClient();
|
|
589
589
|
let authtoken = null;
|
|
590
590
|
if (typeof apikey !== "string") {
|
|
591
591
|
authtoken = await getToken((req.headers["authorization"] || req.headers["x-api-key"]) ?? "");
|
|
@@ -593,7 +593,7 @@ var requestValidators = {
|
|
|
593
593
|
return await authentication({
|
|
594
594
|
authtoken,
|
|
595
595
|
apikey,
|
|
596
|
-
db:
|
|
596
|
+
db: db3
|
|
597
597
|
});
|
|
598
598
|
},
|
|
599
599
|
workflows: (req) => {
|
|
@@ -733,7 +733,7 @@ var requestValidators = {
|
|
|
733
733
|
};
|
|
734
734
|
|
|
735
735
|
// src/registry/utils/graphql.ts
|
|
736
|
-
var
|
|
736
|
+
var import_bcryptjs3 = __toESM(require("bcryptjs"), 1);
|
|
737
737
|
|
|
738
738
|
// src/postgres/core-schema.ts
|
|
739
739
|
var agentMessagesSchema = {
|
|
@@ -1432,10 +1432,10 @@ var getEnabledTools = async (agentInstance, allExuluTools, disabledTools = [], a
|
|
|
1432
1432
|
};
|
|
1433
1433
|
var loadAgentCache = /* @__PURE__ */ new Map();
|
|
1434
1434
|
var loadAgents = async () => {
|
|
1435
|
-
const { db:
|
|
1436
|
-
const agents = await
|
|
1435
|
+
const { db: db3 } = await postgresClient();
|
|
1436
|
+
const agents = await db3.from("agents");
|
|
1437
1437
|
for (const agent of agents) {
|
|
1438
|
-
const agentRbac = await RBACResolver(
|
|
1438
|
+
const agentRbac = await RBACResolver(db3, "agent", agent.id, agent.rights_mode || "private");
|
|
1439
1439
|
agent.RBAC = agentRbac;
|
|
1440
1440
|
loadAgentCache.set(agent.id, {
|
|
1441
1441
|
agent,
|
|
@@ -1450,11 +1450,11 @@ var loadAgent = async (id) => {
|
|
|
1450
1450
|
if (cachedAgent && cachedAgent.expiresAt > /* @__PURE__ */ new Date()) {
|
|
1451
1451
|
return cachedAgent.agent;
|
|
1452
1452
|
}
|
|
1453
|
-
const { db:
|
|
1454
|
-
const agentInstance = await
|
|
1453
|
+
const { db: db3 } = await postgresClient();
|
|
1454
|
+
const agentInstance = await db3.from("agents").where({
|
|
1455
1455
|
id
|
|
1456
1456
|
}).first();
|
|
1457
|
-
const agentRbac = await RBACResolver(
|
|
1457
|
+
const agentRbac = await RBACResolver(db3, "agent", agentInstance.id, agentInstance.rights_mode || "private");
|
|
1458
1458
|
agentInstance.RBAC = agentRbac;
|
|
1459
1459
|
if (!agentInstance) {
|
|
1460
1460
|
throw new Error("Agent instance not found.");
|
|
@@ -1540,6 +1540,59 @@ var checkRecordAccess = async (record, request, user) => {
|
|
|
1540
1540
|
return false;
|
|
1541
1541
|
};
|
|
1542
1542
|
|
|
1543
|
+
// src/auth/generate-key.ts
|
|
1544
|
+
var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
|
|
1545
|
+
var SALT_ROUNDS = 12;
|
|
1546
|
+
async function encryptString(string) {
|
|
1547
|
+
const hash = await import_bcryptjs2.default.hash(string, SALT_ROUNDS);
|
|
1548
|
+
return hash;
|
|
1549
|
+
}
|
|
1550
|
+
var generateApiKey = async (name, email) => {
|
|
1551
|
+
const { db: db3 } = await postgresClient();
|
|
1552
|
+
console.log("[EXULU] Inserting default user and admin role.");
|
|
1553
|
+
const existingRole = await db3.from("roles").where({ name: "admin" }).first();
|
|
1554
|
+
let roleId;
|
|
1555
|
+
if (!existingRole) {
|
|
1556
|
+
console.log("[EXULU] Creating default admin role.");
|
|
1557
|
+
const role = await db3.from("roles").insert({
|
|
1558
|
+
name: "admin",
|
|
1559
|
+
agents: "write",
|
|
1560
|
+
workflows: "write",
|
|
1561
|
+
variables: "write",
|
|
1562
|
+
users: "write"
|
|
1563
|
+
}).returning("id");
|
|
1564
|
+
roleId = role[0].id;
|
|
1565
|
+
} else {
|
|
1566
|
+
roleId = existingRole.id;
|
|
1567
|
+
}
|
|
1568
|
+
const newKeyName = name;
|
|
1569
|
+
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
1570
|
+
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
1571
|
+
const encryptedKey = await encryptString(plainKey);
|
|
1572
|
+
const existingApiUser = await db3.from("users").where({ email }).first();
|
|
1573
|
+
if (!existingApiUser) {
|
|
1574
|
+
console.log("[EXULU] Creating default api user.");
|
|
1575
|
+
await db3.from("users").insert({
|
|
1576
|
+
name,
|
|
1577
|
+
email,
|
|
1578
|
+
super_admin: true,
|
|
1579
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1580
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
1581
|
+
type: "api",
|
|
1582
|
+
emailVerified: /* @__PURE__ */ new Date(),
|
|
1583
|
+
apikey: `${encryptedKey}${postFix}`,
|
|
1584
|
+
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
1585
|
+
role: roleId
|
|
1586
|
+
});
|
|
1587
|
+
console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
|
|
1588
|
+
} else {
|
|
1589
|
+
console.log("[EXULU] API user with that name already exists.");
|
|
1590
|
+
}
|
|
1591
|
+
return {
|
|
1592
|
+
key: `${plainKey}${postFix}`
|
|
1593
|
+
};
|
|
1594
|
+
};
|
|
1595
|
+
|
|
1543
1596
|
// src/registry/utils/graphql.ts
|
|
1544
1597
|
var GraphQLDate = new import_graphql2.GraphQLScalarType({
|
|
1545
1598
|
name: "Date",
|
|
@@ -1761,10 +1814,10 @@ var getRequestedFields = (info) => {
|
|
|
1761
1814
|
}, {}));
|
|
1762
1815
|
return fields.filter((field) => field !== "pageInfo" && field !== "items" && field !== "RBAC");
|
|
1763
1816
|
};
|
|
1764
|
-
var handleRBACUpdate = async (
|
|
1817
|
+
var handleRBACUpdate = async (db3, entityName, resourceId, rbacData, existingRbacRecords) => {
|
|
1765
1818
|
const { users = [], roles = [], projects = [] } = rbacData;
|
|
1766
1819
|
if (!existingRbacRecords) {
|
|
1767
|
-
existingRbacRecords = await
|
|
1820
|
+
existingRbacRecords = await db3.from("rbac").where({
|
|
1768
1821
|
entity: entityName,
|
|
1769
1822
|
target_resource_id: resourceId
|
|
1770
1823
|
}).select("*");
|
|
@@ -1782,13 +1835,13 @@ var handleRBACUpdate = async (db4, entityName, resourceId, rbacData, existingRba
|
|
|
1782
1835
|
const rolesToRemove = existingRbacRecords.filter((r) => r.access_type === "Role" && !newRoleRecords.has(`${r.role_id}:${r.rights}`));
|
|
1783
1836
|
const projectsToRemove = existingRbacRecords.filter((r) => r.access_type === "Project" && !newProjectRecords.has(`${r.project_id}:${r.rights}`));
|
|
1784
1837
|
if (usersToRemove.length > 0) {
|
|
1785
|
-
await
|
|
1838
|
+
await db3.from("rbac").whereIn("id", usersToRemove.map((r) => r.id)).del();
|
|
1786
1839
|
}
|
|
1787
1840
|
if (rolesToRemove.length > 0) {
|
|
1788
|
-
await
|
|
1841
|
+
await db3.from("rbac").whereIn("id", rolesToRemove.map((r) => r.id)).del();
|
|
1789
1842
|
}
|
|
1790
1843
|
if (projectsToRemove.length > 0) {
|
|
1791
|
-
await
|
|
1844
|
+
await db3.from("rbac").whereIn("id", projectsToRemove.map((r) => r.id)).del();
|
|
1792
1845
|
}
|
|
1793
1846
|
const recordsToInsert = [];
|
|
1794
1847
|
usersToCreate.forEach((user) => {
|
|
@@ -1825,14 +1878,14 @@ var handleRBACUpdate = async (db4, entityName, resourceId, rbacData, existingRba
|
|
|
1825
1878
|
});
|
|
1826
1879
|
});
|
|
1827
1880
|
if (recordsToInsert.length > 0) {
|
|
1828
|
-
await
|
|
1881
|
+
await db3.from("rbac").insert(recordsToInsert);
|
|
1829
1882
|
}
|
|
1830
1883
|
};
|
|
1831
1884
|
function createMutations(table, agents, contexts, tools, config) {
|
|
1832
1885
|
const tableNamePlural = table.name.plural.toLowerCase();
|
|
1833
1886
|
const validateWriteAccess = async (id, context) => {
|
|
1834
1887
|
try {
|
|
1835
|
-
const { db:
|
|
1888
|
+
const { db: db3, req, user } = context;
|
|
1836
1889
|
if (user.super_admin === true) {
|
|
1837
1890
|
return true;
|
|
1838
1891
|
}
|
|
@@ -1844,7 +1897,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1844
1897
|
if (!hasRBAC) {
|
|
1845
1898
|
return true;
|
|
1846
1899
|
}
|
|
1847
|
-
const record = await
|
|
1900
|
+
const record = await db3.from(tableNamePlural).select(["rights_mode", "created_by"]).where({ id }).first();
|
|
1848
1901
|
if (!record) {
|
|
1849
1902
|
throw new Error("Record not found");
|
|
1850
1903
|
}
|
|
@@ -1863,7 +1916,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1863
1916
|
throw new Error("Only the creator can edit this private record");
|
|
1864
1917
|
}
|
|
1865
1918
|
if (record.rights_mode === "users") {
|
|
1866
|
-
const rbacRecord = await
|
|
1919
|
+
const rbacRecord = await db3.from("rbac").where({
|
|
1867
1920
|
entity: table.name.singular,
|
|
1868
1921
|
target_resource_id: id,
|
|
1869
1922
|
access_type: "User",
|
|
@@ -1876,7 +1929,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1876
1929
|
throw new Error("Insufficient user permissions to edit this record");
|
|
1877
1930
|
}
|
|
1878
1931
|
if (record.rights_mode === "roles" && user.role) {
|
|
1879
|
-
const rbacRecord = await
|
|
1932
|
+
const rbacRecord = await db3.from("rbac").where({
|
|
1880
1933
|
entity: table.name.singular,
|
|
1881
1934
|
target_resource_id: id,
|
|
1882
1935
|
access_type: "Role",
|
|
@@ -1889,7 +1942,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1889
1942
|
throw new Error("Insufficient role permissions to edit this record");
|
|
1890
1943
|
}
|
|
1891
1944
|
if (record.rights_mode === "projects") {
|
|
1892
|
-
const projects = await
|
|
1945
|
+
const projects = await db3.from("rbac").where({
|
|
1893
1946
|
entity: table.name.singular,
|
|
1894
1947
|
target_resource_id: id,
|
|
1895
1948
|
access_type: "Project",
|
|
@@ -1903,7 +1956,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1903
1956
|
return false;
|
|
1904
1957
|
}
|
|
1905
1958
|
if (project.rights_mode === "users") {
|
|
1906
|
-
const rbacRecord = await
|
|
1959
|
+
const rbacRecord = await db3.from("rbac").where({
|
|
1907
1960
|
entity: "project",
|
|
1908
1961
|
target_resource_id: project.id,
|
|
1909
1962
|
access_type: "User",
|
|
@@ -1916,7 +1969,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1916
1969
|
return false;
|
|
1917
1970
|
}
|
|
1918
1971
|
if (record.rights_mode === "roles" && user.role) {
|
|
1919
|
-
const rbacRecord = await
|
|
1972
|
+
const rbacRecord = await db3.from("rbac").where({
|
|
1920
1973
|
entity: "project",
|
|
1921
1974
|
target_resource_id: project.id,
|
|
1922
1975
|
access_type: "Role",
|
|
@@ -1942,9 +1995,8 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1942
1995
|
};
|
|
1943
1996
|
const mutations = {
|
|
1944
1997
|
[`${tableNamePlural}CreateOne`]: async (_, args, context, info) => {
|
|
1945
|
-
const { db:
|
|
1998
|
+
const { db: db3 } = context;
|
|
1946
1999
|
const requestedFields = getRequestedFields(info);
|
|
1947
|
-
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
1948
2000
|
let { input } = args;
|
|
1949
2001
|
const rbacData = input.RBAC;
|
|
1950
2002
|
delete input.RBAC;
|
|
@@ -1957,7 +2009,9 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1957
2009
|
throw new Error("You are not authorized to create users");
|
|
1958
2010
|
}
|
|
1959
2011
|
if (table.name.singular === "user" && input.password) {
|
|
1960
|
-
|
|
2012
|
+
console.log("[EXULU] Hashing password", input.password);
|
|
2013
|
+
input.password = await import_bcryptjs3.default.hash(input.password, SALT_ROUNDS);
|
|
2014
|
+
console.log("[EXULU] Hashed password", input.password);
|
|
1961
2015
|
}
|
|
1962
2016
|
Object.keys(input).forEach((key) => {
|
|
1963
2017
|
if (table.fields.find((field) => field.name === key)?.type === "json") {
|
|
@@ -1967,10 +2021,13 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1967
2021
|
}
|
|
1968
2022
|
});
|
|
1969
2023
|
if (!input.id) {
|
|
1970
|
-
|
|
2024
|
+
const idField = table.fields.find((field) => field.name === "id");
|
|
2025
|
+
if (!idField || idField?.type !== "number") {
|
|
2026
|
+
input.id = db3.fn.uuid();
|
|
2027
|
+
}
|
|
1971
2028
|
}
|
|
1972
|
-
const columns = await
|
|
1973
|
-
const insert =
|
|
2029
|
+
const columns = await db3(tableNamePlural).columnInfo();
|
|
2030
|
+
const insert = db3(tableNamePlural).insert({
|
|
1974
2031
|
...input,
|
|
1975
2032
|
...table.RBAC ? { rights_mode: "private" } : {}
|
|
1976
2033
|
}).returning(Object.keys(columns));
|
|
@@ -1979,7 +2036,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1979
2036
|
}
|
|
1980
2037
|
let results = await insert;
|
|
1981
2038
|
if (table.RBAC && rbacData && results[0]) {
|
|
1982
|
-
await handleRBACUpdate(
|
|
2039
|
+
await handleRBACUpdate(db3, table.name.singular, results[0].id, rbacData, []);
|
|
1983
2040
|
}
|
|
1984
2041
|
const { job } = await postprocessUpdate({
|
|
1985
2042
|
table,
|
|
@@ -1999,13 +2056,18 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
1999
2056
|
};
|
|
2000
2057
|
},
|
|
2001
2058
|
[`${tableNamePlural}UpdateOne`]: async (_, args, context, info) => {
|
|
2002
|
-
const { db:
|
|
2059
|
+
const { db: db3, req } = context;
|
|
2003
2060
|
let { where, input } = args;
|
|
2004
2061
|
await validateCreateOrRemoveSuperAdminPermission(tableNamePlural, input, req);
|
|
2005
2062
|
const rbacData = input.RBAC;
|
|
2006
2063
|
delete input.RBAC;
|
|
2007
2064
|
delete input.created_by;
|
|
2008
2065
|
input = encryptSensitiveFields(input);
|
|
2066
|
+
if (table.name.singular === "user" && input.password) {
|
|
2067
|
+
console.log("[EXULU] Hashing password", input.password);
|
|
2068
|
+
input.password = await import_bcryptjs3.default.hash(input.password, SALT_ROUNDS);
|
|
2069
|
+
console.log("[EXULU] Hashed password", input.password);
|
|
2070
|
+
}
|
|
2009
2071
|
Object.keys(input).forEach((key) => {
|
|
2010
2072
|
if (table.fields.find((field) => field.name === key)?.type === "json") {
|
|
2011
2073
|
if (typeof input[key] === "object" || Array.isArray(input[key])) {
|
|
@@ -2015,13 +2077,13 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2015
2077
|
});
|
|
2016
2078
|
const requestedFields = getRequestedFields(info);
|
|
2017
2079
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2018
|
-
const item = await
|
|
2080
|
+
const item = await db3.from(tableNamePlural).select(sanitizedFields).where(where).first();
|
|
2019
2081
|
if (!item) {
|
|
2020
2082
|
throw new Error("Record not found");
|
|
2021
2083
|
}
|
|
2022
2084
|
await validateWriteAccess(item.id, context);
|
|
2023
|
-
const columns = await
|
|
2024
|
-
const result = await
|
|
2085
|
+
const columns = await db3(tableNamePlural).columnInfo();
|
|
2086
|
+
const result = await db3(tableNamePlural).where({ id: item.id }).update({
|
|
2025
2087
|
...input,
|
|
2026
2088
|
updatedAt: /* @__PURE__ */ new Date()
|
|
2027
2089
|
}).returning(Object.keys(columns));
|
|
@@ -2029,20 +2091,20 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2029
2091
|
throw new Error("Something went wrong with the update, no id returned.");
|
|
2030
2092
|
}
|
|
2031
2093
|
if (table.RBAC && rbacData && result.id) {
|
|
2032
|
-
const existingRbacRecords = await
|
|
2094
|
+
const existingRbacRecords = await db3.from("rbac").where({
|
|
2033
2095
|
entity: table.name.singular,
|
|
2034
2096
|
target_resource_id: result.id
|
|
2035
2097
|
}).select("*");
|
|
2036
|
-
await handleRBACUpdate(
|
|
2098
|
+
await handleRBACUpdate(db3, table.name.singular, result.id, rbacData, existingRbacRecords);
|
|
2037
2099
|
}
|
|
2038
|
-
const { job } = await postprocessUpdate({ table, requestedFields, agents, contexts, tools, result, user: context.user.id, role: context.user.role?.id });
|
|
2100
|
+
const { job } = await postprocessUpdate({ table, requestedFields, agents, contexts, tools, result, user: context.user.id, role: context.user.role?.id, config });
|
|
2039
2101
|
return {
|
|
2040
2102
|
item: finalizeRequestedFields({ table, requestedFields, agents, contexts, tools, result, user: context.user.id }),
|
|
2041
2103
|
job
|
|
2042
2104
|
};
|
|
2043
2105
|
},
|
|
2044
2106
|
[`${tableNamePlural}UpdateOneById`]: async (_, args, context, info) => {
|
|
2045
|
-
const { db:
|
|
2107
|
+
const { db: db3, req } = context;
|
|
2046
2108
|
let { id, input } = args;
|
|
2047
2109
|
await validateCreateOrRemoveSuperAdminPermission(tableNamePlural, input, req);
|
|
2048
2110
|
await validateWriteAccess(id, context);
|
|
@@ -2050,6 +2112,11 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2050
2112
|
delete input.RBAC;
|
|
2051
2113
|
delete input.created_by;
|
|
2052
2114
|
input = encryptSensitiveFields(input);
|
|
2115
|
+
if (table.name.singular === "user" && input.password) {
|
|
2116
|
+
console.log("[EXULU] Hashing password", input.password);
|
|
2117
|
+
input.password = await import_bcryptjs3.default.hash(input.password, SALT_ROUNDS);
|
|
2118
|
+
console.log("[EXULU] Hashed password", input.password);
|
|
2119
|
+
}
|
|
2053
2120
|
Object.keys(input).forEach((key) => {
|
|
2054
2121
|
if (table.fields.find((field) => field.name === key)?.type === "json") {
|
|
2055
2122
|
if (typeof input[key] === "object" || Array.isArray(input[key])) {
|
|
@@ -2057,21 +2124,21 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2057
2124
|
}
|
|
2058
2125
|
}
|
|
2059
2126
|
});
|
|
2060
|
-
await
|
|
2127
|
+
await db3(tableNamePlural).where({ id }).update({
|
|
2061
2128
|
...input,
|
|
2062
2129
|
updatedAt: /* @__PURE__ */ new Date()
|
|
2063
2130
|
});
|
|
2064
2131
|
if (table.RBAC && rbacData) {
|
|
2065
|
-
const existingRbacRecords = await
|
|
2132
|
+
const existingRbacRecords = await db3.from("rbac").where({
|
|
2066
2133
|
entity: table.name.singular,
|
|
2067
2134
|
target_resource_id: id
|
|
2068
2135
|
}).select("*");
|
|
2069
|
-
await handleRBACUpdate(
|
|
2136
|
+
await handleRBACUpdate(db3, table.name.singular, id, rbacData, existingRbacRecords);
|
|
2070
2137
|
}
|
|
2071
2138
|
const requestedFields = getRequestedFields(info);
|
|
2072
|
-
const columns = await
|
|
2073
|
-
const result = await
|
|
2074
|
-
const { job } = await postprocessUpdate({ table, requestedFields, agents, contexts, tools, result, user: context.user.id, role: context.user.role?.id });
|
|
2139
|
+
const columns = await db3(tableNamePlural).columnInfo();
|
|
2140
|
+
const result = await db3.from(tableNamePlural).select(Object.keys(columns)).where({ id }).first();
|
|
2141
|
+
const { job } = await postprocessUpdate({ table, requestedFields, agents, contexts, tools, result, user: context.user.id, role: context.user.role?.id, config });
|
|
2075
2142
|
return {
|
|
2076
2143
|
item: finalizeRequestedFields({ table, requestedFields, agents, contexts, tools, result, user: context.user.id }),
|
|
2077
2144
|
job
|
|
@@ -2079,11 +2146,11 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2079
2146
|
},
|
|
2080
2147
|
[`${tableNamePlural}RemoveOneById`]: async (_, args, context, info) => {
|
|
2081
2148
|
const { id } = args;
|
|
2082
|
-
const { db:
|
|
2149
|
+
const { db: db3 } = context;
|
|
2083
2150
|
await validateWriteAccess(id, context);
|
|
2084
2151
|
const requestedFields = getRequestedFields(info);
|
|
2085
2152
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2086
|
-
const result = await
|
|
2153
|
+
const result = await db3.from(tableNamePlural).select(sanitizedFields).where({ id }).first();
|
|
2087
2154
|
if (!result) {
|
|
2088
2155
|
throw new Error("Record not found");
|
|
2089
2156
|
}
|
|
@@ -2094,12 +2161,12 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2094
2161
|
}
|
|
2095
2162
|
const chunksTableExists = await context2.chunksTableExists();
|
|
2096
2163
|
if (chunksTableExists) {
|
|
2097
|
-
await
|
|
2164
|
+
await db3.from(getChunksTableName(context2.id)).where({ source: result.id }).del();
|
|
2098
2165
|
}
|
|
2099
2166
|
}
|
|
2100
|
-
await
|
|
2167
|
+
await db3(tableNamePlural).where({ id }).del();
|
|
2101
2168
|
if (table.RBAC) {
|
|
2102
|
-
await
|
|
2169
|
+
await db3.from("rbac").where({
|
|
2103
2170
|
entity: table.name.singular,
|
|
2104
2171
|
target_resource_id: id
|
|
2105
2172
|
}).del();
|
|
@@ -2109,10 +2176,10 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2109
2176
|
},
|
|
2110
2177
|
[`${tableNamePlural}RemoveOne`]: async (_, args, context, info) => {
|
|
2111
2178
|
const { where } = args;
|
|
2112
|
-
const { db:
|
|
2179
|
+
const { db: db3 } = context;
|
|
2113
2180
|
const requestedFields = getRequestedFields(info);
|
|
2114
2181
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2115
|
-
const result = await
|
|
2182
|
+
const result = await db3.from(tableNamePlural).select(sanitizedFields).where(where).first();
|
|
2116
2183
|
if (!result) {
|
|
2117
2184
|
throw new Error("Record not found");
|
|
2118
2185
|
}
|
|
@@ -2124,10 +2191,10 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2124
2191
|
}
|
|
2125
2192
|
const chunksTableExists = await context2.chunksTableExists();
|
|
2126
2193
|
if (chunksTableExists) {
|
|
2127
|
-
await
|
|
2194
|
+
await db3.from(getChunksTableName(context2.id)).where({ source: result.id }).del();
|
|
2128
2195
|
}
|
|
2129
2196
|
}
|
|
2130
|
-
await
|
|
2197
|
+
await db3(tableNamePlural).where(where).del();
|
|
2131
2198
|
await postprocessDeletion({ table, requestedFields, agents, contexts, tools, result });
|
|
2132
2199
|
return finalizeRequestedFields({ table, requestedFields, agents, contexts, tools, result, user: context.user.id });
|
|
2133
2200
|
}
|
|
@@ -2157,8 +2224,8 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2157
2224
|
if (!field.processor) {
|
|
2158
2225
|
throw new Error(`Processor not set for field ${args.field} in context ${exists.id}.`);
|
|
2159
2226
|
}
|
|
2160
|
-
const { db:
|
|
2161
|
-
let query =
|
|
2227
|
+
const { db: db3 } = context;
|
|
2228
|
+
let query = db3.from(tableNamePlural).select("*").where({ id: args.item });
|
|
2162
2229
|
query = applyAccessControl(table, context.user, query);
|
|
2163
2230
|
const item = await query.first();
|
|
2164
2231
|
if (!item) {
|
|
@@ -2183,15 +2250,15 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2183
2250
|
if (!context.user?.super_admin) {
|
|
2184
2251
|
throw new Error("You are not authorized to delete chunks via API, user must be super admin.");
|
|
2185
2252
|
}
|
|
2186
|
-
const { db:
|
|
2253
|
+
const { db: db3 } = await postgresClient();
|
|
2187
2254
|
const exists = contexts.find((context2) => context2.id === table.id);
|
|
2188
2255
|
if (!exists) {
|
|
2189
2256
|
throw new Error(`Context ${table.id} not found.`);
|
|
2190
2257
|
}
|
|
2191
2258
|
const { id, embeddings } = exists;
|
|
2192
2259
|
const mainTable = getTableName(id);
|
|
2193
|
-
const columns = await
|
|
2194
|
-
let query =
|
|
2260
|
+
const columns = await db3(mainTable).columnInfo();
|
|
2261
|
+
let query = db3.from(mainTable).select(Object.keys(columns));
|
|
2195
2262
|
if (!args.where) {
|
|
2196
2263
|
const {
|
|
2197
2264
|
jobs: jobs2,
|
|
@@ -2234,12 +2301,12 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2234
2301
|
if (!context.user?.super_admin) {
|
|
2235
2302
|
throw new Error("You are not authorized to delete chunks via API, user must be super admin.");
|
|
2236
2303
|
}
|
|
2237
|
-
const { db:
|
|
2304
|
+
const { db: db3 } = await postgresClient();
|
|
2238
2305
|
const id = contexts.find((context2) => context2.id === table.id)?.id;
|
|
2239
2306
|
if (!id) {
|
|
2240
2307
|
throw new Error(`Context ${table.id} not found.`);
|
|
2241
2308
|
}
|
|
2242
|
-
let query =
|
|
2309
|
+
let query = db3.from(getTableName(id)).select("id");
|
|
2243
2310
|
if (args.where) {
|
|
2244
2311
|
query = applyFilters(query, args.where);
|
|
2245
2312
|
}
|
|
@@ -2248,7 +2315,7 @@ function createMutations(table, agents, contexts, tools, config) {
|
|
|
2248
2315
|
throw new Error("No items found to delete chunks for.");
|
|
2249
2316
|
}
|
|
2250
2317
|
for (const item of items) {
|
|
2251
|
-
await
|
|
2318
|
+
await db3.from(getChunksTableName(id)).where({ source: item.id }).delete();
|
|
2252
2319
|
}
|
|
2253
2320
|
return {
|
|
2254
2321
|
message: "Chunks deleted successfully.",
|
|
@@ -2265,16 +2332,19 @@ var applyAccessControl = (table, user, query) => {
|
|
|
2265
2332
|
query = query.where("created_by", user.id);
|
|
2266
2333
|
return query;
|
|
2267
2334
|
}
|
|
2268
|
-
const hasRBAC = table.RBAC === true;
|
|
2269
|
-
if (!hasRBAC) {
|
|
2270
|
-
return query;
|
|
2271
|
-
}
|
|
2272
2335
|
if (table.name.plural !== "agent_sessions" && user.super_admin === true) {
|
|
2273
2336
|
return query;
|
|
2274
2337
|
}
|
|
2338
|
+
console.log("[EXULU] user.role", user.role);
|
|
2339
|
+
console.log("[EXULU] table.name.plural", table.name.plural);
|
|
2275
2340
|
if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
|
|
2276
2341
|
console.error("==== Access control error: no role found or no access to entity type. ====");
|
|
2277
|
-
return query.where("
|
|
2342
|
+
return query.where("id", "=", "0");
|
|
2343
|
+
}
|
|
2344
|
+
const hasRBAC = table.RBAC === true;
|
|
2345
|
+
console.log("[EXULU] hasRBAC", hasRBAC);
|
|
2346
|
+
if (!hasRBAC) {
|
|
2347
|
+
return query;
|
|
2278
2348
|
}
|
|
2279
2349
|
try {
|
|
2280
2350
|
query = query.where(function() {
|
|
@@ -2451,9 +2521,9 @@ var postprocessUpdate = async ({
|
|
|
2451
2521
|
if (!context.embedder) {
|
|
2452
2522
|
return result;
|
|
2453
2523
|
}
|
|
2454
|
-
const { db:
|
|
2524
|
+
const { db: db3 } = await postgresClient();
|
|
2455
2525
|
console.log("[EXULU] Deleting chunks for item", result.id);
|
|
2456
|
-
await
|
|
2526
|
+
await db3.from(getChunksTableName(context.id)).where({ source: result.id }).delete();
|
|
2457
2527
|
console.log("[EXULU] Deleted chunks for item", result.id);
|
|
2458
2528
|
console.log("[EXULU] Embedder", context.embedder);
|
|
2459
2529
|
console.log("[EXULU] Configuration", context.configuration);
|
|
@@ -2503,11 +2573,11 @@ var postprocessDeletion = async ({
|
|
|
2503
2573
|
if (!context.embedder) {
|
|
2504
2574
|
return result;
|
|
2505
2575
|
}
|
|
2506
|
-
const { db:
|
|
2576
|
+
const { db: db3 } = await postgresClient();
|
|
2507
2577
|
console.log("[EXULU] Deleting chunks for item", result.id);
|
|
2508
|
-
const chunks = await
|
|
2578
|
+
const chunks = await db3.from(getChunksTableName(context.id)).where({ source: result.id }).select("id");
|
|
2509
2579
|
if (chunks.length > 0) {
|
|
2510
|
-
await
|
|
2580
|
+
await db3.from(getChunksTableName(context.id)).where({ source: result.id }).delete();
|
|
2511
2581
|
}
|
|
2512
2582
|
return result;
|
|
2513
2583
|
}
|
|
@@ -2554,10 +2624,10 @@ var finalizeRequestedFields = async ({
|
|
|
2554
2624
|
result.chunks = [];
|
|
2555
2625
|
return result;
|
|
2556
2626
|
}
|
|
2557
|
-
const { db:
|
|
2558
|
-
const query =
|
|
2627
|
+
const { db: db3 } = await postgresClient();
|
|
2628
|
+
const query = db3.from(getChunksTableName(context.id)).where({ source: result.id }).select("id", "content", "source", "chunk_index", "createdAt", "updatedAt");
|
|
2559
2629
|
query.select(
|
|
2560
|
-
|
|
2630
|
+
db3.raw("vector_dims(??) as embedding_size", [`embedding`])
|
|
2561
2631
|
);
|
|
2562
2632
|
const chunks = await query;
|
|
2563
2633
|
result.chunks = chunks.map((chunk) => ({
|
|
@@ -2608,29 +2678,29 @@ function createQueries(table, agents, tools, contexts) {
|
|
|
2608
2678
|
const tableNameSingular = table.name.singular.toLowerCase();
|
|
2609
2679
|
const queries = {
|
|
2610
2680
|
[`${tableNameSingular}ById`]: async (_, args, context, info) => {
|
|
2611
|
-
const { db:
|
|
2681
|
+
const { db: db3 } = context;
|
|
2612
2682
|
const requestedFields = getRequestedFields(info);
|
|
2613
2683
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2614
|
-
let query =
|
|
2684
|
+
let query = db3.from(tableNamePlural).select(sanitizedFields).where({ id: args.id });
|
|
2615
2685
|
query = applyAccessControl(table, context.user, query);
|
|
2616
2686
|
let result = await query.first();
|
|
2617
2687
|
return finalizeRequestedFields({ table, requestedFields, agents, contexts, tools, result, user: context.user });
|
|
2618
2688
|
},
|
|
2619
2689
|
[`${tableNameSingular}ByIds`]: async (_, args, context, info) => {
|
|
2620
|
-
const { db:
|
|
2690
|
+
const { db: db3 } = context;
|
|
2621
2691
|
const requestedFields = getRequestedFields(info);
|
|
2622
2692
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2623
|
-
let query =
|
|
2693
|
+
let query = db3.from(tableNamePlural).select(sanitizedFields).whereIn("id", args.ids);
|
|
2624
2694
|
query = applyAccessControl(table, context.user, query);
|
|
2625
2695
|
let result = await query;
|
|
2626
2696
|
return finalizeRequestedFields({ table, requestedFields, agents, contexts, tools, result, user: context.user });
|
|
2627
2697
|
},
|
|
2628
2698
|
[`${tableNameSingular}One`]: async (_, args, context, info) => {
|
|
2629
2699
|
const { filters = [], sort } = args;
|
|
2630
|
-
const { db:
|
|
2700
|
+
const { db: db3 } = context;
|
|
2631
2701
|
const requestedFields = getRequestedFields(info);
|
|
2632
2702
|
const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
|
|
2633
|
-
let query =
|
|
2703
|
+
let query = db3.from(tableNamePlural).select(sanitizedFields);
|
|
2634
2704
|
query = applyFilters(query, filters);
|
|
2635
2705
|
query = applyAccessControl(table, context.user, query);
|
|
2636
2706
|
query = applySorting(query, sort);
|
|
@@ -2639,11 +2709,11 @@ function createQueries(table, agents, tools, contexts) {
|
|
|
2639
2709
|
},
|
|
2640
2710
|
[`${tableNamePlural}Pagination`]: async (_, args, context, info) => {
|
|
2641
2711
|
const { limit = 10, page = 0, filters = [], sort } = args;
|
|
2642
|
-
const { db:
|
|
2712
|
+
const { db: db3 } = context;
|
|
2643
2713
|
if (limit > 500) {
|
|
2644
2714
|
throw new Error("Limit cannot be greater than 500.");
|
|
2645
2715
|
}
|
|
2646
|
-
let countQuery =
|
|
2716
|
+
let countQuery = db3(tableNamePlural);
|
|
2647
2717
|
countQuery = applyFilters(countQuery, filters);
|
|
2648
2718
|
countQuery = applyAccessControl(table, context.user, countQuery);
|
|
2649
2719
|
const countResult = await countQuery.count("* as count");
|
|
@@ -2652,7 +2722,7 @@ function createQueries(table, agents, tools, contexts) {
|
|
|
2652
2722
|
const currentPage = page;
|
|
2653
2723
|
const hasPreviousPage = currentPage > 1;
|
|
2654
2724
|
const hasNextPage = currentPage < pageCount - 1;
|
|
2655
|
-
let dataQuery =
|
|
2725
|
+
let dataQuery = db3(tableNamePlural);
|
|
2656
2726
|
dataQuery = applyFilters(dataQuery, filters);
|
|
2657
2727
|
dataQuery = applyAccessControl(table, context.user, dataQuery);
|
|
2658
2728
|
const requestedFields = getRequestedFields(info);
|
|
@@ -2676,8 +2746,8 @@ function createQueries(table, agents, tools, contexts) {
|
|
|
2676
2746
|
// Add generic statistics query for all tables
|
|
2677
2747
|
[`${tableNamePlural}Statistics`]: async (_, args, context, info) => {
|
|
2678
2748
|
const { filters = [], groupBy } = args;
|
|
2679
|
-
const { db:
|
|
2680
|
-
let query =
|
|
2749
|
+
const { db: db3 } = context;
|
|
2750
|
+
let query = db3(tableNamePlural);
|
|
2681
2751
|
query = applyFilters(query, filters);
|
|
2682
2752
|
query = applyAccessControl(table, context.user, query);
|
|
2683
2753
|
if (groupBy) {
|
|
@@ -2740,7 +2810,7 @@ var vectorSearch = async ({
|
|
|
2740
2810
|
filters,
|
|
2741
2811
|
sort,
|
|
2742
2812
|
context,
|
|
2743
|
-
db:
|
|
2813
|
+
db: db3,
|
|
2744
2814
|
query,
|
|
2745
2815
|
method,
|
|
2746
2816
|
user,
|
|
@@ -2777,11 +2847,11 @@ var vectorSearch = async ({
|
|
|
2777
2847
|
}
|
|
2778
2848
|
const mainTable = getTableName(id);
|
|
2779
2849
|
const chunksTable = getChunksTableName(id);
|
|
2780
|
-
let countQuery =
|
|
2850
|
+
let countQuery = db3(mainTable);
|
|
2781
2851
|
countQuery = applyFilters(countQuery, filters);
|
|
2782
2852
|
countQuery = applyAccessControl(table, user, countQuery);
|
|
2783
|
-
const columns = await
|
|
2784
|
-
let itemsQuery =
|
|
2853
|
+
const columns = await db3(mainTable).columnInfo();
|
|
2854
|
+
let itemsQuery = db3(mainTable).select(Object.keys(columns).map((column) => mainTable + "." + column));
|
|
2785
2855
|
itemsQuery = applyFilters(itemsQuery, filters);
|
|
2786
2856
|
itemsQuery = applyAccessControl(table, user, itemsQuery);
|
|
2787
2857
|
itemsQuery = applySorting(itemsQuery, sort);
|
|
@@ -2798,7 +2868,7 @@ var vectorSearch = async ({
|
|
|
2798
2868
|
itemsQuery.select(chunksTable + ".chunk_index");
|
|
2799
2869
|
itemsQuery.select(chunksTable + ".createdAt as chunk_created_at");
|
|
2800
2870
|
itemsQuery.select(chunksTable + ".updatedAt as chunk_updated_at");
|
|
2801
|
-
itemsQuery.select(
|
|
2871
|
+
itemsQuery.select(db3.raw("vector_dims(??) as embedding_size", [`${chunksTable}.embedding`]));
|
|
2802
2872
|
const { chunks } = await embedder.generateFromQuery(query, {
|
|
2803
2873
|
label: table.name.singular,
|
|
2804
2874
|
trigger
|
|
@@ -2813,7 +2883,7 @@ var vectorSearch = async ({
|
|
|
2813
2883
|
let items = [];
|
|
2814
2884
|
switch (method) {
|
|
2815
2885
|
case "tsvector":
|
|
2816
|
-
itemsQuery.select(
|
|
2886
|
+
itemsQuery.select(db3.raw(
|
|
2817
2887
|
`ts_rank(${chunksTable}.fts, websearch_to_tsquery(?, ?)) as fts_rank`,
|
|
2818
2888
|
[language, query]
|
|
2819
2889
|
)).whereRaw(
|
|
@@ -2826,7 +2896,7 @@ var vectorSearch = async ({
|
|
|
2826
2896
|
default:
|
|
2827
2897
|
itemsQuery.whereNotNull(`${chunksTable}.embedding`);
|
|
2828
2898
|
itemsQuery.select(
|
|
2829
|
-
|
|
2899
|
+
db3.raw(`1 - (${chunksTable}.embedding <=> ${vectorExpr}) AS cosine_distance`)
|
|
2830
2900
|
);
|
|
2831
2901
|
itemsQuery.orderByRaw(
|
|
2832
2902
|
`${chunksTable}.embedding <=> ${vectorExpr} ASC NULLS LAST`
|
|
@@ -2916,7 +2986,7 @@ var vectorSearch = async ({
|
|
|
2916
2986
|
matchCount
|
|
2917
2987
|
// final limit
|
|
2918
2988
|
];
|
|
2919
|
-
items = await
|
|
2989
|
+
items = await db3.raw(hybridSQL, bindings).then((r) => r.rows ?? r);
|
|
2920
2990
|
}
|
|
2921
2991
|
const seenSources = /* @__PURE__ */ new Map();
|
|
2922
2992
|
items = items.reduce((acc, item) => {
|
|
@@ -3012,8 +3082,8 @@ var vectorSearch = async ({
|
|
|
3012
3082
|
items
|
|
3013
3083
|
};
|
|
3014
3084
|
};
|
|
3015
|
-
var RBACResolver = async (
|
|
3016
|
-
const rbacRecords = await
|
|
3085
|
+
var RBACResolver = async (db3, entityName, resourceId, rights_mode) => {
|
|
3086
|
+
const rbacRecords = await db3.from("rbac").where({
|
|
3017
3087
|
entity: entityName,
|
|
3018
3088
|
target_resource_id: resourceId
|
|
3019
3089
|
}).select("*");
|
|
@@ -3290,11 +3360,11 @@ type PageInfo {
|
|
|
3290
3360
|
resolvers[rbacResolverName] = {};
|
|
3291
3361
|
}
|
|
3292
3362
|
resolvers[rbacResolverName].RBAC = async (parent, args, context) => {
|
|
3293
|
-
const { db:
|
|
3363
|
+
const { db: db3 } = context;
|
|
3294
3364
|
const resourceId = parent.id;
|
|
3295
3365
|
const entityName = table.name.singular;
|
|
3296
3366
|
const rights_mode = parent.rights_mode;
|
|
3297
|
-
return RBACResolver(
|
|
3367
|
+
return RBACResolver(db3, entityName, resourceId, rights_mode);
|
|
3298
3368
|
};
|
|
3299
3369
|
}
|
|
3300
3370
|
}
|
|
@@ -3661,7 +3731,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3661
3731
|
app.delete("/s3/delete", async (req, res, next) => {
|
|
3662
3732
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3663
3733
|
const internalkey = req.headers["internal-key"] || null;
|
|
3664
|
-
const { db:
|
|
3734
|
+
const { db: db3 } = await postgresClient();
|
|
3665
3735
|
let authtoken = null;
|
|
3666
3736
|
if (typeof apikey !== "string" && typeof internalkey !== "string") {
|
|
3667
3737
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3670,7 +3740,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3670
3740
|
authtoken,
|
|
3671
3741
|
apikey,
|
|
3672
3742
|
internalkey,
|
|
3673
|
-
db:
|
|
3743
|
+
db: db3
|
|
3674
3744
|
});
|
|
3675
3745
|
if (!authenticationResult.user?.id) {
|
|
3676
3746
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3707,7 +3777,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3707
3777
|
app.get("/s3/download", async (req, res, next) => {
|
|
3708
3778
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3709
3779
|
const internalkey = req.headers["internal-key"] || null;
|
|
3710
|
-
const { db:
|
|
3780
|
+
const { db: db3 } = await postgresClient();
|
|
3711
3781
|
let authtoken = null;
|
|
3712
3782
|
if (typeof apikey !== "string" && typeof internalkey !== "string") {
|
|
3713
3783
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3716,7 +3786,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3716
3786
|
authtoken,
|
|
3717
3787
|
apikey,
|
|
3718
3788
|
internalkey,
|
|
3719
|
-
db:
|
|
3789
|
+
db: db3
|
|
3720
3790
|
});
|
|
3721
3791
|
if (!authenticationResult.user?.id) {
|
|
3722
3792
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3751,7 +3821,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3751
3821
|
app.post("/s3/object", async (req, res, next) => {
|
|
3752
3822
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3753
3823
|
const internalkey = req.headers["internal-key"] || null;
|
|
3754
|
-
const { db:
|
|
3824
|
+
const { db: db3 } = await postgresClient();
|
|
3755
3825
|
let authtoken = null;
|
|
3756
3826
|
if (typeof apikey !== "string" && typeof internalkey !== "string") {
|
|
3757
3827
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3760,7 +3830,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3760
3830
|
authtoken,
|
|
3761
3831
|
apikey,
|
|
3762
3832
|
internalkey,
|
|
3763
|
-
db:
|
|
3833
|
+
db: db3
|
|
3764
3834
|
});
|
|
3765
3835
|
if (!authenticationResult.user?.id) {
|
|
3766
3836
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3781,7 +3851,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3781
3851
|
app.get("/s3/list", async (req, res, next) => {
|
|
3782
3852
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3783
3853
|
const internalkey = req.headers["internal-key"] || null;
|
|
3784
|
-
const { db:
|
|
3854
|
+
const { db: db3 } = await postgresClient();
|
|
3785
3855
|
let authtoken = null;
|
|
3786
3856
|
if (typeof apikey !== "string" && typeof internalkey !== "string") {
|
|
3787
3857
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3790,7 +3860,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3790
3860
|
authtoken,
|
|
3791
3861
|
apikey,
|
|
3792
3862
|
internalkey,
|
|
3793
|
-
db:
|
|
3863
|
+
db: db3
|
|
3794
3864
|
});
|
|
3795
3865
|
if (!authenticationResult.user?.id) {
|
|
3796
3866
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3848,7 +3918,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3848
3918
|
const generateS3Key2 = (filename) => `${(0, import_node_crypto.randomUUID)()}-_EXULU_${filename}`;
|
|
3849
3919
|
const signOnServer = async (req, res, next) => {
|
|
3850
3920
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3851
|
-
const { db:
|
|
3921
|
+
const { db: db3 } = await postgresClient();
|
|
3852
3922
|
let authtoken = null;
|
|
3853
3923
|
if (typeof apikey !== "string") {
|
|
3854
3924
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3856,7 +3926,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3856
3926
|
const authenticationResult = await authentication({
|
|
3857
3927
|
authtoken,
|
|
3858
3928
|
apikey,
|
|
3859
|
-
db:
|
|
3929
|
+
db: db3
|
|
3860
3930
|
});
|
|
3861
3931
|
if (!authenticationResult.user?.id) {
|
|
3862
3932
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -3893,7 +3963,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3893
3963
|
});
|
|
3894
3964
|
app.post("/s3/multipart", async (req, res, next) => {
|
|
3895
3965
|
const apikey = req.headers["exulu-api-key"] || null;
|
|
3896
|
-
const { db:
|
|
3966
|
+
const { db: db3 } = await postgresClient();
|
|
3897
3967
|
let authtoken = null;
|
|
3898
3968
|
if (typeof apikey !== "string") {
|
|
3899
3969
|
authtoken = await getToken(req.headers.authorization ?? "");
|
|
@@ -3901,7 +3971,7 @@ var createUppyRoutes = async (app, config) => {
|
|
|
3901
3971
|
const authenticationResult = await authentication({
|
|
3902
3972
|
authtoken,
|
|
3903
3973
|
apikey,
|
|
3904
|
-
db:
|
|
3974
|
+
db: db3
|
|
3905
3975
|
});
|
|
3906
3976
|
if (!authenticationResult.user?.id) {
|
|
3907
3977
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
@@ -4181,10 +4251,10 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
|
|
|
4181
4251
|
};
|
|
4182
4252
|
};
|
|
4183
4253
|
var hydrateVariables = async (tool2) => {
|
|
4184
|
-
const { db:
|
|
4254
|
+
const { db: db3 } = await postgresClient();
|
|
4185
4255
|
const promises = tool2.config.map(async (toolConfig) => {
|
|
4186
4256
|
const variableName = toolConfig.variable;
|
|
4187
|
-
const variable = await
|
|
4257
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
4188
4258
|
if (!variable) {
|
|
4189
4259
|
console.error("[EXULU] Variable " + variableName + " not found.");
|
|
4190
4260
|
throw new Error("Variable " + variableName + " not found.");
|
|
@@ -4320,8 +4390,8 @@ var ExuluAgent2 = class {
|
|
|
4320
4390
|
if (!variableName) {
|
|
4321
4391
|
throw new Error("Provider API key variable not set for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool.");
|
|
4322
4392
|
}
|
|
4323
|
-
const { db:
|
|
4324
|
-
const variable = await
|
|
4393
|
+
const { db: db3 } = await postgresClient();
|
|
4394
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
4325
4395
|
if (!variable) {
|
|
4326
4396
|
throw new Error("Provider API key variable not found for agent: " + agentInstance.name + " (" + agentInstance.id + ") being called as a tool.");
|
|
4327
4397
|
}
|
|
@@ -4689,9 +4759,9 @@ var ExuluAgent2 = class {
|
|
|
4689
4759
|
};
|
|
4690
4760
|
};
|
|
4691
4761
|
var getAgentMessages = async ({ session, user, limit, page }) => {
|
|
4692
|
-
const { db:
|
|
4762
|
+
const { db: db3 } = await postgresClient();
|
|
4693
4763
|
console.log("[EXULU] getting agent messages for session: " + session + " and user: " + user + " and page: " + page);
|
|
4694
|
-
const query =
|
|
4764
|
+
const query = db3.from("agent_messages").where({ session, user }).limit(limit);
|
|
4695
4765
|
if (page > 0) {
|
|
4696
4766
|
query.offset((page - 1) * limit);
|
|
4697
4767
|
}
|
|
@@ -4699,9 +4769,9 @@ var getAgentMessages = async ({ session, user, limit, page }) => {
|
|
|
4699
4769
|
return messages;
|
|
4700
4770
|
};
|
|
4701
4771
|
var saveChat = async ({ session, user, messages }) => {
|
|
4702
|
-
const { db:
|
|
4772
|
+
const { db: db3 } = await postgresClient();
|
|
4703
4773
|
const promises = messages.map((message) => {
|
|
4704
|
-
return
|
|
4774
|
+
return db3.from("agent_messages").insert({
|
|
4705
4775
|
session,
|
|
4706
4776
|
user,
|
|
4707
4777
|
content: JSON.stringify(message),
|
|
@@ -4912,25 +4982,25 @@ var ExuluContext = class {
|
|
|
4912
4982
|
};
|
|
4913
4983
|
};
|
|
4914
4984
|
deleteAll = async () => {
|
|
4915
|
-
const { db:
|
|
4916
|
-
await
|
|
4917
|
-
await
|
|
4985
|
+
const { db: db3 } = await postgresClient();
|
|
4986
|
+
await db3.from(getTableName(this.id)).delete();
|
|
4987
|
+
await db3.from(getChunksTableName(this.id)).delete();
|
|
4918
4988
|
return {
|
|
4919
4989
|
count: 0,
|
|
4920
4990
|
results: []
|
|
4921
4991
|
};
|
|
4922
4992
|
};
|
|
4923
4993
|
tableExists = async () => {
|
|
4924
|
-
const { db:
|
|
4994
|
+
const { db: db3 } = await postgresClient();
|
|
4925
4995
|
const tableName = getTableName(this.id);
|
|
4926
4996
|
console.log("[EXULU] checking if table exists.", tableName);
|
|
4927
|
-
const tableExists = await
|
|
4997
|
+
const tableExists = await db3.schema.hasTable(tableName);
|
|
4928
4998
|
return tableExists;
|
|
4929
4999
|
};
|
|
4930
5000
|
chunksTableExists = async () => {
|
|
4931
|
-
const { db:
|
|
5001
|
+
const { db: db3 } = await postgresClient();
|
|
4932
5002
|
const chunksTableName = getChunksTableName(this.id);
|
|
4933
|
-
const chunksTableExists = await
|
|
5003
|
+
const chunksTableExists = await db3.schema.hasTable(chunksTableName);
|
|
4934
5004
|
return chunksTableExists;
|
|
4935
5005
|
};
|
|
4936
5006
|
createAndUpsertEmbeddings = async (item, config, user, statistics, role, job) => {
|
|
@@ -4940,7 +5010,7 @@ var ExuluContext = class {
|
|
|
4940
5010
|
if (!item.id) {
|
|
4941
5011
|
throw new Error("Item id is required for generating embeddings.");
|
|
4942
5012
|
}
|
|
4943
|
-
const { db:
|
|
5013
|
+
const { db: db3 } = await postgresClient();
|
|
4944
5014
|
const { id: source, chunks } = await this.embedder.generateFromDocument(
|
|
4945
5015
|
{
|
|
4946
5016
|
...item,
|
|
@@ -4954,14 +5024,14 @@ var ExuluContext = class {
|
|
|
4954
5024
|
user,
|
|
4955
5025
|
role
|
|
4956
5026
|
);
|
|
4957
|
-
await
|
|
4958
|
-
await
|
|
5027
|
+
await db3.from(getChunksTableName(this.id)).where({ source }).delete();
|
|
5028
|
+
await db3.from(getChunksTableName(this.id)).insert(chunks.map((chunk) => ({
|
|
4959
5029
|
source,
|
|
4960
5030
|
content: chunk.content,
|
|
4961
5031
|
chunk_index: chunk.index,
|
|
4962
5032
|
embedding: import_knex5.default.toSql(chunk.vector)
|
|
4963
5033
|
})));
|
|
4964
|
-
await
|
|
5034
|
+
await db3.from(getTableName(this.id)).where({ id: item.id }).update({
|
|
4965
5035
|
embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4966
5036
|
}).returning("id");
|
|
4967
5037
|
return {
|
|
@@ -4971,8 +5041,8 @@ var ExuluContext = class {
|
|
|
4971
5041
|
};
|
|
4972
5042
|
};
|
|
4973
5043
|
createItem = async (item, config, user, role, upsert) => {
|
|
4974
|
-
const { db:
|
|
4975
|
-
const mutation =
|
|
5044
|
+
const { db: db3 } = await postgresClient();
|
|
5045
|
+
const mutation = db3.from(getTableName(
|
|
4976
5046
|
this.id
|
|
4977
5047
|
)).insert(
|
|
4978
5048
|
{
|
|
@@ -5006,11 +5076,11 @@ var ExuluContext = class {
|
|
|
5006
5076
|
};
|
|
5007
5077
|
};
|
|
5008
5078
|
updateItem = async (item, config, user, role) => {
|
|
5009
|
-
const { db:
|
|
5079
|
+
const { db: db3 } = await postgresClient();
|
|
5010
5080
|
if (item.field) {
|
|
5011
5081
|
delete item.field;
|
|
5012
5082
|
}
|
|
5013
|
-
const record = await
|
|
5083
|
+
const record = await db3.from(
|
|
5014
5084
|
getTableName(this.id)
|
|
5015
5085
|
).where(
|
|
5016
5086
|
{ id: item.id }
|
|
@@ -5018,7 +5088,7 @@ var ExuluContext = class {
|
|
|
5018
5088
|
if (!record) {
|
|
5019
5089
|
throw new Error("Item not found.");
|
|
5020
5090
|
}
|
|
5021
|
-
const mutation =
|
|
5091
|
+
const mutation = db3.from(
|
|
5022
5092
|
getTableName(this.id)
|
|
5023
5093
|
).where(
|
|
5024
5094
|
{ id: record.id }
|
|
@@ -5052,17 +5122,17 @@ var ExuluContext = class {
|
|
|
5052
5122
|
if (!item.id) {
|
|
5053
5123
|
throw new Error("Item id is required for deleting item.");
|
|
5054
5124
|
}
|
|
5055
|
-
const { db:
|
|
5056
|
-
await
|
|
5125
|
+
const { db: db3 } = await postgresClient();
|
|
5126
|
+
await db3.from(getTableName(this.id)).where({ id: item.id }).delete();
|
|
5057
5127
|
if (!this.embedder) {
|
|
5058
5128
|
return {
|
|
5059
5129
|
id: item.id,
|
|
5060
5130
|
job: void 0
|
|
5061
5131
|
};
|
|
5062
5132
|
}
|
|
5063
|
-
const chunks = await
|
|
5133
|
+
const chunks = await db3.from(getChunksTableName(this.id)).where({ source: item.id }).select("id");
|
|
5064
5134
|
if (chunks.length > 0) {
|
|
5065
|
-
await
|
|
5135
|
+
await db3.from(getChunksTableName(this.id)).where({ source: item.id }).delete();
|
|
5066
5136
|
}
|
|
5067
5137
|
return {
|
|
5068
5138
|
id: item.id,
|
|
@@ -5111,8 +5181,8 @@ var ExuluContext = class {
|
|
|
5111
5181
|
}, role, void 0);
|
|
5112
5182
|
},
|
|
5113
5183
|
all: async (config, userId, roleId) => {
|
|
5114
|
-
const { db:
|
|
5115
|
-
const items = await
|
|
5184
|
+
const { db: db3 } = await postgresClient();
|
|
5185
|
+
const items = await db3.from(getTableName(this.id)).select("*");
|
|
5116
5186
|
const jobs = [];
|
|
5117
5187
|
const queue = await this.embedder?.queue;
|
|
5118
5188
|
if (!queue?.queue.name && items.length > 2e3) {
|
|
@@ -5141,12 +5211,12 @@ var ExuluContext = class {
|
|
|
5141
5211
|
}
|
|
5142
5212
|
};
|
|
5143
5213
|
createItemsTable = async () => {
|
|
5144
|
-
const { db:
|
|
5214
|
+
const { db: db3 } = await postgresClient();
|
|
5145
5215
|
const tableName = getTableName(this.id);
|
|
5146
5216
|
console.log("[EXULU] Creating table: " + tableName);
|
|
5147
|
-
return await
|
|
5217
|
+
return await db3.schema.createTable(tableName, (table) => {
|
|
5148
5218
|
console.log("[EXULU] Creating fields for table.", this.fields);
|
|
5149
|
-
table.uuid("id").primary().defaultTo(
|
|
5219
|
+
table.uuid("id").primary().defaultTo(db3.fn.uuid());
|
|
5150
5220
|
table.text("name");
|
|
5151
5221
|
table.text("description");
|
|
5152
5222
|
table.text("tags");
|
|
@@ -5169,19 +5239,19 @@ var ExuluContext = class {
|
|
|
5169
5239
|
}
|
|
5170
5240
|
mapType(table, type, sanitizeName(name), void 0, unique);
|
|
5171
5241
|
}
|
|
5172
|
-
table.timestamp("createdAt").defaultTo(
|
|
5173
|
-
table.timestamp("updatedAt").defaultTo(
|
|
5242
|
+
table.timestamp("createdAt").defaultTo(db3.fn.now());
|
|
5243
|
+
table.timestamp("updatedAt").defaultTo(db3.fn.now());
|
|
5174
5244
|
});
|
|
5175
5245
|
};
|
|
5176
5246
|
createChunksTable = async () => {
|
|
5177
|
-
const { db:
|
|
5247
|
+
const { db: db3 } = await refreshPostgresClient();
|
|
5178
5248
|
const tableName = getChunksTableName(this.id);
|
|
5179
5249
|
console.log("[EXULU] Creating table: " + tableName);
|
|
5180
|
-
await
|
|
5250
|
+
await db3.schema.createTable(tableName, (table) => {
|
|
5181
5251
|
if (!this.embedder) {
|
|
5182
5252
|
throw new Error("Embedder must be set for context " + this.name + " to create chunks table.");
|
|
5183
5253
|
}
|
|
5184
|
-
table.uuid("id").primary().defaultTo(
|
|
5254
|
+
table.uuid("id").primary().defaultTo(db3.fn.uuid());
|
|
5185
5255
|
table.uuid("source").references("id").inTable(getTableName(this.id));
|
|
5186
5256
|
table.text("content");
|
|
5187
5257
|
table.jsonb("metadata");
|
|
@@ -5193,10 +5263,10 @@ var ExuluContext = class {
|
|
|
5193
5263
|
);
|
|
5194
5264
|
table.index(["fts"], `${tableName}_fts_gin_idx`, "gin");
|
|
5195
5265
|
table.index(["source"], `${tableName}_source_idx`);
|
|
5196
|
-
table.timestamp("createdAt").defaultTo(
|
|
5197
|
-
table.timestamp("updatedAt").defaultTo(
|
|
5266
|
+
table.timestamp("createdAt").defaultTo(db3.fn.now());
|
|
5267
|
+
table.timestamp("updatedAt").defaultTo(db3.fn.now());
|
|
5198
5268
|
});
|
|
5199
|
-
await
|
|
5269
|
+
await db3.raw(`
|
|
5200
5270
|
CREATE INDEX IF NOT EXISTS ${tableName}_embedding_hnsw_cosine
|
|
5201
5271
|
ON ${tableName}
|
|
5202
5272
|
USING hnsw (embedding vector_cosine_ops)
|
|
@@ -5217,7 +5287,7 @@ var ExuluContext = class {
|
|
|
5217
5287
|
config: [],
|
|
5218
5288
|
description: `Gets information from the context called: ${this.name}. The context description is: ${this.description}.`,
|
|
5219
5289
|
execute: async ({ query, user, role }) => {
|
|
5220
|
-
const { db:
|
|
5290
|
+
const { db: db3 } = await postgresClient();
|
|
5221
5291
|
const result = await vectorSearch({
|
|
5222
5292
|
page: 1,
|
|
5223
5293
|
limit: 10,
|
|
@@ -5227,7 +5297,7 @@ var ExuluContext = class {
|
|
|
5227
5297
|
role,
|
|
5228
5298
|
method: "hybridSearch",
|
|
5229
5299
|
context: this,
|
|
5230
|
-
db:
|
|
5300
|
+
db: db3,
|
|
5231
5301
|
sort: void 0,
|
|
5232
5302
|
trigger: "agent"
|
|
5233
5303
|
});
|
|
@@ -5250,8 +5320,8 @@ var ExuluContext = class {
|
|
|
5250
5320
|
var updateStatistic = async (statistic) => {
|
|
5251
5321
|
console.log("[EXULU] Updating statistic", statistic);
|
|
5252
5322
|
const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
5253
|
-
const { db:
|
|
5254
|
-
const existing = await
|
|
5323
|
+
const { db: db3 } = await postgresClient();
|
|
5324
|
+
const existing = await db3.from("tracking").where({
|
|
5255
5325
|
...statistic.user ? { user: statistic.user } : {},
|
|
5256
5326
|
...statistic.role ? { role: statistic.role } : {},
|
|
5257
5327
|
name: statistic.name,
|
|
@@ -5261,7 +5331,7 @@ var updateStatistic = async (statistic) => {
|
|
|
5261
5331
|
}).first();
|
|
5262
5332
|
console.log("[EXULU] Existing", existing);
|
|
5263
5333
|
if (!existing) {
|
|
5264
|
-
await
|
|
5334
|
+
await db3.from("tracking").insert({
|
|
5265
5335
|
name: statistic.name,
|
|
5266
5336
|
label: statistic.label,
|
|
5267
5337
|
type: statistic.type,
|
|
@@ -5271,8 +5341,8 @@ var updateStatistic = async (statistic) => {
|
|
|
5271
5341
|
...statistic.role ? { role: statistic.role } : {}
|
|
5272
5342
|
});
|
|
5273
5343
|
} else {
|
|
5274
|
-
await
|
|
5275
|
-
total:
|
|
5344
|
+
await db3.from("tracking").update({
|
|
5345
|
+
total: db3.raw("total + ?", [statistic.count ?? 1])
|
|
5276
5346
|
}).where({
|
|
5277
5347
|
name: statistic.name,
|
|
5278
5348
|
label: statistic.label,
|
|
@@ -5557,10 +5627,10 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, tracer) =
|
|
|
5557
5627
|
if (!authenticationResult.user?.id) {
|
|
5558
5628
|
throw new Error(authenticationResult.message);
|
|
5559
5629
|
}
|
|
5560
|
-
const { db:
|
|
5630
|
+
const { db: db3 } = await postgresClient();
|
|
5561
5631
|
return {
|
|
5562
5632
|
req,
|
|
5563
|
-
db:
|
|
5633
|
+
db: db3,
|
|
5564
5634
|
user: authenticationResult.user
|
|
5565
5635
|
};
|
|
5566
5636
|
}
|
|
@@ -5580,8 +5650,8 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, tracer) =
|
|
|
5580
5650
|
});
|
|
5581
5651
|
return;
|
|
5582
5652
|
}
|
|
5583
|
-
const { db:
|
|
5584
|
-
const variable = await
|
|
5653
|
+
const { db: db3 } = await postgresClient();
|
|
5654
|
+
const variable = await db3.from("variables").where({ name: "OPENAI_IMAGE_GENERATION_API_KEY" }).first();
|
|
5585
5655
|
if (!variable) {
|
|
5586
5656
|
res.status(400).json({
|
|
5587
5657
|
message: "Provider API key variable not found."
|
|
@@ -5672,8 +5742,8 @@ Mood: friendly and intelligent.
|
|
|
5672
5742
|
});
|
|
5673
5743
|
return;
|
|
5674
5744
|
}
|
|
5675
|
-
const { db:
|
|
5676
|
-
const evalRun = await
|
|
5745
|
+
const { db: db3 } = await postgresClient();
|
|
5746
|
+
const evalRun = await db3.from("eval_runs").where({ id: evalRunId }).first();
|
|
5677
5747
|
if (!evalRun) {
|
|
5678
5748
|
res.status(404).json({
|
|
5679
5749
|
message: "Eval run not found."
|
|
@@ -5701,7 +5771,7 @@ Mood: friendly and intelligent.
|
|
|
5701
5771
|
});
|
|
5702
5772
|
return;
|
|
5703
5773
|
}
|
|
5704
|
-
const testCases = await
|
|
5774
|
+
const testCases = await db3.from("test_cases").whereIn("id", testCaseIds);
|
|
5705
5775
|
if (testCases.length === 0) {
|
|
5706
5776
|
res.status(404).json({
|
|
5707
5777
|
message: "No test cases found."
|
|
@@ -5767,8 +5837,8 @@ Mood: friendly and intelligent.
|
|
|
5767
5837
|
});
|
|
5768
5838
|
});
|
|
5769
5839
|
app.get("/theme", async (req, res) => {
|
|
5770
|
-
const { db:
|
|
5771
|
-
const themeConfig = await
|
|
5840
|
+
const { db: db3 } = await postgresClient();
|
|
5841
|
+
const themeConfig = await db3.from("platform_configurations").where({ config_key: "theme_config" }).first();
|
|
5772
5842
|
if (!themeConfig) {
|
|
5773
5843
|
res.status(200).json({
|
|
5774
5844
|
theme: {
|
|
@@ -5784,6 +5854,7 @@ Mood: friendly and intelligent.
|
|
|
5784
5854
|
});
|
|
5785
5855
|
app.get("/config", async (req, res) => {
|
|
5786
5856
|
res.status(200).json({
|
|
5857
|
+
authMode: process.env.AUTH_MODE,
|
|
5787
5858
|
MCP: {
|
|
5788
5859
|
enabled: config?.MCP.enabled
|
|
5789
5860
|
},
|
|
@@ -5819,7 +5890,7 @@ Mood: friendly and intelligent.
|
|
|
5819
5890
|
});
|
|
5820
5891
|
return;
|
|
5821
5892
|
}
|
|
5822
|
-
const { db:
|
|
5893
|
+
const { db: db3 } = await postgresClient();
|
|
5823
5894
|
const agentInstance = await loadAgent(instance);
|
|
5824
5895
|
const requestValidationResult = requestValidators.agents(req);
|
|
5825
5896
|
if (requestValidationResult.error) {
|
|
@@ -5840,7 +5911,7 @@ Mood: friendly and intelligent.
|
|
|
5840
5911
|
return;
|
|
5841
5912
|
}
|
|
5842
5913
|
if (headers.session) {
|
|
5843
|
-
const session = await
|
|
5914
|
+
const session = await db3.from("agent_sessions").where({
|
|
5844
5915
|
id: headers.session
|
|
5845
5916
|
}).first();
|
|
5846
5917
|
let hasAccessToSession = await checkRecordAccess(session, "write", user);
|
|
@@ -5862,7 +5933,7 @@ Mood: friendly and intelligent.
|
|
|
5862
5933
|
let enabledTools = await getEnabledTools(agentInstance, tools, disabledTools, agents, user);
|
|
5863
5934
|
console.log("[EXULU] enabled tools", enabledTools?.map((x) => x.name + " (" + x.id + ")"));
|
|
5864
5935
|
const variableName = agentInstance.providerapikey;
|
|
5865
|
-
const variable = await
|
|
5936
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
5866
5937
|
if (!variable) {
|
|
5867
5938
|
res.status(400).json({
|
|
5868
5939
|
message: "Provider API key variable not found."
|
|
@@ -5965,8 +6036,8 @@ Mood: friendly and intelligent.
|
|
|
5965
6036
|
return;
|
|
5966
6037
|
}
|
|
5967
6038
|
console.log("[EXULU] Authenticated call", authenticationResult.user?.email);
|
|
5968
|
-
const { db:
|
|
5969
|
-
let query =
|
|
6039
|
+
const { db: db3 } = await postgresClient();
|
|
6040
|
+
let query = db3("agents");
|
|
5970
6041
|
query.select("*");
|
|
5971
6042
|
query = applyAccessControl(agentsSchema2(), authenticationResult.user, query);
|
|
5972
6043
|
query.where({ id: srcReq.params.id });
|
|
@@ -5986,7 +6057,7 @@ Mood: friendly and intelligent.
|
|
|
5986
6057
|
return;
|
|
5987
6058
|
}
|
|
5988
6059
|
const variableName = agent.providerapikey;
|
|
5989
|
-
const variable = await
|
|
6060
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
5990
6061
|
console.log("[EXULU] Variable loaded", variable);
|
|
5991
6062
|
let providerapikey = variable.value;
|
|
5992
6063
|
if (!variable.encrypted) {
|
|
@@ -6036,8 +6107,8 @@ Mood: friendly and intelligent.
|
|
|
6036
6107
|
return;
|
|
6037
6108
|
}
|
|
6038
6109
|
const user = authenticationResult.user;
|
|
6039
|
-
const { db:
|
|
6040
|
-
let query =
|
|
6110
|
+
const { db: db3 } = await postgresClient();
|
|
6111
|
+
let query = db3("agents");
|
|
6041
6112
|
query.select("*");
|
|
6042
6113
|
query = applyAccessControl(agentsSchema2(), authenticationResult.user, query);
|
|
6043
6114
|
query.where({ id: req.params.id });
|
|
@@ -6064,7 +6135,7 @@ Mood: friendly and intelligent.
|
|
|
6064
6135
|
return;
|
|
6065
6136
|
}
|
|
6066
6137
|
const variableName = agent.providerapikey;
|
|
6067
|
-
const variable = await
|
|
6138
|
+
const variable = await db3.from("variables").where({ name: variableName }).first();
|
|
6068
6139
|
if (!variable) {
|
|
6069
6140
|
const arrayBuffer = createCustomAnthropicStreamingMessage(CLAUDE_MESSAGES.anthropic_token_variable_not_found);
|
|
6070
6141
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -6204,7 +6275,7 @@ var createWorkers = async (queues2, config, contexts, tracer) => {
|
|
|
6204
6275
|
const worker = new import_bullmq5.Worker(
|
|
6205
6276
|
`${queue}`,
|
|
6206
6277
|
async (bullmqJob) => {
|
|
6207
|
-
const { db:
|
|
6278
|
+
const { db: db3 } = await postgresClient();
|
|
6208
6279
|
try {
|
|
6209
6280
|
const data = bullmqJob.data;
|
|
6210
6281
|
bullmq.validate(bullmqJob.id, data);
|
|
@@ -6260,7 +6331,7 @@ var createWorkers = async (queues2, config, contexts, tracer) => {
|
|
|
6260
6331
|
return result;
|
|
6261
6332
|
}
|
|
6262
6333
|
} catch (error) {
|
|
6263
|
-
await
|
|
6334
|
+
await db3.from("jobs").where({ redis: bullmqJob.id }).update({
|
|
6264
6335
|
status: "failed",
|
|
6265
6336
|
finishedAt: /* @__PURE__ */ new Date(),
|
|
6266
6337
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -6999,8 +7070,8 @@ var ExuluApp = class {
|
|
|
6999
7070
|
context: contextId,
|
|
7000
7071
|
item: itemId
|
|
7001
7072
|
}) => {
|
|
7002
|
-
const { db:
|
|
7003
|
-
const item = await
|
|
7073
|
+
const { db: db3 } = await postgresClient();
|
|
7074
|
+
const item = await db3.from(getTableName(contextId)).where({ id: itemId }).select("*").first();
|
|
7004
7075
|
const context = this.contexts.find((x) => contextId === x.id);
|
|
7005
7076
|
if (!context) {
|
|
7006
7077
|
throw new Error(`Context ${contextId} not found in registry.`);
|
|
@@ -8300,59 +8371,6 @@ var SentenceChunker = class _SentenceChunker extends BaseChunker {
|
|
|
8300
8371
|
}
|
|
8301
8372
|
};
|
|
8302
8373
|
|
|
8303
|
-
// src/auth/generate-key.ts
|
|
8304
|
-
var import_bcryptjs3 = __toESM(require("bcryptjs"), 1);
|
|
8305
|
-
var SALT_ROUNDS = 12;
|
|
8306
|
-
async function encryptString(string) {
|
|
8307
|
-
const hash = await import_bcryptjs3.default.hash(string, SALT_ROUNDS);
|
|
8308
|
-
return hash;
|
|
8309
|
-
}
|
|
8310
|
-
var generateApiKey = async (name, email) => {
|
|
8311
|
-
const { db: db4 } = await postgresClient();
|
|
8312
|
-
console.log("[EXULU] Inserting default user and admin role.");
|
|
8313
|
-
const existingRole = await db4.from("roles").where({ name: "admin" }).first();
|
|
8314
|
-
let roleId;
|
|
8315
|
-
if (!existingRole) {
|
|
8316
|
-
console.log("[EXULU] Creating default admin role.");
|
|
8317
|
-
const role = await db4.from("roles").insert({
|
|
8318
|
-
name: "admin",
|
|
8319
|
-
agents: "write",
|
|
8320
|
-
workflows: "write",
|
|
8321
|
-
variables: "write",
|
|
8322
|
-
users: "write"
|
|
8323
|
-
}).returning("id");
|
|
8324
|
-
roleId = role[0].id;
|
|
8325
|
-
} else {
|
|
8326
|
-
roleId = existingRole.id;
|
|
8327
|
-
}
|
|
8328
|
-
const newKeyName = name;
|
|
8329
|
-
const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
|
|
8330
|
-
const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
|
|
8331
|
-
const encryptedKey = await encryptString(plainKey);
|
|
8332
|
-
const existingApiUser = await db4.from("users").where({ email }).first();
|
|
8333
|
-
if (!existingApiUser) {
|
|
8334
|
-
console.log("[EXULU] Creating default api user.");
|
|
8335
|
-
await db4.from("users").insert({
|
|
8336
|
-
name,
|
|
8337
|
-
email,
|
|
8338
|
-
super_admin: true,
|
|
8339
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
8340
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
8341
|
-
type: "api",
|
|
8342
|
-
emailVerified: /* @__PURE__ */ new Date(),
|
|
8343
|
-
apikey: `${encryptedKey}${postFix}`,
|
|
8344
|
-
// password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
|
|
8345
|
-
role: roleId
|
|
8346
|
-
});
|
|
8347
|
-
console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
|
|
8348
|
-
} else {
|
|
8349
|
-
console.log("[EXULU] API user with that name already exists.");
|
|
8350
|
-
}
|
|
8351
|
-
return {
|
|
8352
|
-
key: `${plainKey}${postFix}`
|
|
8353
|
-
};
|
|
8354
|
-
};
|
|
8355
|
-
|
|
8356
8374
|
// src/postgres/init-db.ts
|
|
8357
8375
|
var {
|
|
8358
8376
|
agentsSchema: agentsSchema3,
|
|
@@ -8499,16 +8517,16 @@ var contextDatabases = async (contexts) => {
|
|
|
8499
8517
|
}
|
|
8500
8518
|
};
|
|
8501
8519
|
var execute = async ({ contexts }) => {
|
|
8502
|
-
const { db:
|
|
8520
|
+
const { db: db3 } = await postgresClient();
|
|
8503
8521
|
console.log("[EXULU] Checking Exulu IMP database status.");
|
|
8504
|
-
await up(
|
|
8522
|
+
await up(db3);
|
|
8505
8523
|
await contextDatabases(contexts);
|
|
8506
8524
|
console.log("[EXULU] Inserting default user and admin role.");
|
|
8507
|
-
const existingRole = await
|
|
8525
|
+
const existingRole = await db3.from("roles").where({ name: "admin" }).first();
|
|
8508
8526
|
let roleId;
|
|
8509
8527
|
if (!existingRole) {
|
|
8510
8528
|
console.log("[EXULU] Creating default admin role.");
|
|
8511
|
-
const role = await
|
|
8529
|
+
const role = await db3.from("roles").insert({
|
|
8512
8530
|
name: "admin",
|
|
8513
8531
|
agents: "write",
|
|
8514
8532
|
workflows: "write",
|
|
@@ -8519,11 +8537,11 @@ var execute = async ({ contexts }) => {
|
|
|
8519
8537
|
} else {
|
|
8520
8538
|
roleId = existingRole.id;
|
|
8521
8539
|
}
|
|
8522
|
-
const existingUser = await
|
|
8540
|
+
const existingUser = await db3.from("users").where({ email: "admin@exulu.com" }).first();
|
|
8523
8541
|
if (!existingUser) {
|
|
8524
8542
|
const password = await encryptString("admin");
|
|
8525
8543
|
console.log("[EXULU] Creating default admin user.");
|
|
8526
|
-
await
|
|
8544
|
+
await db3.from("users").insert({
|
|
8527
8545
|
name: "exulu",
|
|
8528
8546
|
email: "admin@exulu.com",
|
|
8529
8547
|
super_admin: true,
|
|
@@ -8630,8 +8648,8 @@ var ExuluDefaultAgents = {
|
|
|
8630
8648
|
};
|
|
8631
8649
|
var ExuluVariables = {
|
|
8632
8650
|
get: async (name) => {
|
|
8633
|
-
const { db:
|
|
8634
|
-
let variable = await
|
|
8651
|
+
const { db: db3 } = await postgresClient();
|
|
8652
|
+
let variable = await db3.from("variables").where({ name }).first();
|
|
8635
8653
|
if (!variable) {
|
|
8636
8654
|
throw new Error(`Variable ${name} not found.`);
|
|
8637
8655
|
}
|
|
@@ -8733,7 +8751,7 @@ var ExuluOtel = {
|
|
|
8733
8751
|
});
|
|
8734
8752
|
}
|
|
8735
8753
|
};
|
|
8736
|
-
var
|
|
8754
|
+
var db2 = {
|
|
8737
8755
|
init: async ({
|
|
8738
8756
|
contexts
|
|
8739
8757
|
}) => {
|