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