@exulu/backend 1.48.2 → 1.49.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/index.cjs +351 -42
- package/dist/index.d.cts +96 -1
- package/dist/index.d.ts +96 -1
- package/dist/index.js +340 -38
- package/ee/{markdown.ts → chunking/markdown.ts} +2 -2
- package/ee/python/README.md +295 -0
- package/ee/python/documents/processing/README.md +155 -0
- package/ee/{documents → python/documents}/processing/doc_processor.ts +25 -17
- package/ee/{documents/processing/pdf_to_markdown.py → python/documents/processing/document_to_markdown.py} +3 -10
- package/ee/python/setup.sh +180 -0
- package/package.json +14 -3
- package/scripts/postinstall.cjs +149 -0
- package/.agents/skills/mintlify/SKILL.md +0 -347
- package/.editorconfig +0 -15
- package/.eslintrc.json +0 -52
- package/.github/workflows/release-backend.yml +0 -38
- package/.husky/commit-msg +0 -1
- package/.jscpd.json +0 -18
- package/.mcp.json +0 -25
- package/.nvmrc +0 -1
- package/.prettierignore +0 -5
- package/.prettierrc.json +0 -12
- package/CHANGELOG.md +0 -8
- package/SECURITY.md +0 -5
- package/commitlint.config.js +0 -4
- package/devops/documentation/patch-older-releases.md +0 -42
- package/ee/documents/processing/build_pdf_processor.sh +0 -35
- package/ee/documents/processing/chunk_markdown.py +0 -263
- package/ee/documents/processing/pdf_processor.spec +0 -115
- package/eslint.config.js +0 -88
- package/jest.config.ts +0 -25
- package/mintlify-docs/.mintignore +0 -7
- package/mintlify-docs/AGENTS.md +0 -33
- package/mintlify-docs/CLAUDE.MD +0 -50
- package/mintlify-docs/CONTRIBUTING.md +0 -32
- package/mintlify-docs/LICENSE +0 -21
- package/mintlify-docs/README.md +0 -55
- package/mintlify-docs/ai-tools/claude-code.mdx +0 -43
- package/mintlify-docs/ai-tools/cursor.mdx +0 -39
- package/mintlify-docs/ai-tools/windsurf.mdx +0 -39
- package/mintlify-docs/api-reference/core-types/agent-types.mdx +0 -110
- package/mintlify-docs/api-reference/core-types/analytics-types.mdx +0 -95
- package/mintlify-docs/api-reference/core-types/configuration-types.mdx +0 -83
- package/mintlify-docs/api-reference/core-types/evaluation-types.mdx +0 -106
- package/mintlify-docs/api-reference/core-types/job-types.mdx +0 -135
- package/mintlify-docs/api-reference/core-types/overview.mdx +0 -73
- package/mintlify-docs/api-reference/core-types/prompt-types.mdx +0 -102
- package/mintlify-docs/api-reference/core-types/rbac-types.mdx +0 -163
- package/mintlify-docs/api-reference/core-types/session-types.mdx +0 -77
- package/mintlify-docs/api-reference/core-types/user-management.mdx +0 -112
- package/mintlify-docs/api-reference/core-types/workflow-types.mdx +0 -88
- package/mintlify-docs/api-reference/core-types.mdx +0 -585
- package/mintlify-docs/api-reference/dynamic-types.mdx +0 -851
- package/mintlify-docs/api-reference/endpoint/create.mdx +0 -4
- package/mintlify-docs/api-reference/endpoint/delete.mdx +0 -4
- package/mintlify-docs/api-reference/endpoint/get.mdx +0 -4
- package/mintlify-docs/api-reference/endpoint/webhook.mdx +0 -4
- package/mintlify-docs/api-reference/introduction.mdx +0 -661
- package/mintlify-docs/api-reference/mutations.mdx +0 -1012
- package/mintlify-docs/api-reference/openapi.json +0 -217
- package/mintlify-docs/api-reference/queries.mdx +0 -1154
- package/mintlify-docs/backend/introduction.mdx +0 -218
- package/mintlify-docs/changelog.mdx +0 -387
- package/mintlify-docs/community-edition.mdx +0 -304
- package/mintlify-docs/core/exulu-agent/api-reference.mdx +0 -894
- package/mintlify-docs/core/exulu-agent/configuration.mdx +0 -690
- package/mintlify-docs/core/exulu-agent/introduction.mdx +0 -552
- package/mintlify-docs/core/exulu-app/api-reference.mdx +0 -481
- package/mintlify-docs/core/exulu-app/configuration.mdx +0 -319
- package/mintlify-docs/core/exulu-app/introduction.mdx +0 -117
- package/mintlify-docs/core/exulu-authentication.mdx +0 -810
- package/mintlify-docs/core/exulu-chunkers/api-reference.mdx +0 -1011
- package/mintlify-docs/core/exulu-chunkers/configuration.mdx +0 -596
- package/mintlify-docs/core/exulu-chunkers/introduction.mdx +0 -403
- package/mintlify-docs/core/exulu-context/api-reference.mdx +0 -911
- package/mintlify-docs/core/exulu-context/configuration.mdx +0 -648
- package/mintlify-docs/core/exulu-context/introduction.mdx +0 -394
- package/mintlify-docs/core/exulu-database.mdx +0 -811
- package/mintlify-docs/core/exulu-default-agents.mdx +0 -545
- package/mintlify-docs/core/exulu-eval/api-reference.mdx +0 -772
- package/mintlify-docs/core/exulu-eval/configuration.mdx +0 -680
- package/mintlify-docs/core/exulu-eval/introduction.mdx +0 -459
- package/mintlify-docs/core/exulu-logging.mdx +0 -464
- package/mintlify-docs/core/exulu-otel.mdx +0 -670
- package/mintlify-docs/core/exulu-queues/api-reference.mdx +0 -648
- package/mintlify-docs/core/exulu-queues/configuration.mdx +0 -650
- package/mintlify-docs/core/exulu-queues/introduction.mdx +0 -474
- package/mintlify-docs/core/exulu-reranker/api-reference.mdx +0 -630
- package/mintlify-docs/core/exulu-reranker/configuration.mdx +0 -663
- package/mintlify-docs/core/exulu-reranker/introduction.mdx +0 -516
- package/mintlify-docs/core/exulu-tool/api-reference.mdx +0 -723
- package/mintlify-docs/core/exulu-tool/configuration.mdx +0 -805
- package/mintlify-docs/core/exulu-tool/introduction.mdx +0 -539
- package/mintlify-docs/core/exulu-variables/api-reference.mdx +0 -699
- package/mintlify-docs/core/exulu-variables/configuration.mdx +0 -736
- package/mintlify-docs/core/exulu-variables/introduction.mdx +0 -511
- package/mintlify-docs/development.mdx +0 -94
- package/mintlify-docs/docs.json +0 -248
- package/mintlify-docs/enterprise-edition.mdx +0 -538
- package/mintlify-docs/essentials/code.mdx +0 -35
- package/mintlify-docs/essentials/images.mdx +0 -59
- package/mintlify-docs/essentials/markdown.mdx +0 -88
- package/mintlify-docs/essentials/navigation.mdx +0 -87
- package/mintlify-docs/essentials/reusable-snippets.mdx +0 -110
- package/mintlify-docs/essentials/settings.mdx +0 -318
- package/mintlify-docs/favicon.svg +0 -3
- package/mintlify-docs/frontend/introduction.mdx +0 -39
- package/mintlify-docs/getting-started.mdx +0 -267
- package/mintlify-docs/guides/custom-agent.mdx +0 -608
- package/mintlify-docs/guides/first-agent.mdx +0 -315
- package/mintlify-docs/images/admin_ui.png +0 -0
- package/mintlify-docs/images/contexts.png +0 -0
- package/mintlify-docs/images/create_agents.png +0 -0
- package/mintlify-docs/images/evals.png +0 -0
- package/mintlify-docs/images/graphql.png +0 -0
- package/mintlify-docs/images/graphql_api.png +0 -0
- package/mintlify-docs/images/hero-dark.png +0 -0
- package/mintlify-docs/images/hero-light.png +0 -0
- package/mintlify-docs/images/hero.png +0 -0
- package/mintlify-docs/images/knowledge_sources.png +0 -0
- package/mintlify-docs/images/mcp.png +0 -0
- package/mintlify-docs/images/scaling.png +0 -0
- package/mintlify-docs/index.mdx +0 -411
- package/mintlify-docs/logo/dark.svg +0 -9
- package/mintlify-docs/logo/light.svg +0 -9
- package/mintlify-docs/partners.mdx +0 -558
- package/mintlify-docs/products.mdx +0 -77
- package/mintlify-docs/snippets/snippet-intro.mdx +0 -4
- package/mintlify-docs/styles.css +0 -207
- package/ngrok.bash +0 -1
- package/ngrok.md +0 -6
- package/ngrok.yml +0 -10
- package/release.config.cjs +0 -15
- package/skills-lock.json +0 -10
- package/types/context-processor.ts +0 -45
- package/types/enums/eval-types.ts +0 -5
- package/types/enums/field-types.ts +0 -1
- package/types/enums/jobs.ts +0 -11
- package/types/enums/statistics.ts +0 -13
- package/types/exulu-table-definition.ts +0 -79
- package/types/file-types.ts +0 -18
- package/types/models/agent-session.ts +0 -27
- package/types/models/agent.ts +0 -68
- package/types/models/context.ts +0 -53
- package/types/models/embedding.ts +0 -17
- package/types/models/eval-run.ts +0 -40
- package/types/models/exulu-agent-tool-config.ts +0 -11
- package/types/models/item.ts +0 -21
- package/types/models/job.ts +0 -8
- package/types/models/project.ts +0 -16
- package/types/models/rate-limiter-rules.ts +0 -7
- package/types/models/test-case.ts +0 -25
- package/types/models/tool.ts +0 -9
- package/types/models/user-role.ts +0 -12
- package/types/models/user.ts +0 -20
- package/types/models/variable.ts +0 -8
- package/types/models/vector-methods.ts +0 -7
- package/types/provider-config.ts +0 -21
- package/types/queue-config.ts +0 -16
- package/types/rbac-rights-modes.ts +0 -1
- package/types/statistics.ts +0 -20
- package/types/workflow.ts +0 -31
- /package/ee/{documents → python/documents}/THIRD_PARTY_LICENSES/docling.txt +0 -0
- /package/ee/{documents/processing → python}/requirements.txt +0 -0
|
@@ -1,699 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "API reference"
|
|
3
|
-
description: "Complete method and property reference for ExuluVariables"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
## ExuluVariables object
|
|
7
|
-
|
|
8
|
-
ExuluVariables is exported as a utility object:
|
|
9
|
-
|
|
10
|
-
```typescript
|
|
11
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
12
|
-
|
|
13
|
-
// Access the get method
|
|
14
|
-
const value = await ExuluVariables.get("variable_name");
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Methods
|
|
18
|
-
|
|
19
|
-
### get()
|
|
20
|
-
|
|
21
|
-
Retrieves and decrypts a variable value from the database.
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
async get(name: string): Promise<string>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
<ParamField path="name" type="string" required>
|
|
28
|
-
The unique name of the variable to retrieve
|
|
29
|
-
</ParamField>
|
|
30
|
-
|
|
31
|
-
<ResponseField name="return" type="Promise<string>">
|
|
32
|
-
The decrypted variable value
|
|
33
|
-
</ResponseField>
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
37
|
-
|
|
38
|
-
// Retrieve a variable
|
|
39
|
-
const apiKey = await ExuluVariables.get("openai_api_key");
|
|
40
|
-
|
|
41
|
-
console.log(apiKey); // "sk-proj-..."
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Behavior:**
|
|
45
|
-
1. Queries the `variables` table for the specified `name`
|
|
46
|
-
2. Throws an error if the variable is not found
|
|
47
|
-
3. If `encrypted: true`, decrypts the value using AES with `NEXTAUTH_SECRET`
|
|
48
|
-
4. Returns the decrypted (or plain) value
|
|
49
|
-
|
|
50
|
-
**Error handling:**
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
try {
|
|
54
|
-
const apiKey = await ExuluVariables.get("my_variable");
|
|
55
|
-
console.log("Retrieved:", apiKey);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error("Error:", error.message);
|
|
58
|
-
// Error: Variable my_variable not found.
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
**Throws:**
|
|
63
|
-
- Error if variable name doesn't exist
|
|
64
|
-
- Error if database connection fails
|
|
65
|
-
- Error if decryption fails (wrong `NEXTAUTH_SECRET`)
|
|
66
|
-
|
|
67
|
-
## Variable type
|
|
68
|
-
|
|
69
|
-
Variables in the database follow this structure:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
interface Variable {
|
|
73
|
-
name: string; // Primary key, unique identifier
|
|
74
|
-
value: string; // Encrypted or plain text value
|
|
75
|
-
encrypted: boolean; // Whether value is encrypted
|
|
76
|
-
created_at?: Date; // When variable was created
|
|
77
|
-
updated_at?: Date; // When variable was last updated
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
<ResponseField name="name" type="string">
|
|
82
|
-
Unique variable identifier
|
|
83
|
-
</ResponseField>
|
|
84
|
-
|
|
85
|
-
<ResponseField name="value" type="string">
|
|
86
|
-
The variable value (encrypted if `encrypted: true`)
|
|
87
|
-
</ResponseField>
|
|
88
|
-
|
|
89
|
-
<ResponseField name="encrypted" type="boolean">
|
|
90
|
-
Whether the value is encrypted at rest
|
|
91
|
-
</ResponseField>
|
|
92
|
-
|
|
93
|
-
<ResponseField name="created_at" type="Date">
|
|
94
|
-
Timestamp when created
|
|
95
|
-
</ResponseField>
|
|
96
|
-
|
|
97
|
-
<ResponseField name="updated_at" type="Date">
|
|
98
|
-
Timestamp when last updated
|
|
99
|
-
</ResponseField>
|
|
100
|
-
|
|
101
|
-
## Usage examples
|
|
102
|
-
|
|
103
|
-
### Basic retrieval
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
107
|
-
|
|
108
|
-
async function getApiKey() {
|
|
109
|
-
const apiKey = await ExuluVariables.get("openai_api_key");
|
|
110
|
-
return apiKey;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const key = await getApiKey();
|
|
114
|
-
console.log(key); // "sk-proj-..."
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### With error handling
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
121
|
-
|
|
122
|
-
async function getVariableWithFallback(name: string, fallback: string) {
|
|
123
|
-
try {
|
|
124
|
-
return await ExuluVariables.get(name);
|
|
125
|
-
} catch (error) {
|
|
126
|
-
console.warn(`Variable ${name} not found, using fallback`);
|
|
127
|
-
return fallback;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Use with fallback
|
|
132
|
-
const apiKey = await getVariableWithFallback(
|
|
133
|
-
"openai_api_key",
|
|
134
|
-
process.env.OPENAI_API_KEY || ""
|
|
135
|
-
);
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Retrieving multiple variables
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
142
|
-
|
|
143
|
-
async function getVariables(names: string[]) {
|
|
144
|
-
const values = await Promise.all(
|
|
145
|
-
names.map((name) => ExuluVariables.get(name))
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
return Object.fromEntries(
|
|
149
|
-
names.map((name, i) => [name, values[i]])
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Retrieve multiple
|
|
154
|
-
const vars = await getVariables([
|
|
155
|
-
"openai_api_key",
|
|
156
|
-
"anthropic_api_key",
|
|
157
|
-
"google_api_key"
|
|
158
|
-
]);
|
|
159
|
-
|
|
160
|
-
console.log(vars.openai_api_key); // "sk-..."
|
|
161
|
-
console.log(vars.anthropic_api_key); // "sk-ant-..."
|
|
162
|
-
console.log(vars.google_api_key); // "AIza..."
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### With ExuluAgent
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
import { ExuluAgent, ExuluVariables } from "@exulu/backend";
|
|
169
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
170
|
-
|
|
171
|
-
// Retrieve API key
|
|
172
|
-
const openaiKey = await ExuluVariables.get("openai_api_key");
|
|
173
|
-
|
|
174
|
-
// Use in agent
|
|
175
|
-
const agent = new ExuluAgent({
|
|
176
|
-
id: "assistant",
|
|
177
|
-
name: "AI Assistant",
|
|
178
|
-
type: "agent",
|
|
179
|
-
description: "General AI assistant",
|
|
180
|
-
provider: "openai",
|
|
181
|
-
authenticationInformation: openaiKey, // Use retrieved variable
|
|
182
|
-
config: {
|
|
183
|
-
name: "gpt-4o",
|
|
184
|
-
model: {
|
|
185
|
-
create: ({ apiKey }) => createOpenAI({ apiKey: apiKey || openaiKey })("gpt-4o")
|
|
186
|
-
},
|
|
187
|
-
instructions: "You are a helpful assistant."
|
|
188
|
-
},
|
|
189
|
-
capabilities: { text: true, images: [], files: [], audio: [], video: [] }
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// Generate response
|
|
193
|
-
const response = await agent.generateSync({
|
|
194
|
-
prompt: "Hello!",
|
|
195
|
-
agentInstance: await loadAgent("assistant"),
|
|
196
|
-
statistics: { label: "assistant", trigger: "api" }
|
|
197
|
-
});
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### With ExuluEmbedder
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { ExuluEmbedder, ExuluVariables } from "@exulu/backend";
|
|
204
|
-
|
|
205
|
-
// Retrieve API key
|
|
206
|
-
const openaiKey = await ExuluVariables.get("openai_api_key");
|
|
207
|
-
|
|
208
|
-
// Create embedder
|
|
209
|
-
const embedder = new ExuluEmbedder({
|
|
210
|
-
id: "openai_embedder",
|
|
211
|
-
name: "OpenAI Embeddings",
|
|
212
|
-
provider: "openai",
|
|
213
|
-
model: "text-embedding-3-small",
|
|
214
|
-
vectorDimensions: 1536,
|
|
215
|
-
authenticationInformation: openaiKey // Use retrieved variable
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Generate embeddings
|
|
219
|
-
const embeddings = await embedder.generate([
|
|
220
|
-
"First text to embed",
|
|
221
|
-
"Second text to embed"
|
|
222
|
-
]);
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### With ExuluTool
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
import { ExuluTool, ExuluVariables } from "@exulu/backend";
|
|
229
|
-
import { z } from "zod";
|
|
230
|
-
|
|
231
|
-
// Create tool with variable reference
|
|
232
|
-
const githubTool = new ExuluTool({
|
|
233
|
-
id: "github_search",
|
|
234
|
-
name: "search_github",
|
|
235
|
-
description: "Searches GitHub repositories",
|
|
236
|
-
type: "function",
|
|
237
|
-
inputSchema: z.object({
|
|
238
|
-
query: z.string()
|
|
239
|
-
}),
|
|
240
|
-
config: [
|
|
241
|
-
{
|
|
242
|
-
name: "github_token",
|
|
243
|
-
type: "variable",
|
|
244
|
-
value: "github_api_token" // Variable name
|
|
245
|
-
}
|
|
246
|
-
],
|
|
247
|
-
execute: async ({ query }, config) => {
|
|
248
|
-
// Retrieve variable inside execute
|
|
249
|
-
const token = await ExuluVariables.get("github_api_token");
|
|
250
|
-
|
|
251
|
-
const response = await fetch(
|
|
252
|
-
`https://api.github.com/search/repositories?q=${query}`,
|
|
253
|
-
{
|
|
254
|
-
headers: {
|
|
255
|
-
Authorization: `Bearer ${token}`,
|
|
256
|
-
"Accept": "application/vnd.github+json"
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
const data = await response.json();
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
result: JSON.stringify(
|
|
265
|
-
data.items.slice(0, 5).map((item: any) => ({
|
|
266
|
-
name: item.full_name,
|
|
267
|
-
description: item.description,
|
|
268
|
-
stars: item.stargazers_count,
|
|
269
|
-
url: item.html_url
|
|
270
|
-
}))
|
|
271
|
-
)
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Environment-aware retrieval
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
281
|
-
|
|
282
|
-
async function getEnvironmentVariable(baseName: string) {
|
|
283
|
-
const env = process.env.NODE_ENV || "dev";
|
|
284
|
-
const variableName = `${env}_${baseName}`;
|
|
285
|
-
|
|
286
|
-
return await ExuluVariables.get(variableName);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// In development: retrieves "dev_openai_api_key"
|
|
290
|
-
// In production: retrieves "prod_openai_api_key"
|
|
291
|
-
const apiKey = await getEnvironmentVariable("openai_api_key");
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Tenant-specific retrieval
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
298
|
-
|
|
299
|
-
async function getTenantVariable(tenantId: string, variableName: string) {
|
|
300
|
-
const fullName = `tenant_${tenantId}_${variableName}`;
|
|
301
|
-
return await ExuluVariables.get(fullName);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Retrieve tenant-specific API key
|
|
305
|
-
const tenantApiKey = await getTenantVariable("acme_corp", "openai_api_key");
|
|
306
|
-
// Retrieves "tenant_acme_corp_openai_api_key"
|
|
307
|
-
|
|
308
|
-
// Use with tenant agent
|
|
309
|
-
const tenantAgent = new ExuluAgent({
|
|
310
|
-
id: `agent_${tenantId}`,
|
|
311
|
-
name: `Agent for ${tenantId}`,
|
|
312
|
-
type: "agent",
|
|
313
|
-
description: "Tenant-specific agent",
|
|
314
|
-
provider: "openai",
|
|
315
|
-
authenticationInformation: tenantApiKey,
|
|
316
|
-
config: { /* ... */ },
|
|
317
|
-
capabilities: { text: true, images: [], files: [], audio: [], video: [] }
|
|
318
|
-
});
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
### Caching variables
|
|
322
|
-
|
|
323
|
-
For performance, cache frequently accessed variables:
|
|
324
|
-
|
|
325
|
-
```typescript
|
|
326
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
327
|
-
|
|
328
|
-
class VariableCache {
|
|
329
|
-
private cache = new Map<string, { value: string; expires: number }>();
|
|
330
|
-
private ttl: number;
|
|
331
|
-
|
|
332
|
-
constructor(ttlSeconds: number = 300) {
|
|
333
|
-
this.ttl = ttlSeconds * 1000;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
async get(name: string): Promise<string> {
|
|
337
|
-
const cached = this.cache.get(name);
|
|
338
|
-
|
|
339
|
-
if (cached && cached.expires > Date.now()) {
|
|
340
|
-
return cached.value;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const value = await ExuluVariables.get(name);
|
|
344
|
-
|
|
345
|
-
this.cache.set(name, {
|
|
346
|
-
value,
|
|
347
|
-
expires: Date.now() + this.ttl
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
return value;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
invalidate(name: string) {
|
|
354
|
-
this.cache.delete(name);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
clear() {
|
|
358
|
-
this.cache.clear();
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Use cache
|
|
363
|
-
const cache = new VariableCache(300); // 5 minute TTL
|
|
364
|
-
|
|
365
|
-
const apiKey = await cache.get("openai_api_key"); // Fetches from DB
|
|
366
|
-
const apiKey2 = await cache.get("openai_api_key"); // Returns cached value
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Validating variables on startup
|
|
370
|
-
|
|
371
|
-
```typescript
|
|
372
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
373
|
-
|
|
374
|
-
const REQUIRED_VARIABLES = [
|
|
375
|
-
"openai_api_key",
|
|
376
|
-
"anthropic_api_key",
|
|
377
|
-
"database_url",
|
|
378
|
-
"redis_url"
|
|
379
|
-
];
|
|
380
|
-
|
|
381
|
-
async function validateRequiredVariables() {
|
|
382
|
-
const missing: string[] = [];
|
|
383
|
-
|
|
384
|
-
for (const name of REQUIRED_VARIABLES) {
|
|
385
|
-
try {
|
|
386
|
-
await ExuluVariables.get(name);
|
|
387
|
-
console.log(`✓ ${name}`);
|
|
388
|
-
} catch (error) {
|
|
389
|
-
console.error(`✗ ${name}`);
|
|
390
|
-
missing.push(name);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (missing.length > 0) {
|
|
395
|
-
throw new Error(
|
|
396
|
-
`Missing required variables: ${missing.join(", ")}\n` +
|
|
397
|
-
`Please add them to the database via UI or SQL.`
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
console.log("All required variables present.");
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Run on application startup
|
|
405
|
-
validateRequiredVariables()
|
|
406
|
-
.then(() => console.log("Starting application..."))
|
|
407
|
-
.catch((error) => {
|
|
408
|
-
console.error("Startup failed:", error.message);
|
|
409
|
-
process.exit(1);
|
|
410
|
-
});
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### Dynamic configuration
|
|
414
|
-
|
|
415
|
-
```typescript
|
|
416
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
417
|
-
|
|
418
|
-
async function getDynamicConfig() {
|
|
419
|
-
const config = {
|
|
420
|
-
llm: {
|
|
421
|
-
provider: await ExuluVariables.get("llm_provider").catch(() => "openai"),
|
|
422
|
-
apiKey: await ExuluVariables.get("llm_api_key"),
|
|
423
|
-
model: await ExuluVariables.get("llm_model").catch(() => "gpt-4o")
|
|
424
|
-
},
|
|
425
|
-
embeddings: {
|
|
426
|
-
provider: await ExuluVariables.get("embeddings_provider").catch(() => "openai"),
|
|
427
|
-
apiKey: await ExuluVariables.get("embeddings_api_key"),
|
|
428
|
-
model: await ExuluVariables.get("embeddings_model").catch(() => "text-embedding-3-small")
|
|
429
|
-
},
|
|
430
|
-
features: {
|
|
431
|
-
analytics: await ExuluVariables.get("feature_analytics").catch(() => "false") === "true",
|
|
432
|
-
rateLimit: parseInt(await ExuluVariables.get("rate_limit_per_minute").catch(() => "100"))
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
return config;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// Use dynamic config
|
|
440
|
-
const config = await getDynamicConfig();
|
|
441
|
-
|
|
442
|
-
const agent = new ExuluAgent({
|
|
443
|
-
id: "dynamic_agent",
|
|
444
|
-
name: "Dynamic Agent",
|
|
445
|
-
type: "agent",
|
|
446
|
-
provider: config.llm.provider,
|
|
447
|
-
authenticationInformation: config.llm.apiKey,
|
|
448
|
-
config: {
|
|
449
|
-
name: config.llm.model,
|
|
450
|
-
// ...
|
|
451
|
-
},
|
|
452
|
-
capabilities: { text: true, images: [], files: [], audio: [], video: [] }
|
|
453
|
-
});
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### Secret rotation helper
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
import { ExuluVariables, postgresClient } from "@exulu/backend";
|
|
460
|
-
import CryptoJS from "crypto-js";
|
|
461
|
-
|
|
462
|
-
async function rotateSecret(variableName: string, newValue: string) {
|
|
463
|
-
const { db } = await postgresClient();
|
|
464
|
-
|
|
465
|
-
// Verify old value works
|
|
466
|
-
try {
|
|
467
|
-
const oldValue = await ExuluVariables.get(variableName);
|
|
468
|
-
console.log("Current value retrieved successfully");
|
|
469
|
-
} catch (error) {
|
|
470
|
-
throw new Error(`Cannot retrieve current value: ${error.message}`);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Encrypt new value
|
|
474
|
-
const encrypted = CryptoJS.AES.encrypt(
|
|
475
|
-
newValue,
|
|
476
|
-
process.env.NEXTAUTH_SECRET
|
|
477
|
-
).toString();
|
|
478
|
-
|
|
479
|
-
// Update variable
|
|
480
|
-
await db("variables")
|
|
481
|
-
.where({ name: variableName })
|
|
482
|
-
.update({
|
|
483
|
-
value: encrypted,
|
|
484
|
-
updated_at: new Date()
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
// Verify new value
|
|
488
|
-
const updated = await ExuluVariables.get(variableName);
|
|
489
|
-
|
|
490
|
-
if (updated !== newValue) {
|
|
491
|
-
throw new Error("Verification failed after rotation");
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
console.log(`✓ Secret rotated successfully: ${variableName}`);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// Rotate API key
|
|
498
|
-
await rotateSecret("openai_api_key", "sk-proj-NEW_KEY_HERE");
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Listing variables
|
|
502
|
-
|
|
503
|
-
```typescript
|
|
504
|
-
import { postgresClient } from "@exulu/backend";
|
|
505
|
-
|
|
506
|
-
async function listVariables() {
|
|
507
|
-
const { db } = await postgresClient();
|
|
508
|
-
|
|
509
|
-
const variables = await db
|
|
510
|
-
.from("variables")
|
|
511
|
-
.select("name", "encrypted", "created_at", "updated_at")
|
|
512
|
-
.orderBy("name");
|
|
513
|
-
|
|
514
|
-
console.log("Variables:");
|
|
515
|
-
for (const v of variables) {
|
|
516
|
-
console.log(` ${v.name} (encrypted: ${v.encrypted})`);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
return variables;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
await listVariables();
|
|
523
|
-
// Variables:
|
|
524
|
-
// anthropic_api_key (encrypted: true)
|
|
525
|
-
// app_name (encrypted: false)
|
|
526
|
-
// app_version (encrypted: false)
|
|
527
|
-
// openai_api_key (encrypted: true)
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
## Integration patterns
|
|
531
|
-
|
|
532
|
-
### Factory function with variables
|
|
533
|
-
|
|
534
|
-
```typescript
|
|
535
|
-
import { ExuluAgent, ExuluVariables } from "@exulu/backend";
|
|
536
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
537
|
-
|
|
538
|
-
async function createAgentWithVariables(
|
|
539
|
-
id: string,
|
|
540
|
-
provider: string,
|
|
541
|
-
variableName: string
|
|
542
|
-
) {
|
|
543
|
-
const apiKey = await ExuluVariables.get(variableName);
|
|
544
|
-
|
|
545
|
-
return new ExuluAgent({
|
|
546
|
-
id,
|
|
547
|
-
name: `Agent ${id}`,
|
|
548
|
-
type: "agent",
|
|
549
|
-
description: "Agent with variable-based auth",
|
|
550
|
-
provider,
|
|
551
|
-
authenticationInformation: apiKey,
|
|
552
|
-
config: {
|
|
553
|
-
name: "gpt-4o",
|
|
554
|
-
model: {
|
|
555
|
-
create: ({ apiKey: key }) => createOpenAI({ apiKey: key || apiKey })("gpt-4o")
|
|
556
|
-
},
|
|
557
|
-
instructions: "You are a helpful assistant."
|
|
558
|
-
},
|
|
559
|
-
capabilities: { text: true, images: [], files: [], audio: [], video: [] }
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Create agents
|
|
564
|
-
const agent1 = await createAgentWithVariables("agent1", "openai", "openai_api_key");
|
|
565
|
-
const agent2 = await createAgentWithVariables("agent2", "anthropic", "anthropic_api_key");
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
### Middleware for API authentication
|
|
569
|
-
|
|
570
|
-
```typescript
|
|
571
|
-
import { ExuluVariables } from "@exulu/backend";
|
|
572
|
-
import express from "express";
|
|
573
|
-
|
|
574
|
-
const app = express();
|
|
575
|
-
|
|
576
|
-
// Middleware to inject API keys
|
|
577
|
-
app.use(async (req, res, next) => {
|
|
578
|
-
try {
|
|
579
|
-
req.apiKeys = {
|
|
580
|
-
openai: await ExuluVariables.get("openai_api_key"),
|
|
581
|
-
anthropic: await ExuluVariables.get("anthropic_api_key"),
|
|
582
|
-
google: await ExuluVariables.get("google_api_key")
|
|
583
|
-
};
|
|
584
|
-
next();
|
|
585
|
-
} catch (error) {
|
|
586
|
-
res.status(500).json({ error: "Failed to load API keys" });
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
// Use in routes
|
|
591
|
-
app.post("/api/generate", async (req, res) => {
|
|
592
|
-
const { provider } = req.body;
|
|
593
|
-
|
|
594
|
-
const agent = new ExuluAgent({
|
|
595
|
-
id: "api_agent",
|
|
596
|
-
provider,
|
|
597
|
-
authenticationInformation: req.apiKeys[provider],
|
|
598
|
-
// ...
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
const response = await agent.generateSync({
|
|
602
|
-
prompt: req.body.prompt,
|
|
603
|
-
agentInstance: await loadAgent("api_agent"),
|
|
604
|
-
statistics: { label: "api", trigger: "http" }
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
res.json({ response });
|
|
608
|
-
});
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
## Best practices
|
|
612
|
-
|
|
613
|
-
<Tip>
|
|
614
|
-
**Cache variables**: For frequently accessed variables, implement caching to reduce database queries.
|
|
615
|
-
</Tip>
|
|
616
|
-
|
|
617
|
-
<Note>
|
|
618
|
-
**Handle errors gracefully**: Always wrap `ExuluVariables.get()` in try/catch to handle missing variables.
|
|
619
|
-
</Note>
|
|
620
|
-
|
|
621
|
-
<Warning>
|
|
622
|
-
**Don't expose values**: Never return variable values through public APIs or logs. Only use them internally.
|
|
623
|
-
</Warning>
|
|
624
|
-
|
|
625
|
-
<Info>
|
|
626
|
-
**Validate on startup**: Check that all required variables exist before starting your application.
|
|
627
|
-
</Info>
|
|
628
|
-
|
|
629
|
-
## Error reference
|
|
630
|
-
|
|
631
|
-
### Variable not found
|
|
632
|
-
|
|
633
|
-
```typescript
|
|
634
|
-
// Error: Variable my_variable not found.
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
**Cause**: Variable doesn't exist in database
|
|
638
|
-
|
|
639
|
-
**Solution**: Create the variable:
|
|
640
|
-
|
|
641
|
-
```sql
|
|
642
|
-
INSERT INTO variables (name, value, encrypted)
|
|
643
|
-
VALUES ('my_variable', 'value', true);
|
|
644
|
-
```
|
|
645
|
-
|
|
646
|
-
### Decryption error
|
|
647
|
-
|
|
648
|
-
```typescript
|
|
649
|
-
// Error: Malformed UTF-8 data
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
**Cause**: Wrong `NEXTAUTH_SECRET` or corrupted encrypted value
|
|
653
|
-
|
|
654
|
-
**Solution**: Re-encrypt with correct secret or verify `NEXTAUTH_SECRET` is correct
|
|
655
|
-
|
|
656
|
-
### Database connection error
|
|
657
|
-
|
|
658
|
-
```typescript
|
|
659
|
-
// Error: Connection refused / timeout
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
**Cause**: Database not accessible
|
|
663
|
-
|
|
664
|
-
**Solution**: Check database connection settings and ensure database is running
|
|
665
|
-
|
|
666
|
-
## Type definitions
|
|
667
|
-
|
|
668
|
-
```typescript
|
|
669
|
-
// Variable database record
|
|
670
|
-
interface Variable {
|
|
671
|
-
name: string;
|
|
672
|
-
value: string;
|
|
673
|
-
encrypted: boolean;
|
|
674
|
-
created_at?: Date;
|
|
675
|
-
updated_at?: Date;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// ExuluVariables utility
|
|
679
|
-
interface ExuluVariables {
|
|
680
|
-
get(name: string): Promise<string>;
|
|
681
|
-
}
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
## Next steps
|
|
685
|
-
|
|
686
|
-
<CardGroup cols={2}>
|
|
687
|
-
<Card title="Configuration guide" icon="gear" href="/core/exulu-variables/configuration">
|
|
688
|
-
Learn about setup and management
|
|
689
|
-
</Card>
|
|
690
|
-
<Card title="Overview" icon="book" href="/core/exulu-variables/introduction">
|
|
691
|
-
Understand variable concepts
|
|
692
|
-
</Card>
|
|
693
|
-
<Card title="ExuluAgent" icon="robot" href="/core/exulu-agent/introduction">
|
|
694
|
-
Use variables with agents
|
|
695
|
-
</Card>
|
|
696
|
-
<Card title="ExuluTool" icon="wrench" href="/core/exulu-tool/introduction">
|
|
697
|
-
Use variables with tools
|
|
698
|
-
</Card>
|
|
699
|
-
</CardGroup>
|