@exulu/backend 3.1.0 → 3.3.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.d.ts CHANGED
@@ -4,9 +4,9 @@ import { Knex } from 'knex';
4
4
  import { RedisClientType } from 'redis';
5
5
  import * as bullmq from 'bullmq';
6
6
  import { Queue } from 'bullmq';
7
- import { Request, Express } from 'express';
7
+ import { Express } from 'express';
8
8
  import { transport } from 'winston';
9
- import { LanguageModel, Tool, UIMessage, streamText } from 'ai';
9
+ import { UIMessage, Tool, LanguageModel } from 'ai';
10
10
  import { z } from 'zod';
11
11
  import { Tiktoken } from 'tiktoken/lite';
12
12
  import models from 'tiktoken/model_to_encoding.json';
@@ -92,37 +92,24 @@ declare function redisClient(): Promise<{
92
92
  client: RedisClientType | null;
93
93
  }>;
94
94
 
95
- type ExuluProviderConfig = {
95
+ interface TestCase {
96
+ id: string;
96
97
  name: string;
97
- instructions: string;
98
- model: {
99
- create: ({ apiKey, user, role, project, agent }: {
100
- apiKey?: string | undefined;
101
- user?: number;
102
- role?: string;
103
- project?: string;
104
- agent?: string;
105
- }) => LanguageModel;
106
- };
107
- custom?: {
108
- name: string;
109
- description: string;
110
- }[];
111
- memory?: {
112
- lastMessages: number;
113
- vector: boolean;
114
- semanticRecall: {
115
- topK: number;
116
- messageRange: number;
117
- };
118
- };
119
- };
98
+ description?: string;
99
+ inputs: UIMessage[];
100
+ expected_output: string;
101
+ expected_tools?: string[];
102
+ expected_knowledge_sources?: string[];
103
+ expected_agent_tools?: string[];
104
+ createdAt: string;
105
+ updatedAt: string;
106
+ }
120
107
 
