@exulu/backend 1.48.1 → 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.
Files changed (165) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +353 -42
  3. package/dist/index.d.cts +422 -327
  4. package/dist/index.d.ts +422 -327
  5. package/dist/index.js +341 -38
  6. package/ee/{markdown.ts → chunking/markdown.ts} +2 -2
  7. package/ee/python/README.md +295 -0
  8. package/ee/python/documents/processing/README.md +155 -0
  9. package/ee/{documents → python/documents}/processing/doc_processor.ts +25 -17
  10. package/ee/{documents/processing/pdf_to_markdown.py → python/documents/processing/document_to_markdown.py} +3 -10
  11. package/ee/python/setup.sh +180 -0
  12. package/package.json +17 -5
  13. package/scripts/postinstall.cjs +149 -0
  14. package/.agents/skills/mintlify/SKILL.md +0 -347
  15. package/.editorconfig +0 -15
  16. package/.eslintrc.json +0 -52
  17. package/.github/workflows/release-backend.yml +0 -38
  18. package/.husky/commit-msg +0 -1
  19. package/.jscpd.json +0 -18
  20. package/.mcp.json +0 -18
  21. package/.nvmrc +0 -1
  22. package/.prettierignore +0 -5
  23. package/.prettierrc.json +0 -12
  24. package/CHANGELOG.md +0 -6
  25. package/SECURITY.md +0 -5
  26. package/commitlint.config.js +0 -4
  27. package/devops/documentation/patch-older-releases.md +0 -42
  28. package/ee/documents/processing/build_pdf_processor.sh +0 -35
  29. package/ee/documents/processing/chunk_markdown.py +0 -263
  30. package/ee/documents/processing/pdf_processor.spec +0 -115
  31. package/eslint.config.js +0 -88
  32. package/jest.config.ts +0 -25
  33. package/mintlify-docs/.mintignore +0 -7
  34. package/mintlify-docs/AGENTS.md +0 -33
  35. package/mintlify-docs/CLAUDE.MD +0 -50
  36. package/mintlify-docs/CONTRIBUTING.md +0 -32
  37. package/mintlify-docs/LICENSE +0 -21
  38. package/mintlify-docs/README.md +0 -55
  39. package/mintlify-docs/ai-tools/claude-code.mdx +0 -43
  40. package/mintlify-docs/ai-tools/cursor.mdx +0 -39
  41. package/mintlify-docs/ai-tools/windsurf.mdx +0 -39
  42. package/mintlify-docs/api-reference/core-types/agent-types.mdx +0 -110
  43. package/mintlify-docs/api-reference/core-types/analytics-types.mdx +0 -95
  44. package/mintlify-docs/api-reference/core-types/configuration-types.mdx +0 -83
  45. package/mintlify-docs/api-reference/core-types/evaluation-types.mdx +0 -106
  46. package/mintlify-docs/api-reference/core-types/job-types.mdx +0 -135
  47. package/mintlify-docs/api-reference/core-types/overview.mdx +0 -73
  48. package/mintlify-docs/api-reference/core-types/prompt-types.mdx +0 -102
  49. package/mintlify-docs/api-reference/core-types/rbac-types.mdx +0 -163
  50. package/mintlify-docs/api-reference/core-types/session-types.mdx +0 -77
  51. package/mintlify-docs/api-reference/core-types/user-management.mdx +0 -112
  52. package/mintlify-docs/api-reference/core-types/workflow-types.mdx +0 -88
  53. package/mintlify-docs/api-reference/core-types.mdx +0 -585
  54. package/mintlify-docs/api-reference/dynamic-types.mdx +0 -851
  55. package/mintlify-docs/api-reference/endpoint/create.mdx +0 -4
  56. package/mintlify-docs/api-reference/endpoint/delete.mdx +0 -4
  57. package/mintlify-docs/api-reference/endpoint/get.mdx +0 -4
  58. package/mintlify-docs/api-reference/endpoint/webhook.mdx +0 -4
  59. package/mintlify-docs/api-reference/introduction.mdx +0 -661
  60. package/mintlify-docs/api-reference/mutations.mdx +0 -1012
  61. package/mintlify-docs/api-reference/openapi.json +0 -217
  62. package/mintlify-docs/api-reference/queries.mdx +0 -1154
  63. package/mintlify-docs/backend/introduction.mdx +0 -218
  64. package/mintlify-docs/changelog.mdx +0 -387
  65. package/mintlify-docs/community-edition.mdx +0 -304
  66. package/mintlify-docs/core/exulu-agent/api-reference.mdx +0 -894
  67. package/mintlify-docs/core/exulu-agent/configuration.mdx +0 -690
  68. package/mintlify-docs/core/exulu-agent/introduction.mdx +0 -552
  69. package/mintlify-docs/core/exulu-app/api-reference.mdx +0 -481
  70. package/mintlify-docs/core/exulu-app/configuration.mdx +0 -319
  71. package/mintlify-docs/core/exulu-app/introduction.mdx +0 -117
  72. package/mintlify-docs/core/exulu-authentication.mdx +0 -810
  73. package/mintlify-docs/core/exulu-chunkers/api-reference.mdx +0 -1011
  74. package/mintlify-docs/core/exulu-chunkers/configuration.mdx +0 -596
  75. package/mintlify-docs/core/exulu-chunkers/introduction.mdx +0 -403
  76. package/mintlify-docs/core/exulu-context/api-reference.mdx +0 -911
  77. package/mintlify-docs/core/exulu-context/configuration.mdx +0 -648
  78. package/mintlify-docs/core/exulu-context/introduction.mdx +0 -394
  79. package/mintlify-docs/core/exulu-database.mdx +0 -811
  80. package/mintlify-docs/core/exulu-default-agents.mdx +0 -545
  81. package/mintlify-docs/core/exulu-eval/api-reference.mdx +0 -772
  82. package/mintlify-docs/core/exulu-eval/configuration.mdx +0 -680
  83. package/mintlify-docs/core/exulu-eval/introduction.mdx +0 -459
  84. package/mintlify-docs/core/exulu-logging.mdx +0 -464
  85. package/mintlify-docs/core/exulu-otel.mdx +0 -670
  86. package/mintlify-docs/core/exulu-queues/api-reference.mdx +0 -648
  87. package/mintlify-docs/core/exulu-queues/configuration.mdx +0 -650
  88. package/mintlify-docs/core/exulu-queues/introduction.mdx +0 -474
  89. package/mintlify-docs/core/exulu-reranker/api-reference.mdx +0 -630
  90. package/mintlify-docs/core/exulu-reranker/configuration.mdx +0 -663
  91. package/mintlify-docs/core/exulu-reranker/introduction.mdx +0 -516
  92. package/mintlify-docs/core/exulu-tool/api-reference.mdx +0 -723
  93. package/mintlify-docs/core/exulu-tool/configuration.mdx +0 -805
  94. package/mintlify-docs/core/exulu-tool/introduction.mdx +0 -539
  95. package/mintlify-docs/core/exulu-variables/api-reference.mdx +0 -699
  96. package/mintlify-docs/core/exulu-variables/configuration.mdx +0 -736
  97. package/mintlify-docs/core/exulu-variables/introduction.mdx +0 -511
  98. package/mintlify-docs/development.mdx +0 -94
  99. package/mintlify-docs/docs.json +0 -248
  100. package/mintlify-docs/enterprise-edition.mdx +0 -538
  101. package/mintlify-docs/essentials/code.mdx +0 -35
  102. package/mintlify-docs/essentials/images.mdx +0 -59
  103. package/mintlify-docs/essentials/markdown.mdx +0 -88
  104. package/mintlify-docs/essentials/navigation.mdx +0 -87
  105. package/mintlify-docs/essentials/reusable-snippets.mdx +0 -110
  106. package/mintlify-docs/essentials/settings.mdx +0 -318
  107. package/mintlify-docs/favicon.svg +0 -3
  108. package/mintlify-docs/frontend/introduction.mdx +0 -39
  109. package/mintlify-docs/getting-started.mdx +0 -267
  110. package/mintlify-docs/guides/custom-agent.mdx +0 -608
  111. package/mintlify-docs/guides/first-agent.mdx +0 -315
  112. package/mintlify-docs/images/admin_ui.png +0 -0
  113. package/mintlify-docs/images/contexts.png +0 -0
  114. package/mintlify-docs/images/create_agents.png +0 -0
  115. package/mintlify-docs/images/evals.png +0 -0
  116. package/mintlify-docs/images/graphql.png +0 -0
  117. package/mintlify-docs/images/graphql_api.png +0 -0
  118. package/mintlify-docs/images/hero-dark.png +0 -0
  119. package/mintlify-docs/images/hero-light.png +0 -0
  120. package/mintlify-docs/images/hero.png +0 -0
  121. package/mintlify-docs/images/knowledge_sources.png +0 -0
  122. package/mintlify-docs/images/mcp.png +0 -0
  123. package/mintlify-docs/images/scaling.png +0 -0
  124. package/mintlify-docs/index.mdx +0 -411
  125. package/mintlify-docs/logo/dark.svg +0 -9
  126. package/mintlify-docs/logo/light.svg +0 -9
  127. package/mintlify-docs/partners.mdx +0 -558
  128. package/mintlify-docs/products.mdx +0 -77
  129. package/mintlify-docs/snippets/snippet-intro.mdx +0 -4
  130. package/mintlify-docs/styles.css +0 -207
  131. package/ngrok.bash +0 -1
  132. package/ngrok.md +0 -6
  133. package/ngrok.yml +0 -10
  134. package/release.config.cjs +0 -15
  135. package/skills-lock.json +0 -10
  136. package/types/context-processor.ts +0 -45
  137. package/types/enums/eval-types.ts +0 -5
  138. package/types/enums/field-types.ts +0 -1
  139. package/types/enums/jobs.ts +0 -11
  140. package/types/enums/statistics.ts +0 -13
  141. package/types/exulu-table-definition.ts +0 -79
  142. package/types/file-types.ts +0 -18
  143. package/types/models/agent-session.ts +0 -27
  144. package/types/models/agent.ts +0 -68
  145. package/types/models/context.ts +0 -53
  146. package/types/models/embedding.ts +0 -17
  147. package/types/models/eval-run.ts +0 -40
  148. package/types/models/exulu-agent-tool-config.ts +0 -11
  149. package/types/models/item.ts +0 -21
  150. package/types/models/job.ts +0 -8
  151. package/types/models/project.ts +0 -16
  152. package/types/models/rate-limiter-rules.ts +0 -7
  153. package/types/models/test-case.ts +0 -25
  154. package/types/models/tool.ts +0 -9
  155. package/types/models/user-role.ts +0 -12
  156. package/types/models/user.ts +0 -20
  157. package/types/models/variable.ts +0 -8
  158. package/types/models/vector-methods.ts +0 -7
  159. package/types/provider-config.ts +0 -21
  160. package/types/queue-config.ts +0 -16
  161. package/types/rbac-rights-modes.ts +0 -1
  162. package/types/statistics.ts +0 -20
  163. package/types/workflow.ts +0 -31
  164. /package/ee/{documents → python/documents}/THIRD_PARTY_LICENSES/docling.txt +0 -0
  165. /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>