@exulu/backend 1.58.0 → 1.59.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/dist/catalog-EOKGOHTY.js +10 -0
- package/dist/{chunk-RVLZ5EL3.js → chunk-U36VJDZ7.js} +644 -66
- package/dist/chunk-YS27XOXI.js +62 -0
- package/dist/{convert-exulu-tools-to-ai-sdk-tools-K4W6OJ3G.js → convert-exulu-tools-to-ai-sdk-tools-ZEECMX43.js} +1 -1
- package/dist/index.cjs +2606 -1236
- package/dist/index.d.cts +13 -14
- package/dist/index.d.ts +13 -14
- package/dist/index.js +1812 -1134
- package/ee/python/.litellm/config.yaml.example +64 -0
- package/ee/python/requirements.txt +15 -0
- package/ee/python/setup.sh +13 -0
- package/ee/workers.ts +15 -29
- package/package.json +3 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# LiteLLM Proxy configuration for Exulu.
|
|
2
|
+
#
|
|
3
|
+
# This file is read by the LiteLLM process Exulu spawns when EXULU_USE_LITELLM=true.
|
|
4
|
+
# Documentation: https://docs.litellm.ai/docs/proxy/configs
|
|
5
|
+
#
|
|
6
|
+
# To use:
|
|
7
|
+
# 1. Copy this file to config.yaml in the same directory.
|
|
8
|
+
# 2. Edit model_list to add the providers you want to expose.
|
|
9
|
+
# 3. Set the referenced env vars (LITELLM_MASTER_KEY, GOOGLE_VERTEX_PROJECT, etc.).
|
|
10
|
+
# 4. Set EXULU_USE_LITELLM=true and (re)start Exulu.
|
|
11
|
+
|
|
12
|
+
general_settings:
|
|
13
|
+
master_key: os.environ/LITELLM_MASTER_KEY
|
|
14
|
+
|
|
15
|
+
# Database mode (optional). Set `database_url` only if you want LiteLLM's
|
|
16
|
+
# user/key/budget/spend tracking tables. When set, LiteLLM creates ~60
|
|
17
|
+
# tables in the target database (all prefixed `LiteLLM_`).
|
|
18
|
+
#
|
|
19
|
+
# ⚠ ALWAYS use a DEDICATED Postgres database for LiteLLM — never share it
|
|
20
|
+
# with Exulu's main database. LiteLLM's schema sync drops any tables in
|
|
21
|
+
# the public schema that aren't part of its schema; sharing a database
|
|
22
|
+
# with Exulu has destroyed application data in the past.
|
|
23
|
+
#
|
|
24
|
+
# Exulu's ExuluDatabase.init runs `prisma db push` against this URL
|
|
25
|
+
# automatically at boot, but only after verifying:
|
|
26
|
+
# 1. database_url is NOT the same as Exulu's own Postgres (warns + skips)
|
|
27
|
+
# 2. the target database contains no non-LiteLLM_* tables (warns + skips)
|
|
28
|
+
# 3. the push itself runs without --accept-data-loss (Prisma refuses any
|
|
29
|
+
# schema change that would drop data)
|
|
30
|
+
# Re-running on an already-set-up database is a no-op.
|
|
31
|
+
#
|
|
32
|
+
# database_url: "postgresql://user:pass@host:5432/litellm_dedicated"
|
|
33
|
+
|
|
34
|
+
model_list:
|
|
35
|
+
# Each entry's `model_name` is what Exulu agents will reference in their
|
|
36
|
+
# `model` field after toggling LiteLLM on. Pick stable, human-friendly names.
|
|
37
|
+
|
|
38
|
+
- model_name: vertex-flash
|
|
39
|
+
litellm_params:
|
|
40
|
+
model: vertex_ai/gemini-2.5-flash
|
|
41
|
+
vertex_project: os.environ/GOOGLE_VERTEX_PROJECT
|
|
42
|
+
vertex_location: europe-west1
|
|
43
|
+
vertex_credentials: os.environ/GOOGLE_VERTEX_CREDENTIALS_JSON
|
|
44
|
+
|
|
45
|
+
- model_name: vertex-pro
|
|
46
|
+
litellm_params:
|
|
47
|
+
model: vertex_ai/gemini-2.5-pro
|
|
48
|
+
vertex_project: os.environ/GOOGLE_VERTEX_PROJECT
|
|
49
|
+
vertex_location: europe-west1
|
|
50
|
+
vertex_credentials: os.environ/GOOGLE_VERTEX_CREDENTIALS_JSON
|
|
51
|
+
|
|
52
|
+
- model_name: claude-haiku
|
|
53
|
+
litellm_params:
|
|
54
|
+
model: anthropic/claude-haiku-4-5
|
|
55
|
+
api_key: os.environ/ANTHROPIC_API_KEY
|
|
56
|
+
|
|
57
|
+
- model_name: gpt-5
|
|
58
|
+
litellm_params:
|
|
59
|
+
model: openai/gpt-5
|
|
60
|
+
api_key: os.environ/OPENAI_API_KEY
|
|
61
|
+
|
|
62
|
+
# Per-model rate limits and budgets are configured here in LiteLLM-native form.
|
|
63
|
+
# See https://docs.litellm.ai/docs/proxy/users for budget configuration and
|
|
64
|
+
# https://docs.litellm.ai/docs/proxy/rate_limit_tiers for rate limiting.
|
|
@@ -3,3 +3,18 @@ transformers
|
|
|
3
3
|
pyinstaller
|
|
4
4
|
docling-hierarchical-pdf
|
|
5
5
|
defusedxml
|
|
6
|
+
# LiteLLM proxy — only used when EXULU_USE_LITELLM=true. Always installed so
|
|
7
|
+
# the dep is ready when the env var is flipped. Pinned to a tested version;
|
|
8
|
+
# upgrade deliberately.
|
|
9
|
+
litellm[proxy]==1.85.1
|
|
10
|
+
# Prisma Python client — required by LiteLLM proxy whenever a `database_url`
|
|
11
|
+
# is set in config.litellm.yaml (used for user/budget tracking, key
|
|
12
|
+
# management, etc.). NOT included in litellm[proxy] in 1.85.1, hence the
|
|
13
|
+
# separate pin. setup.sh runs `prisma generate` against LiteLLM's bundled
|
|
14
|
+
# schema after pip install so the Python client module is materialized.
|
|
15
|
+
prisma==0.15.0
|
|
16
|
+
# Vertex AI SDK — required by LiteLLM when routing to `vertex_ai/*` models
|
|
17
|
+
# (the `vertexai` Python module lives inside google-cloud-aiplatform).
|
|
18
|
+
# NOT included in litellm[proxy]; without it, requests to Vertex models
|
|
19
|
+
# fail with "No module named 'vertexai'".
|
|
20
|
+
google-cloud-aiplatform>=1.38
|
package/ee/python/setup.sh
CHANGED
|
@@ -203,6 +203,19 @@ pip install -r "$REQUIREMENTS_FILE"
|
|
|
203
203
|
|
|
204
204
|
print_success "All dependencies installed successfully"
|
|
205
205
|
|
|
206
|
+
# Step 6.5: Generate Prisma client for LiteLLM database mode.
|
|
207
|
+
# LiteLLM's PrismaClient does `from prisma import Prisma`, which only works
|
|
208
|
+
# after `prisma generate` has materialized the Python client against
|
|
209
|
+
# LiteLLM's bundled schema. Skip silently if LiteLLM isn't installed or its
|
|
210
|
+
# schema isn't where we expect — database mode is opt-in via config.litellm.yaml.
|
|
211
|
+
LITELLM_PROXY_DIR=$(find "$VENV_DIR/lib" -path "*/litellm/proxy" -type d 2>/dev/null | head -1)
|
|
212
|
+
if [ -n "$LITELLM_PROXY_DIR" ] && [ -f "$LITELLM_PROXY_DIR/schema.prisma" ]; then
|
|
213
|
+
print_info "Generating Prisma client for LiteLLM..."
|
|
214
|
+
(cd "$LITELLM_PROXY_DIR" && PATH="$VENV_DIR/bin:$PATH" "$VENV_DIR/bin/prisma" generate > /dev/null 2>&1) \
|
|
215
|
+
&& print_success "Prisma client generated for LiteLLM" \
|
|
216
|
+
|| print_warning "Prisma generate failed; LiteLLM database mode (database_url in config.litellm.yaml) may not work until you run 'cd $LITELLM_PROXY_DIR && PATH=$VENV_DIR/bin:\$PATH $VENV_DIR/bin/prisma generate'"
|
|
217
|
+
fi
|
|
218
|
+
|
|
206
219
|
# Step 7: Validate installation
|
|
207
220
|
echo ""
|
|
208
221
|
echo "Step 7: Validating installation..."
|
package/ee/workers.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { getTableName, type ExuluContext } from "@SRC/exulu/context.ts";
|
|
|
10
10
|
import type { ExuluReranker } from "@SRC/exulu/reranker.ts";
|
|
11
11
|
import type { ExuluEval } from "@SRC/exulu/evals.ts";
|
|
12
12
|
import type { ExuluTool } from "@SRC/exulu/tool.ts";
|
|
13
|
+
import { resolveModel } from "@SRC/exulu/resolve-model.ts";
|
|
13
14
|
import { postgresClient } from "@SRC/postgres/client";
|
|
14
15
|
import type { BullMqJobData } from "@EE/queues/decorator.ts";
|
|
15
16
|
import { type Tracer } from "@opentelemetry/api";
|
|
@@ -1379,37 +1380,21 @@ export const processUiMessagesFlow = async ({
|
|
|
1379
1380
|
enabledTools?.map((x) => x.name + " (" + x.id + ")"),
|
|
1380
1381
|
);
|
|
1381
1382
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
const { db } = await postgresClient();
|
|
1387
|
-
|
|
1388
|
-
let providerapikey: string | undefined;
|
|
1389
|
-
|
|
1390
|
-
if (variableName) {
|
|
1391
|
-
const variable = await db.from("variables").where({ name: variableName }).first();
|
|
1392
|
-
if (!variable) {
|
|
1393
|
-
throw new Error(
|
|
1394
|
-
`Provider API key variable not found for agent ${agent.name} (${agent.id}).`,
|
|
1395
|
-
);
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
// Get the API key from the variable (decrypt if encrypted)
|
|
1399
|
-
providerapikey = variable.value;
|
|
1400
|
-
|
|
1401
|
-
if (!variable.encrypted) {
|
|
1402
|
-
throw new Error(
|
|
1403
|
-
`Provider API key variable not encrypted for agent ${agent.name} (${agent.id}), for security reasons you are only allowed to use encrypted variables for provider API keys.`,
|
|
1404
|
-
);
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
if (variable.encrypted) {
|
|
1408
|
-
const bytes = CryptoJS.AES.decrypt(variable.value, process.env.NEXTAUTH_SECRET);
|
|
1409
|
-
providerapikey = bytes.toString(CryptoJS.enc.Utf8);
|
|
1410
|
-
}
|
|
1383
|
+
if (!agent.model) {
|
|
1384
|
+
throw new Error(
|
|
1385
|
+
`Agent ${agent.name} (${agent.id}) has no model configured.`,
|
|
1386
|
+
);
|
|
1411
1387
|
}
|
|
1412
1388
|
|
|
1389
|
+
const resolved = await resolveModel({
|
|
1390
|
+
modelId: agent.model,
|
|
1391
|
+
user,
|
|
1392
|
+
providers,
|
|
1393
|
+
agent: { id: agent.id },
|
|
1394
|
+
});
|
|
1395
|
+
const providerapikey = resolved.apiKey;
|
|
1396
|
+
const resolvedLanguageModel = resolved.languageModel;
|
|
1397
|
+
|
|
1413
1398
|
// Remove placeholder agent response before sending
|
|
1414
1399
|
const messagesWithoutPlaceholder = inputMessages.filter(
|
|
1415
1400
|
(message) => (message.metadata as any)?.type !== "placeholder",
|
|
@@ -1512,6 +1497,7 @@ export const processUiMessagesFlow = async ({
|
|
|
1512
1497
|
message: currentMessage,
|
|
1513
1498
|
currentTools: enabledTools,
|
|
1514
1499
|
allExuluTools: tools,
|
|
1500
|
+
languageModel: resolvedLanguageModel,
|
|
1515
1501
|
providerapikey,
|
|
1516
1502
|
toolConfigs: agent.tools,
|
|
1517
1503
|
exuluConfig: config,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exulu/backend",
|
|
3
3
|
"author": "Qventu Bv.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.59.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
7
7
|
"publishConfig": {
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"@types/express": "^5.0.1",
|
|
64
64
|
"@types/graphql-type-json": "^0.3.5",
|
|
65
65
|
"@types/jest": "^29.5.14",
|
|
66
|
+
"@types/multer": "^2.1.0",
|
|
66
67
|
"@types/node": "^22.14.0",
|
|
67
68
|
"@types/pg": "^8.15.1",
|
|
68
69
|
"@types/supertest": "^6.0.2",
|
|
@@ -139,6 +140,7 @@
|
|
|
139
140
|
"knex": "^3.1.0",
|
|
140
141
|
"link": "^2.1.1",
|
|
141
142
|
"mammoth": "^1.11.0",
|
|
143
|
+
"multer": "^2.1.1",
|
|
142
144
|
"natural": "^8.1.0",
|
|
143
145
|
"nodemailer": "^8.0.7",
|
|
144
146
|
"officeparser": "^5.2.2",
|