121
108
  interface ExuluAgent {
122
109
  id: string;
123
110
  modelName?: string;
124
111
  providerName?: string;
125
- /** @deprecated Hydrated for read compatibility; the underlying DB column is gone. */
112
+ /** @deprecated Hydrated for read compatibility; the underlying DB column is gone. Use model instead */
126
113
  provider?: string;
127
114
  source: "code" | "database";
128
115
  memory?: string;
@@ -133,7 +120,6 @@ interface ExuluAgent {
133
120
  image?: string;
134
121
  /** FK to models.id — replaces legacy provider + providerapikey columns. */
135
122
  model?: string;
136
- workflows?: ExuluProviderWorkflowConfig;
137
123
  firewall?: {
138
124
  enabled: boolean;
139
125
  scanners?: {
@@ -198,6 +184,61 @@ type fileTypes$1 = '.pdf' | '.docx' | '.xlsx' | '.xls' | '.csv' | '.pptx' | '.pp
198
184
  type audioTypes$1 = '.mp3' | '.wav' | '.m4a' | '.mp4' | '.mpeg';
199
185
  type videoTypes$1 = '.mp4' | '.m4a' | '.mp3' | '.mpeg' | '.wav';
200
186
 
187
+ type ExuluQueueConfig = {
188
+ queue: Queue;
189
+ ratelimit: number;
190
+ timeoutInSeconds?: number;
191
+ concurrency: {
192
+ worker: number;
193
+ queue: number;
194
+ };
195
+ retries?: number;
196
+ backoff?: {
197
+ type: "exponential" | "linear";
198
+ delay: number;
199
+ };
200
+ };
201
+
202
+ interface ExuluEvalParams {
203
+ id: string;
204
+ name: string;
205
+ description: string;
206
+ llm: boolean;
207
+ execute: (params: {
208
+ agent: ExuluAgent;
209
+ messages: UIMessage[];
210
+ testCase: TestCase;
211
+ config?: Record<string, any>;
212
+ }) => Promise<number>;
213
+ config?: {
214
+ name: string;
215
+ description: string;
216
+ }[];
217
+ queue: Promise<ExuluQueueConfig>;
218
+ }
219
+ declare class ExuluEval {
220
+ id: string;
221
+ name: string;
222
+ description: string;
223
+ llm: boolean;
224
+ private execute;
225
+ config?: {
226
+ name: string;
227
+ description: string;
228
+ }[];
229
+ queue?: Promise<ExuluQueueConfig>;
230
+ constructor({ id, name, description, execute, config, queue, llm }: ExuluEvalParams);
231
+ run(agent: ExuluAgent, testCase: TestCase, messages: UIMessage[], config?: Record<string, any>): Promise<number>;
232
+ }
233
+
234
+ type ExuluFieldTypes = "text" | "longText" | "shortText" | "number" | "boolean" | "code" | "json" | "enum" | "markdown" | "file" | "date" | "uuid";
235
+
236
+ type allFileTypes = imageTypes | fileTypes | audioTypes | videoTypes;
237
+ type audioTypes = ".mp3" | ".wav" | ".m4a" | ".mp4" | ".mpeg";
238
+ type videoTypes = ".mp4" | ".m4a" | ".mp3" | ".mpeg" | ".wav";
239
+ type imageTypes = ".png" | ".jpg" | ".jpeg" | ".gif" | ".webp";
240
+ type fileTypes = ".pdf" | ".docx" | ".doc" | ".xlsx" | ".xls" | ".csv" | ".pptx" | ".ppt" | ".txt" | ".md" | ".json" | ".srt" | ".html";
241
+
201
242
  interface Item {
202
243
  id?: string;
203
244
  name?: string;
@@ -220,163 +261,6 @@ interface Item {
220
261
  [key: string]: any;
221
262
  }
222
263
 
223
- /**
224
- * OAuth 2.0 configuration for an {@link ExuluTool}. When a tool is constructed
225
- * with an `oauth` property, Exulu wraps its `execute` so it only runs when a
226
- * valid access token exists for the calling (providerKey, userId) pair — where
227
- * providerKey defaults to the tool's id but can be shared across tools by
228
- * setting the "provider" field below. When no valid token exists the tool
229
- * short-circuits and returns an authorization URL the agent can show the user;
230
- * the generic /oauth/callback route completes the flow and persists the tokens.
231
- *
232
- * Only the standard authorization-code grant is supported. All values are
233
- * declared in code (source them from env vars or however you like) — none of
234
- * them are exposed as admin-configurable tool config.
235
- */
236
- interface ExuluOauthConfig {
237
- authType: "oauth";
238
- /**
239
- * Identifier for the OAuth provider (e.g., "google", "jira", "github").
240
- * Tools sharing the same provider share tokens under (provider, userId) —
241
- * one consent screen per provider per user instead of per tool. When
242
- * omitted, defaults to the tool's `id`, preserving per-tool behavior for
243
- * tools that don't opt in.
244
- */
245
- provider: string;
246
- /** The provider's authorization endpoint, e.g. https://app.hubspot.com/oauth/authorize */
247
- authorizationUrl: string;
248
- /** The provider's token endpoint, e.g. https://api.hubapi.com/oauth/v1/token */
249
- tokenUrl: string;
250
- clientId: string;
251
- /** Never leaves the server: used only in the server-side token exchange. */
252
- clientSecret: string;
253
- /** Scopes to request; joined with spaces in the authorization URL. */
254
- scopes: readonly string[];
255
- /** PKCE (S256). Defaults to true; set false for providers that reject PKCE. */
256
- pkce?: boolean;
257
- /**
258
- * Extra query params appended to the authorization URL, e.g.
259
- * `{ access_type: "offline", prompt: "consent" }` to make Google return a
260
- * refresh token.
261
- */
262
- extraAuthParams?: Record<string, string>;
263
- }
264
- interface CredentialField {
265
- name: string;
266
- label: string;
267
- type: "text" | "password";
268
- placeholder?: string;
269
- help?: string;
270
- }
271
- interface ExuluUserCredentialsConfig {
272
- authType: "user_credentials";
273
- provider: string;
274
- fields: CredentialField[];
275
- validate?: (values: Record<string, string>) => Promise<void>;
276
- }
277
- type ExuluAuthConfig = ExuluOauthConfig | ExuluUserCredentialsConfig;
278
- interface ExuluCredentialsToolContext {
279
- userId: string;
280
- provider: string;
281
- credentials: Record<string, string>;
282
- }
283
- /** The oauth context injected into an oauth-enabled tool's execute inputs. */
284
- type ExuluOauthToolContext = {
285
- accessToken: string;
286
- /** null when the provider did not report an expiry. */
287
- expiresAt: Date | null;
288
- /** Space-joined scopes the token was granted, when reported by the provider. */
289
- scopes: string | null;
290
- };
291
-
292
- declare const PUBLIC_TOOL_TYPES: readonly ["function", "web_search", "skill", "context"];
293
- type PublicToolType = (typeof PUBLIC_TOOL_TYPES)[number];
294
- type ToolType = PublicToolType | "agent" | "context";
295
- declare class ExuluTool {
296
- id: string;
297
- name: string;
298
- description: string;
299
- category: string;
300
- inputSchema?: z.ZodType;
301
- type: ToolType;
302
- tool: Tool;
303
- needsApproval: boolean;
304
- authentication?: ExuluAuthConfig;
305
- config: {
306
- name: string;
307
- description: string;
308
- type: "boolean" | "string" | "number" | "variable" | "json";
309
- default?: string | boolean | number | object;
310
- }[];
311
- constructor({ id, name, description, category, inputSchema, type, execute, config, needsApproval, authentication, }: {
312
- id: string;
313
- name: string;
314
- description: string;
315
- category?: string;
316
- inputSchema?: z.ZodType;
317
- type: PublicToolType;
318
- config: {
319
- name: string;
320
- description: string;
321
- type: "boolean" | "string" | "number" | "variable" | "json";
322
- default?: string | boolean | number | object;
323
- }[];
324
- needsApproval?: boolean;
325
- authentication?: ExuluAuthConfig;
326
- execute: (inputs: any, options?: any) => Promise<{
327
- result?: string;
328
- job?: string;
329
- items?: Item[];
330
- }> | AsyncGenerator<{
331
- result?: string;
332
- job?: string;
333
- items?: Item[];
334
- }>;
335
- });
336
- /**
337
- * Framework-only factory for tools whose `type` is managed by Exulu itself —
338
- * "agent" (agent-as-tool instrumentation) and "context" (internal retrieval
339
- * tools). NOT part of the public API: package consumers must use
340
- * `new ExuluTool(...)`, which only accepts a {@link PublicToolType}. Building
341
- * the tool as a "function" and then setting the managed type bypasses the
342
- * constructor guard without weakening it for consumers.
343
- */
344
- static internal(params: Omit<ConstructorParameters<typeof ExuluTool>[0], "type"> & {
345
- type: ToolType;
346
- }): ExuluTool;
347
- execute: ({ agent: agentId, config, user, inputs, project, items, }: {
348
- agent: string;
349
- config: ExuluConfig;
350
- user?: User;
351
- inputs: any;
352
- project?: string;
353
- items?: string[];
354
- }) => Promise<any>;
355
- }
356
-
357
- type ExuluFieldTypes = "text" | "longText" | "shortText" | "number" | "boolean" | "code" | "json" | "enum" | "markdown" | "file" | "date" | "uuid";
358
-
359
- type allFileTypes = imageTypes | fileTypes | audioTypes | videoTypes;
360
- type audioTypes = ".mp3" | ".wav" | ".m4a" | ".mp4" | ".mpeg";
361
- type videoTypes = ".mp4" | ".m4a" | ".mp3" | ".mpeg" | ".wav";
362
- type imageTypes = ".png" | ".jpg" | ".jpeg" | ".gif" | ".webp";
363
- type fileTypes = ".pdf" | ".docx" | ".doc" | ".xlsx" | ".xls" | ".csv" | ".pptx" | ".ppt" | ".txt" | ".md" | ".json" | ".srt" | ".html";
364
-
365
- type ExuluQueueConfig = {
366
- queue: Queue;
367
- ratelimit: number;
368
- timeoutInSeconds?: number;
369
- concurrency: {
370
- worker: number;
371
- queue: number;
372
- };
373
- retries?: number;
374
- backoff?: {
375
- type: "exponential" | "linear";
376
- delay: number;
377
- };
378
- };
379
-
380
264
  declare class ExuluStorage {
381
265
  private config;
382
266
  constructor({ config }: {
@@ -935,190 +819,261 @@ declare class ExuluContext {
935
819
  createChunksTable: () => Promise<void>;
936
820
  }
937
821
 
938
- type ExuluAgentToolConfig = {
939
- id: string;
940
- type: string;
941
- config: {
942
- name: string;
943
- variable: string | boolean | number | object;
944
- type: "boolean" | "string" | "number" | "variable" | "json";
945
- value?: any;
946
- default?: string | boolean | number | object;
947
- }[];
948
- };
949
-
950
- type ExuluSkill = {
951
- id: string;
952
- name: string;
953
- description: string;
954
- s3folder: string;
955
- tags: string[];
956
- usage_count: number;
957
- favorite_count: number;
958
- current_version: number;
959
- };
960
-
961
- type ExuluProviderWorkflowConfig = {
962
- enabled: boolean;
963
- queue?: Promise<ExuluQueueConfig>;
964
- };
965
- interface ExuluProviderParams {
966
- id: string;
967
- name: string;
968
- type: "agent";
969
- description: string;
970
- config?: ExuluProviderConfig | undefined;
971
- queue?: ExuluQueueConfig;
972
- maxContextLength?: number;
973
- authenticationInformation?: string;
822
+ /**
823
+ * OAuth 2.0 configuration for an {@link ExuluTool}. When a tool is constructed
824
+ * with an `oauth` property, Exulu wraps its `execute` so it only runs when a
825
+ * valid access token exists for the calling (providerKey, userId) pair — where
826
+ * providerKey defaults to the tool's id but can be shared across tools by
827
+ * setting the "provider" field below. When no valid token exists the tool
828
+ * short-circuits and returns an authorization URL the agent can show the user;
829
+ * the generic /oauth/callback route completes the flow and persists the tokens.
830
+ *
831
+ * Only the standard authorization-code grant is supported. All values are
832
+ * declared in code (source them from env vars or however you like) — none of
833
+ * them are exposed as admin-configurable tool config.
834
+ */
835
+ interface ExuluOauthConfig {
836
+ authType: "oauth";
837
+ /**
838
+ * Identifier for the OAuth provider (e.g., "google", "jira", "github").
839
+ * Tools sharing the same provider share tokens under (provider, userId) —
840
+ * one consent screen per provider per user instead of per tool. When
841
+ * omitted, defaults to the tool's `id`, preserving per-tool behavior for
842
+ * tools that don't opt in.
843
+ */
974
844
  provider: string;
975
- workflows?: ExuluProviderWorkflowConfig;
976
- capabilities?: {
977
- text: boolean;
978
- images: imageTypes$1[];
979
- files: fileTypes$1[];
980
- audio: audioTypes$1[];
981
- video: videoTypes$1[];
982
- };
845
+ /** The provider's authorization endpoint, e.g. https://app.hubspot.com/oauth/authorize */
846
+ authorizationUrl: string;
847
+ /** The provider's token endpoint, e.g. https://api.hubapi.com/oauth/v1/token */
848
+ tokenUrl: string;
849
+ clientId: string;
850
+ /** Never leaves the server: used only in the server-side token exchange. */
851
+ clientSecret: string;
852
+ /** Scopes to request; joined with spaces in the authorization URL. */
853
+ scopes: readonly string[];
854
+ /** PKCE (S256). Defaults to true; set false for providers that reject PKCE. */
855
+ pkce?: boolean;
856
+ /**
857
+ * Extra query params appended to the authorization URL, e.g.
858
+ * `{ access_type: "offline", prompt: "consent" }` to make Google return a
859
+ * refresh token.
860
+ */
861
+ extraAuthParams?: Record<string, string>;
983
862
  }
984
- declare class ExuluProvider {
985
- id: string;
863
+ interface CredentialField {
986
864
  name: string;
865
+ label: string;
866
+ type: "text" | "password";
867
+ placeholder?: string;
868
+ help?: string;
869
+ }
870
+ interface ExuluUserCredentialsConfig {
871
+ authType: "user_credentials";
987
872
  provider: string;
988
- description: string;
989
- slug: string;
990
- type: "agent";
991
- streaming: boolean;
992
- authenticationInformation?: string;
993
- maxContextLength?: number;
994
- workflows?: ExuluProviderWorkflowConfig;
995
- queue?: ExuluQueueConfig;
996
- config?: ExuluProviderConfig | undefined;
997
- model?: {
998
- create: ({ apiKey, user, role, project, agent }: {
999
- apiKey?: string | undefined;
1000
- user?: number;
1001
- role?: string;
1002
- project?: string;
1003
- agent?: string;
1004
- }) => LanguageModel;
1005
- };
1006
- capabilities: {
1007
- text: boolean;
1008
- images: string[];
1009
- files: string[];
1010
- audio: string[];
1011
- video: string[];
1012
- };
1013
- constructor({ id, name, description, config, capabilities, type, maxContextLength, provider, queue, authenticationInformation, workflows, }: ExuluProviderParams);
1014
- get providerName(): string;
1015
- get modelName(): string;
1016
- tool: (instance: string, providers: ExuluProvider[], contexts: ExuluContext[]) => Promise<ExuluTool | null>;
1017
- generateSync: ({ prompt, req, user, session, inputMessages, approvedTools, currentTools, currentSkills, allExuluTools, statistics, toolConfigs, providerapikey, languageModel, contexts, exuluConfig, agent, instructions, maxStepCount, onTokenUsage, contextWindow, disabledTools, }: {
1018
- prompt?: string;
1019
- user?: User;
1020
- maxStepCount?: number;
1021
- req?: Request;
1022
- session?: string;
1023
- agent?: ExuluAgent;
1024
- approvedTools?: string[];
1025
- inputMessages?: UIMessage[];
1026
- currentTools?: ExuluTool[];
1027
- currentSkills?: ExuluSkill[];
1028
- allExuluTools?: ExuluTool[];
1029
- statistics?: ExuluStatisticParams;
1030
- toolConfigs?: ExuluAgentToolConfig[];
1031
- providerapikey?: string | undefined;
1032
- languageModel: LanguageModel;
1033
- contexts?: ExuluContext[] | undefined;
1034
- exuluConfig?: ExuluConfig;
1035
- instructions?: string;
1036
- onTokenUsage?: (usage: {
1037
- inputTokens: number;
1038
- outputTokens: number;
1039
- }) => Promise<void> | void;
1040
- contextWindow?: number;
1041
- disabledTools?: string[];
1042
- }) => Promise<any>;
1043
- /**
1044
- * Convert file parts in messages to OpenAI Responses API compatible format.
1045
- * The OpenAI Responses API doesn't support inline file parts with type 'file'.
1046
- * This function converts:
1047
- * - Document files (PDF, DOCX, etc.) -> text parts with extracted content using officeparser
1048
- * - Image files -> image parts (which ARE supported by Responses API)
1049
- */
1050
- private processFilePartsInMessages;
1051
- generateStream: ({ user, session, agent, message, previousMessages, currentTools, currentSkills, approvedTools, allExuluTools, toolConfigs, providerapikey, languageModel, contexts, exuluConfig, instructions, req, maxStepCount, contextWindow, disabledTools, }: {
1052
- user?: User;
1053
- session?: string;
1054
- agent?: ExuluAgent;
1055
- maxStepCount?: number;
1056
- message?: UIMessage;
1057
- previousMessages?: UIMessage[];
1058
- currentTools?: ExuluTool[];
1059
- currentSkills?: ExuluSkill[];
1060
- approvedTools?: string[];
1061
- allExuluTools?: ExuluTool[];
1062
- toolConfigs?: ExuluAgentToolConfig[];
1063
- providerapikey?: string | undefined;
1064
- languageModel: LanguageModel;
1065
- contexts?: ExuluContext[] | undefined;
1066
- exuluConfig?: ExuluConfig;
1067
- instructions?: string;
1068
- req?: Request;
1069
- contextWindow?: number;
1070
- disabledTools?: string[];
1071
- }) => Promise<{
1072
- stream: ReturnType<typeof streamText>;
1073
- originalMessages: UIMessage[];
1074
- previousMessages: UIMessage[];
1075
- }>;
873
+ fields: CredentialField[];
874
+ validate?: (values: Record<string, string>) => Promise<void>;
1076
875
  }
1077
-
1078
- interface TestCase {
1079
- id: string;
1080
- name: string;
1081
- description?: string;
1082
- inputs: UIMessage[];
1083
- expected_output: string;
1084
- expected_tools?: string[];
1085
- expected_knowledge_sources?: string[];
1086
- expected_agent_tools?: string[];
1087
- createdAt: string;
1088
- updatedAt: string;
876
+ type ExuluAuthConfig = ExuluOauthConfig | ExuluUserCredentialsConfig;
877
+ interface ExuluCredentialsToolContext {
878
+ userId: string;
879
+ provider: string;
880
+ credentials: Record<string, string>;
1089
881
  }
882
+ /** The oauth context injected into an oauth-enabled tool's execute inputs. */
883
+ type ExuluOauthToolContext = {
884
+ accessToken: string;
885
+ /** null when the provider did not report an expiry. */
886
+ expiresAt: Date | null;
887
+ /** Space-joined scopes the token was granted, when reported by the provider. */
888
+ scopes: string | null;
889
+ };
1090
890
 
1091
- interface ExuluEvalParams {
891
+ declare const PUBLIC_TOOL_TYPES: readonly ["function", "web_search", "skill", "context"];
892
+ type PublicToolType = (typeof PUBLIC_TOOL_TYPES)[number];
893
+ type ToolType = PublicToolType | "agent" | "context";
894
+ declare class ExuluTool {
1092
895
  id: string;
1093
896
  name: string;
1094
897
  description: string;
1095
- llm: boolean;
1096
- execute: (params: {
1097
- agent: ExuluAgent;
1098
- provider: ExuluProvider;
1099
- messages: UIMessage[];
1100
- testCase: TestCase;
1101
- config?: Record<string, any>;
1102
- }) => Promise<number>;
1103
- config?: {
898
+ category: string;
899
+ inputSchema?: z.ZodType;
900
+ type: ToolType;
901
+ tool: Tool;
902
+ needsApproval: boolean;
903
+ authentication?: ExuluAuthConfig;
904
+ config: {
1104
905
  name: string;
1105
906
  description: string;
907
+ type: "boolean" | "string" | "number" | "variable" | "json";
908
+ default?: string | boolean | number | object;
1106
909
  }[];
1107
- queue: Promise<ExuluQueueConfig>;
1108
- }
1109
- declare class ExuluEval {
1110
- id: string;
1111
- name: string;
1112
- description: string;
1113
- llm: boolean;
1114
- private execute;
1115
- config?: {
910
+ constructor({ id, name, description, category, inputSchema, type, execute, config, needsApproval, authentication, }: {
911
+ id: string;
1116
912
  name: string;
1117
913
  description: string;
1118
- }[];
1119
- queue?: Promise<ExuluQueueConfig>;
1120
- constructor({ id, name, description, execute, config, queue, llm }: ExuluEvalParams);
1121
- run(agent: ExuluAgent, provider: ExuluProvider, testCase: TestCase, messages: UIMessage[], config?: Record<string, any>): Promise<number>;
914
+ category?: string;
915
+ inputSchema?: z.ZodType;
916
+ type: PublicToolType;
917
+ config: {
918
+ name: string;
919
+ description: string;
920
+ type: "boolean" | "string" | "number" | "variable" | "json";
921
+ default?: string | boolean | number | object;
922
+ }[];
923
+ needsApproval?: boolean;
924
+ authentication?: ExuluAuthConfig;
925
+ execute: (inputs: any, options?: any) => Promise<{
926
+ result?: string;
927
+ job?: string;
928
+ items?: Item[];
929
+ }> | AsyncGenerator<{
930
+ result?: string;
931
+ job?: string;
932
+ items?: Item[];
933
+ }>;
934
+ });
935
+ /**
936
+ * Framework-only factory for tools whose `type` is managed by Exulu itself —
937
+ * "agent" (agent-as-tool instrumentation) and "context" (internal retrieval
938
+ * tools). NOT part of the public API: package consumers must use
939
+ * `new ExuluTool(...)`, which only accepts a {@link PublicToolType}. Building
940
+ * the tool as a "function" and then setting the managed type bypasses the
941
+ * constructor guard without weakening it for consumers.
942
+ */
943
+ static internal(params: Omit<ConstructorParameters<typeof ExuluTool>[0], "type"> & {
944
+ type: ToolType;
945
+ }): ExuluTool;
946
+ execute: ({ agent: agentId, config, user, inputs, project, items, }: {
947
+ agent: string;
948
+ config: ExuluConfig;
949
+ user?: User;
950
+ inputs: any;
951
+ project?: string;
952
+ items?: string[];
953
+ }) => Promise<any>;
954
+ }
955
+
956
+ type S3Target = {
957
+ s3region: string;
958
+ s3key: string;
959
+ s3secret: string;
960
+ s3Bucket: string;
961
+ s3endpoint?: string;
962
+ s3prefix?: string;
963
+ };
964
+ type AuditConfig = {
965
+ enabled: boolean;
966
+ s3?: S3Target;
967
+ retentionDays: number;
968
+ manageLifecycle?: boolean;
969
+ spoolDir?: string;
970
+ flush?: {
971
+ maxRecords?: number;
972
+ maxIntervalMs?: number;
973
+ };
974
+ payload?: {
975
+ maxBytes?: number;
976
+ captureOutput?: boolean;
977
+ redactKeys?: string[];
978
+ };
979
+ failureMode?: "open" | "closed";
980
+ sources?: {
981
+ toolCalls?: {
982
+ enabled?: boolean;
983
+ include?: string[];
984
+ exclude?: string[];
985
+ };
986
+ };
987
+ };
988
+
989
+ type AuditClient = {
990
+ ip?: string;
991
+ userAgent?: string;
992
+ referer?: string;
993
+ origin?: string;
994
+ forwardedFor?: string;
995
+ };
996
+ type AuditEvent = {
997
+ v: 1;
998
+ ts: string;
999
+ type: string;
1000
+ actor: {
1001
+ kind?: "user" | "agent" | "system";
1002
+ userId?: string;
1003
+ email?: string;
1004
+ roleId?: string;
1005
+ projectId?: string;
1006
+ };
1007
+ context?: {
1008
+ sessionId?: string;
1009
+ agentId?: string;
1010
+ agentName?: string;
1011
+ toolCallId?: string;
1012
+ [k: string]: unknown;
1013
+ };
1014
+ target?: {
1015
+ kind?: string;
1016
+ id?: string;
1017
+ name?: string;
1018
+ [k: string]: unknown;
1019
+ };
1020
+ credential?: {
1021
+ provider: string;
1022
+ authType: "oauth" | "user_credentials";
1023
+ account?: string;
1024
+ scopes?: string[];
1025
+ expiresAt?: string | null;
1026
+ };
1027
+ status: "ok" | "error" | "denied" | "auth_required";
1028
+ error?: {
1029
+ name?: string;
1030
+ message: string;
1031
+ };
1032
+ data?: Record<string, unknown>;
1033
+ durationMs?: number;
1034
+ truncated?: Record<string, boolean>;
1035
+ client?: AuditClient;
1036
+ };
1037
+ type AuditToolCallInput = {
1038
+ durationMs: number;
1039
+ agent?: {
1040
+ id?: string;
1041
+ name?: string;
1042
+ slug?: string;
1043
+ };
1044
+ tool: {
1045
+ id: string;
1046
+ name: string;
1047
+ category?: string;
1048
+ authentication?: ExuluAuthConfig;
1049
+ };
1050
+ builtin: boolean;
1051
+ user?: {
1052
+ id?: unknown;
1053
+ email?: string;
1054
+ role?: {
1055
+ id?: unknown;
1056
+ };
1057
+ };
1058
+ projectId?: string;
1059
+ sessionID?: string;
1060
+ toolCallId?: string;
1061
+ input: unknown;
1062
+ output: unknown;
1063
+ status: "ok" | "error" | "auth_required";
1064
+ error?: unknown;
1065
+ client?: AuditClient;
1066
+ };
1067
+
1068
+ interface AuditLogger {
1069
+ enabled: boolean;
1070
+ failClosed: boolean;
1071
+ isBuiltin: (id: string) => boolean;
1072
+ shouldAuditTool: (id: string) => boolean;
1073
+ record: (event: AuditEvent) => void;
1074
+ recordToolCall: (ctx: AuditToolCallInput) => Promise<void>;
1075
+ flush: () => Promise<void>;
1076
+ close: () => Promise<void>;
1122
1077
  }
1123
1078
 
1124
1079
  type ExuluConfig = {
@@ -1155,6 +1110,12 @@ type ExuluConfig = {
1155
1110
  privacy?: {
1156
1111
  systemPromptPersonalization?: boolean;
1157
1112
  };
1113
+ /**
1114
+ * Audit logging. When enabled, structured audit events (starting with one
1115
+ * per tool call) are batched to S3 as NDJSON with configurable retention.
1116
+ * Off by default. See docs/superpowers/specs/2026-07-28-tool-call-audit-layer-design.md.
1117
+ */
1118
+ audit?: AuditConfig;
1158
1119
  /**
1159
1120
  * When true, ExuluApp.create() throws if any required system binary
1160
1121
  * (pandoc / soffice / pdftoppm — needed by built-in skills like docx) is
@@ -1165,7 +1126,6 @@ type ExuluConfig = {
1165
1126
  requireSystemDependencies?: boolean;
1166
1127
  };
1167
1128
  declare class ExuluApp {
1168
- private _providers;
1169
1129
  private _agents;
1170
1130
  private _config?;
1171
1131
  private _evals;
@@ -1173,14 +1133,15 @@ declare class ExuluApp {
1173
1133
  private _contexts?;
1174
1134
  private _tools;
1175
1135
  private _expressApp;
1136
+ private _audit?;
1176
1137
  constructor();
1177
- create: ({ contexts, providers, config, agents, tools, evals, }: {
1138
+ create: ({ contexts, config, agents, tools, evals, queues }: {
1178
1139
  contexts?: Record<string, ExuluContext>;
1179
1140
  config: ExuluConfig;
1180
1141
  agents?: ExuluAgent[];
1181
- providers?: ExuluProvider[];
1182
1142
  evals?: ExuluEval[];
1183
1143
  tools?: ExuluTool[];
1144
+ queues?: Promise<ExuluQueueConfig>[];
1184
1145
  }) => Promise<ExuluApp>;
1185
1146
  express: {
1186
1147
  init: () => Promise<Express>;
@@ -1194,6 +1155,7 @@ declare class ExuluApp {
1194
1155
  database: boolean;
1195
1156
  };
1196
1157
  }): Promise<ExuluAgent | undefined>;
1158
+ queues(): ExuluQueueConfig[];
1197
1159
  agents(include?: {
1198
1160
  source: {
1199
1161
  code: boolean;
@@ -1201,9 +1163,8 @@ declare class ExuluApp {
1201
1163
  };
1202
1164
  }): Promise<ExuluAgent[]>;
1203
1165
  context(id: string): ExuluContext | undefined;
1204
- provider(id: string): ExuluProvider | undefined;
1205
1166
  get contexts(): ExuluContext[];
1206
- get providers(): ExuluProvider[];
1167
+ get audit(): AuditLogger;
1207
1168
  embeddings: {
1208
1169
  generate: {
1209
1170
  one: ({ context: contextId, item: itemId }: {
@@ -2577,35 +2538,6 @@ declare const ExuluDefaultTools: {
2577
2538
  };
2578
2539
  };
2579
2540
  };
2580
- declare const ExuluDefaultProviders: {
2581
- anthropic: {
2582
- opus4: ExuluProvider;
2583
- sonnet4: ExuluProvider;
2584
- sonnet45: ExuluProvider;
2585
- };
2586
- cerebras: {
2587
- gptOss120b: ExuluProvider;
2588
- llama38b: ExuluProvider;
2589
- llama3370b: ExuluProvider;
2590
- };
2591
- google: {
2592
- vertexGemini25Flash: ExuluProvider;
2593
- vertexGemini25Pro: ExuluProvider;
2594
- vertexGemini3Pro: ExuluProvider;
2595
- vertexLlamaScout4: ExuluProvider;
2596
- };
2597
- openai: {
2598
- gpt5Mini: ExuluProvider;
2599
- gpt5: ExuluProvider;
2600
- gpt5pro: ExuluProvider;
2601
- gpt5Codex: ExuluProvider;
2602
- gpt5Nano: ExuluProvider;
2603
- gpt41: ExuluProvider;
2604
- gpt41Mini: ExuluProvider;
2605
- gpt4o: ExuluProvider;
2606
- gpt4oMini: ExuluProvider;
2607
- };
2608
- };
2609
2541
  declare const ExuluVariables: {
2610
2542
  get: (name: string) => Promise<string>;
2611
2543
  };
@@ -2668,4 +2600,4 @@ declare const ExuluPython: {
2668
2600
  instructions: typeof getPythonSetupInstructions;
2669
2601
  };
2670
2602
 
2671
- export { type ChunkerOperation, type ChunkerResponse, type CredentialField, CredentialInvalidError, type JOB_STATUS as EXULU_JOB_STATUS, JOB_STATUS_ENUM as EXULU_JOB_STATUS_ENUM, type STATISTICS_TYPE as EXULU_STATISTICS_TYPE, STATISTICS_TYPE_ENUM as EXULU_STATISTICS_TYPE_ENUM, type ExuluAgent, ExuluApp, type ExuluAuthConfig, ExuluAuthentication, ExuluChunkers, ExuluContext, type ExuluContextEmbedder, type ExuluCredentialsToolContext, ExuluDatabase, ExuluDefaultProviders, ExuluDefaultTools, ExuluDocumentProcessor, ExuluEval, type Item as ExuluItem, ExuluJobs, type ExuluOauthConfig, type ExuluOauthToolContext, ExuluOtel, ExuluProvider, ExuluPython, queues as ExuluQueues, ExuluReadApi, ExuluReranker, ExuluTool, type ExuluUserCredentialsConfig, ExuluVariables, type VectorSearchChunkResult, defaultChunker, enableLiteLLMClientMode, postgresClient };
2603
+ export { type AuditConfig, type AuditEvent, type AuditLogger, type ChunkerOperation, type ChunkerResponse, type CredentialField, CredentialInvalidError, type JOB_STATUS as EXULU_JOB_STATUS, JOB_STATUS_ENUM as EXULU_JOB_STATUS_ENUM, type STATISTICS_TYPE as EXULU_STATISTICS_TYPE, STATISTICS_TYPE_ENUM as EXULU_STATISTICS_TYPE_ENUM, type ExuluAgent, ExuluApp, type ExuluAuthConfig, ExuluAuthentication, ExuluChunkers, ExuluContext, type ExuluContextEmbedder, type ExuluCredentialsToolContext, ExuluDatabase, ExuluDefaultTools, ExuluDocumentProcessor, ExuluEval, type Item as ExuluItem, ExuluJobs, type ExuluOauthConfig, type ExuluOauthToolContext, ExuluOtel, ExuluPython, queues as ExuluQueues, ExuluReadApi, ExuluReranker, ExuluTool, type ExuluUserCredentialsConfig, ExuluVariables, type VectorSearchChunkResult, defaultChunker, enableLiteLLMClientMode, postgresClient };