lua-cli 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (66) hide show
  1. package/dist/api/chat.api.service.d.ts +8 -0
  2. package/dist/api/chat.api.service.js +55 -0
  3. package/dist/api/job.api.service.d.ts +16 -7
  4. package/dist/api/job.api.service.js +21 -5
  5. package/dist/api/postprocessor.api.service.d.ts +61 -1
  6. package/dist/api/postprocessor.api.service.js +35 -0
  7. package/dist/api/preprocessor.api.service.d.ts +61 -1
  8. package/dist/api/preprocessor.api.service.js +35 -0
  9. package/dist/api-exports.d.ts +27 -7
  10. package/dist/api-exports.js +48 -30
  11. package/dist/cli/command-definitions.js +13 -6
  12. package/dist/commands/chat.js +71 -39
  13. package/dist/commands/compile.js +16 -2
  14. package/dist/commands/dev.js +23 -2
  15. package/dist/commands/push.d.ts +3 -2
  16. package/dist/commands/push.js +536 -6
  17. package/dist/commands/test.js +18 -2
  18. package/dist/common/job.instance.d.ts +3 -0
  19. package/dist/common/job.instance.js +8 -0
  20. package/dist/config/constants.d.ts +6 -5
  21. package/dist/config/constants.js +12 -10
  22. package/dist/interfaces/chat.d.ts +30 -1
  23. package/dist/interfaces/jobs.d.ts +21 -0
  24. package/dist/services/auth.d.ts +8 -2
  25. package/dist/services/auth.js +35 -3
  26. package/dist/types/skill.d.ts +75 -56
  27. package/dist/types/skill.js +53 -59
  28. package/dist/utils/bundling.d.ts +13 -4
  29. package/dist/utils/bundling.js +83 -26
  30. package/dist/utils/compile.js +27 -6
  31. package/dist/utils/dev-api.d.ts +42 -2
  32. package/dist/utils/dev-api.js +177 -4
  33. package/dist/utils/dev-server.d.ts +1 -1
  34. package/dist/utils/dev-server.js +4 -4
  35. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  36. package/dist/utils/dynamic-job-bundler.js +143 -0
  37. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  38. package/dist/utils/pre-bundle-jobs.js +176 -0
  39. package/dist/utils/sandbox-storage.d.ts +48 -0
  40. package/dist/utils/sandbox-storage.js +114 -0
  41. package/dist/utils/sandbox.d.ts +2 -2
  42. package/dist/utils/sandbox.js +23 -8
  43. package/package.json +1 -1
  44. package/template/env.example +5 -0
  45. package/template/lua.skill.yaml +47 -0
  46. package/template/package-lock.json +10505 -0
  47. package/template/package.json +2 -1
  48. package/template/src/index.ts +65 -3
  49. package/template/src/tools/CreateInlineJob.ts +42 -0
  50. package/API_REFERENCE.md +0 -1408
  51. package/CHANGELOG.md +0 -236
  52. package/CLI_REFERENCE.md +0 -908
  53. package/GETTING_STARTED.md +0 -1040
  54. package/INSTANCE_TYPES.md +0 -1158
  55. package/README.md +0 -865
  56. package/TEMPLATE_GUIDE.md +0 -1398
  57. package/USER_DATA_INSTANCE.md +0 -621
  58. package/template/AGENT_CONFIGURATION.md +0 -251
  59. package/template/COMPLEX_JOB_EXAMPLES.md +0 -795
  60. package/template/DYNAMIC_JOB_CREATION.md +0 -371
  61. package/template/TOOL_EXAMPLES.md +0 -655
  62. package/template/WEBHOOKS_JOBS_QUICKSTART.md +0 -318
  63. package/template/WEBHOOK_JOB_EXAMPLES.md +0 -817
  64. package/template/src/index-agent-example.ts +0 -201
  65. package/template/src/postprocessors/ResponseFormatter.ts +0 -151
  66. package/template/src/preprocessors/MessageFilter.ts +0 -91
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Base URLs for the API, Auth, and Chat - Production
3
3
  */
4
- export declare const BASE_URLS: {
5
- readonly API: "http://localhost:3022";
6
- readonly AUTH: "https://auth.heylua.ai";
7
- readonly CHAT: "http://localhost:3001";
8
- };
9
4
  /**
10
5
  * Base URLs for the API, Auth, and Chat - Development
11
6
  */
7
+ export declare const BASE_URLS: {
8
+ readonly API: "https://api.heylua.ai";
9
+ readonly AUTH: "https://auth.heylua.ai";
10
+ readonly CHAT: "https://api.heylua.ai";
11
+ readonly WEBHOOK: "https://webhook.heylua.ai";
12
+ };
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * Base URLs for the API, Auth, and Chat - Production
3
3
  */
4
- export const BASE_URLS = {
5
- API: 'http://localhost:3022',
6
- AUTH: 'https://auth.heylua.ai',
7
- CHAT: 'http://localhost:3001',
8
- };
9
- /**
10
- * Base URLs for the API, Auth, and Chat - Development
11
- */
12
4
  // export const BASE_URLS = {
13
- // API: 'https://api.heylua.ai',
5
+ // API: 'http://localhost:3022',
14
6
  // AUTH: 'https://auth.heylua.ai',
15
- // CHAT: 'https://api.heylua.ai',
7
+ // CHAT: 'http://localhost:3001',
8
+ // WEBHOOK: 'https://webhook.heylua.ai',
16
9
  // } as const;
10
+ /**
11
+ * Base URLs for the API, Auth, and Chat - Development
12
+ */
13
+ export const BASE_URLS = {
14
+ API: 'https://api.heylua.ai',
15
+ AUTH: 'https://auth.heylua.ai',
16
+ CHAT: 'https://api.heylua.ai',
17
+ WEBHOOK: 'https://webhook.heylua.ai',
18
+ };
@@ -6,10 +6,21 @@
6
6
  * Chat message structure.
7
7
  * Currently only supports text messages.
8
8
  */
9
- export interface ChatMessage {
9
+ export type ChatMessage = TextMessage | ImageMessage | FileMessage;
10
+ export interface TextMessage {
10
11
  type: 'text';
11
12
  text: string;
12
13
  }
14
+ export interface ImageMessage {
15
+ type: 'image';
16
+ image: string;
17
+ mimeType: string;
18
+ }
19
+ export interface FileMessage {
20
+ type: 'file';
21
+ data: string;
22
+ mimeType: string;
23
+ }
13
24
  /**
14
25
  * Skill override for testing specific skill versions.
15
26
  * Used in dev mode to override production skills with sandbox versions.
@@ -18,6 +29,22 @@ export interface SkillOverride {
18
29
  skillId: string;
19
30
  sandboxId: string;
20
31
  }
32
+ /**
33
+ * PreProcessor override for sandbox testing.
34
+ * Maps production preprocessor ID to sandbox version ID.
35
+ */
36
+ export interface PreProcessorOverride {
37
+ preprocessorId: string;
38
+ sandboxId: string;
39
+ }
40
+ /**
41
+ * PostProcessor override for sandbox testing.
42
+ * Maps production postprocessor ID to sandbox version ID.
43
+ */
44
+ export interface PostProcessorOverride {
45
+ postprocessorId: string;
46
+ sandboxId: string;
47
+ }
21
48
  /**
22
49
  * Chat request payload.
23
50
  * Sent to the chat API to start or continue a conversation.
@@ -26,6 +53,8 @@ export interface ChatRequest {
26
53
  messages: ChatMessage[];
27
54
  navigate: boolean;
28
55
  skillOverride: SkillOverride[];
56
+ preprocessorOverride?: PreProcessorOverride[];
57
+ postprocessorOverride?: PostProcessorOverride[];
29
58
  personaOverride?: string;
30
59
  runtimeContext?: string;
31
60
  }
@@ -13,6 +13,27 @@ export interface CreateJobDTO {
13
13
  timeout?: number;
14
14
  retry?: JobRetryConfig;
15
15
  metadata?: Record<string, any>;
16
+ dynamic?: boolean;
17
+ /**
18
+ * Optional initial version data.
19
+ * If provided, creates the first version automatically.
20
+ */
21
+ version?: {
22
+ version: string;
23
+ description?: string;
24
+ context?: string;
25
+ code: string;
26
+ executeFunction: string;
27
+ timeout?: number;
28
+ retry?: JobRetryConfig;
29
+ metadata?: Record<string, any>;
30
+ };
31
+ /**
32
+ * Auto-publish and activate the job after creation.
33
+ * If true, the job will be immediately active and running.
34
+ * Default: false
35
+ */
36
+ activate?: boolean;
16
37
  }
17
38
  /**
18
39
  * DTO for pushing a job version
@@ -13,9 +13,15 @@ import { UserData } from "../interfaces/admin.js";
13
13
  */
14
14
  export declare function saveApiKey(apiKey: string): Promise<void>;
15
15
  /**
16
- * Loads API key from secure system keychain.
16
+ * Loads API key from multiple sources in priority order:
17
+ * 1. Secure system keychain (macOS Keychain, Windows Credential Vault, Linux libsecret)
18
+ * 2. LUA_API_KEY environment variable
19
+ * 3. LUA_API_KEY from .env file
17
20
  *
18
- * @returns Promise resolving to API key or null if not found
21
+ * This fallback mechanism allows the CLI to work in CI/CD environments where
22
+ * keychain access isn't available.
23
+ *
24
+ * @returns Promise resolving to API key or null if not found in any source
19
25
  */
20
26
  export declare function loadApiKey(): Promise<string | null>;
21
27
  /**
@@ -22,12 +22,44 @@ export async function saveApiKey(apiKey) {
22
22
  await keytar.setPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT, apiKey);
23
23
  }
24
24
  /**
25
- * Loads API key from secure system keychain.
25
+ * Loads API key from multiple sources in priority order:
26
+ * 1. Secure system keychain (macOS Keychain, Windows Credential Vault, Linux libsecret)
27
+ * 2. LUA_API_KEY environment variable
28
+ * 3. LUA_API_KEY from .env file
26
29
  *
27
- * @returns Promise resolving to API key or null if not found
30
+ * This fallback mechanism allows the CLI to work in CI/CD environments where
31
+ * keychain access isn't available.
32
+ *
33
+ * @returns Promise resolving to API key or null if not found in any source
28
34
  */
29
35
  export async function loadApiKey() {
30
- return keytar.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
36
+ // Priority 1: Check secure system keychain
37
+ const keychainKey = await keytar.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
38
+ if (keychainKey) {
39
+ return keychainKey;
40
+ }
41
+ // Priority 2: Check environment variable
42
+ if (process.env.LUA_API_KEY) {
43
+ return process.env.LUA_API_KEY;
44
+ }
45
+ // Priority 3: Check .env file
46
+ try {
47
+ const fs = await import('fs');
48
+ const path = await import('path');
49
+ const envPath = path.join(process.cwd(), '.env');
50
+ if (fs.existsSync(envPath)) {
51
+ const envContent = fs.readFileSync(envPath, 'utf8');
52
+ const match = envContent.match(/^LUA_API_KEY=(.+)$/m);
53
+ if (match && match[1]) {
54
+ // Remove quotes if present
55
+ return match[1].trim().replace(/^["']|["']$/g, '');
56
+ }
57
+ }
58
+ }
59
+ catch (error) {
60
+ // Silently fail if .env file can't be read
61
+ }
62
+ return null;
31
63
  }
32
64
  /**
33
65
  * Deletes API key from secure system keychain.
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { ZodType } from "zod";
6
6
  import UserDataInstance from "../common/user.instance.js";
7
+ import { JobInstance } from "../common/job.instance.js";
7
8
  /**
8
9
  * Safe environment variable access function.
9
10
  * Gets injected at runtime with skill-specific environment variables.
@@ -171,8 +172,11 @@ export interface LuaJobConfig {
171
172
  context: string;
172
173
  /** Schedule configuration - cron, once, or interval */
173
174
  schedule: JobSchedule;
174
- /** Function that executes the job logic - receives job instance as parameter */
175
- execute: (job?: any) => Promise<any>;
175
+ /**
176
+ * Function that executes the job logic.
177
+ * Receives metadata as parameter for accessing job configuration.
178
+ */
179
+ execute: (job: JobInstance) => Promise<any>;
176
180
  /** Optional timeout in seconds (default: 300) */
177
181
  timeout?: number;
178
182
  /** Optional retry configuration */
@@ -180,7 +184,11 @@ export interface LuaJobConfig {
180
184
  maxAttempts: number;
181
185
  backoffSeconds?: number;
182
186
  };
183
- /** Optional metadata for the job */
187
+ /**
188
+ * Optional metadata for the job.
189
+ * Can store any custom data (tags, config, context, etc.)
190
+ * Sent to server and accessible during execution.
191
+ */
184
192
  metadata?: Record<string, any>;
185
193
  }
186
194
  /**
@@ -309,19 +317,6 @@ export declare class LuaJob {
309
317
  * Gets the job metadata.
310
318
  */
311
319
  getMetadata(): Record<string, any> | undefined;
312
- /**
313
- * Executes the job.
314
- * This is called by the scheduler at the appropriate time.
315
- *
316
- * @returns Promise resolving to job execution result
317
- *
318
- * @example
319
- * ```typescript
320
- * const result = await job.execute();
321
- * console.log('Job completed:', result);
322
- * ```
323
- */
324
- execute(): Promise<any>;
325
320
  }
326
321
  /**
327
322
  * Lua Webhook configuration.
@@ -343,11 +338,7 @@ export interface LuaWebhookConfig {
343
338
  /** Optional Zod schema for body validation */
344
339
  bodySchema?: ZodType;
345
340
  /** Function that executes the webhook logic */
346
- execute: (input: {
347
- query?: any;
348
- headers?: any;
349
- body?: any;
350
- }) => Promise<any>;
341
+ execute: (query?: any, headers?: any, body?: any) => Promise<any>;
351
342
  }
352
343
  /**
353
344
  * Lua Webhook class.
@@ -380,19 +371,19 @@ export interface LuaWebhookConfig {
380
371
  * email: z.string().email(),
381
372
  * name: z.string()
382
373
  * }),
383
- * execute: async ({ query, headers, body }) => {
374
+ * execute: async (query, headers, body) => {
384
375
  * // Process the webhook...
385
376
  * console.log('New user:', body.email);
386
377
  * return { success: true, userId: body.userId };
387
378
  * }
388
379
  * });
389
380
  *
390
- * // Execute the webhook with validated input
391
- * const result = await webhook.execute({
392
- * query: { source: 'mobile' },
393
- * headers: { 'x-api-key': 'secret-key' },
394
- * body: { userId: '123', email: 'user@example.com', name: 'John' }
395
- * });
381
+ * // Execute the webhook with validated inputs
382
+ * const result = await webhook.execute(
383
+ * { source: 'mobile' },
384
+ * { 'x-api-key': 'secret-key' },
385
+ * { userId: '123', email: 'user@example.com', name: 'John' }
386
+ * );
396
387
  * ```
397
388
  */
398
389
  export declare class LuaWebhook {
@@ -439,27 +430,22 @@ export declare class LuaWebhook {
439
430
  * Validates query parameters, headers, and body against their respective schemas
440
431
  * before executing the webhook function.
441
432
  *
442
- * @param input - Input object containing query, headers, and/or body
443
- * @param input.query - Query parameters object
444
- * @param input.headers - Headers object
445
- * @param input.body - Request body
433
+ * @param query - Query parameters object
434
+ * @param headers - Headers object
435
+ * @param body - Request body
446
436
  * @returns Promise resolving to webhook execution result
447
437
  * @throws Error if validation fails for any input
448
438
  *
449
439
  * @example
450
440
  * ```typescript
451
- * const result = await webhook.execute({
452
- * query: { limit: '10' },
453
- * headers: { 'x-api-key': 'secret' },
454
- * body: { data: 'value' }
455
- * });
441
+ * const result = await webhook.execute(
442
+ * { limit: '10' },
443
+ * { 'x-api-key': 'secret' },
444
+ * { data: 'value' }
445
+ * );
456
446
  * ```
457
447
  */
458
- execute(input: {
459
- query?: Record<string, any>;
460
- headers?: Record<string, any>;
461
- body?: any;
462
- }): Promise<any>;
448
+ execute(query?: Record<string, any>, headers?: Record<string, any>, body?: any): Promise<any>;
463
449
  }
464
450
  /**
465
451
  * PreProcessor configuration.
@@ -473,26 +459,45 @@ export interface PreProcessorConfig {
473
459
  description: string;
474
460
  /** Detailed context for what this preprocessor does */
475
461
  context: string;
476
- /** Function that processes the message before sending to agent */
477
- execute: (user: UserDataInstance, message: string, channel: string) => Promise<string>;
462
+ /**
463
+ * Async flag - indicates if processor should run in background on server:
464
+ * - true: Run asynchronously (non-blocking, for slow operations like API calls)
465
+ * - false: Run synchronously (blocking, for fast operations like text filtering)
466
+ * Default: false (synchronous)
467
+ */
468
+ async?: boolean;
469
+ /**
470
+ * Function that processes messages before sending to agent.
471
+ * MUST return ChatMessage[] - array of text, image, or file messages.
472
+ */
473
+ execute: (user: UserDataInstance, messages: import("../interfaces/chat.js").ChatMessage[], channel: string) => Promise<import("../interfaces/chat.js").ChatMessage[]>;
478
474
  }
479
475
  /**
480
476
  * PreProcessor class.
481
477
  * Processes user messages before they reach the agent.
478
+ * Can handle rich content (text, images, files).
482
479
  *
483
480
  * @example
484
481
  * ```typescript
485
- * const languageDetector = new PreProcessor({
486
- * name: 'language-detector',
482
+ * const contentFilter = new PreProcessor({
483
+ * name: 'content-filter',
487
484
  * version: '1.0.0',
488
- * description: 'Detects and translates messages',
489
- * context: 'Detects language and translates to English if needed',
490
- * execute: async (user, message, channel) => {
491
- * const language = await detectLanguage(message);
492
- * if (language !== 'en') {
493
- * return await translate(message, 'en');
494
- * }
495
- * return message;
485
+ * description: 'Filters and processes message content',
486
+ * context: 'Filters spam, validates images, and adds context',
487
+ * execute: async (user, messages, channel) => {
488
+ * // Process each message
489
+ * return messages.map(msg => {
490
+ * if (msg.type === 'text') {
491
+ * // Filter spam from text
492
+ * const filtered = msg.text.replace(/spam/gi, '[filtered]');
493
+ * return { type: 'text', text: filtered };
494
+ * }
495
+ * if (msg.type === 'image') {
496
+ * // Could validate image, add watermark, etc.
497
+ * return msg;
498
+ * }
499
+ * return msg;
500
+ * });
496
501
  * }
497
502
  * });
498
503
  * ```
@@ -502,13 +507,15 @@ export declare class PreProcessor {
502
507
  private readonly version;
503
508
  private readonly description;
504
509
  private readonly context;
510
+ private readonly asyncMode;
505
511
  private readonly executeFunction;
506
512
  constructor(config: PreProcessorConfig);
507
513
  getName(): string;
508
514
  getVersion(): string;
509
515
  getDescription(): string;
510
516
  getContext(): string;
511
- execute(user: UserDataInstance, message: string, channel: string): Promise<string>;
517
+ getAsync(): boolean;
518
+ execute(user: UserDataInstance, messages: import("../interfaces/chat.js").ChatMessage[], channel: string): Promise<import("../interfaces/chat.js").ChatMessage[]>;
512
519
  }
513
520
  /**
514
521
  * PostProcessor configuration.
@@ -522,7 +529,17 @@ export interface PostProcessorConfig {
522
529
  description: string;
523
530
  /** Detailed context for what this postprocessor does */
524
531
  context: string;
525
- /** Function that processes the agent's response before sending to user */
532
+ /**
533
+ * Async flag - indicates if processor should run in background on server:
534
+ * - true: Run asynchronously (non-blocking, for slow operations like API calls, translations)
535
+ * - false: Run synchronously (blocking, for fast operations like text formatting)
536
+ * Default: false (synchronous)
537
+ */
538
+ async?: boolean;
539
+ /**
540
+ * Function that processes the agent's response before sending to user.
541
+ * MUST return string - the formatted response text.
542
+ */
526
543
  execute: (user: UserDataInstance, message: string, response: string, channel: string) => Promise<string>;
527
544
  }
528
545
  /**
@@ -547,12 +564,14 @@ export declare class PostProcessor {
547
564
  private readonly version;
548
565
  private readonly description;
549
566
  private readonly context;
567
+ private readonly asyncMode;
550
568
  private readonly executeFunction;
551
569
  constructor(config: PostProcessorConfig);
552
570
  getName(): string;
553
571
  getVersion(): string;
554
572
  getDescription(): string;
555
573
  getContext(): string;
574
+ getAsync(): boolean;
556
575
  execute(user: UserDataInstance, message: string, response: string, channel: string): Promise<string>;
557
576
  }
558
577
  /**
@@ -283,21 +283,6 @@ export class LuaJob {
283
283
  getMetadata() {
284
284
  return this.metadata;
285
285
  }
286
- /**
287
- * Executes the job.
288
- * This is called by the scheduler at the appropriate time.
289
- *
290
- * @returns Promise resolving to job execution result
291
- *
292
- * @example
293
- * ```typescript
294
- * const result = await job.execute();
295
- * console.log('Job completed:', result);
296
- * ```
297
- */
298
- async execute() {
299
- return this.executeFunction();
300
- }
301
286
  }
302
287
  /**
303
288
  * Lua Webhook class.
@@ -330,19 +315,19 @@ export class LuaJob {
330
315
  * email: z.string().email(),
331
316
  * name: z.string()
332
317
  * }),
333
- * execute: async ({ query, headers, body }) => {
318
+ * execute: async (query, headers, body) => {
334
319
  * // Process the webhook...
335
320
  * console.log('New user:', body.email);
336
321
  * return { success: true, userId: body.userId };
337
322
  * }
338
323
  * });
339
324
  *
340
- * // Execute the webhook with validated input
341
- * const result = await webhook.execute({
342
- * query: { source: 'mobile' },
343
- * headers: { 'x-api-key': 'secret-key' },
344
- * body: { userId: '123', email: 'user@example.com', name: 'John' }
345
- * });
325
+ * // Execute the webhook with validated inputs
326
+ * const result = await webhook.execute(
327
+ * { source: 'mobile' },
328
+ * { 'x-api-key': 'secret-key' },
329
+ * { userId: '123', email: 'user@example.com', name: 'John' }
330
+ * );
346
331
  * ```
347
332
  */
348
333
  export class LuaWebhook {
@@ -398,81 +383,82 @@ export class LuaWebhook {
398
383
  * Validates query parameters, headers, and body against their respective schemas
399
384
  * before executing the webhook function.
400
385
  *
401
- * @param input - Input object containing query, headers, and/or body
402
- * @param input.query - Query parameters object
403
- * @param input.headers - Headers object
404
- * @param input.body - Request body
386
+ * @param query - Query parameters object
387
+ * @param headers - Headers object
388
+ * @param body - Request body
405
389
  * @returns Promise resolving to webhook execution result
406
390
  * @throws Error if validation fails for any input
407
391
  *
408
392
  * @example
409
393
  * ```typescript
410
- * const result = await webhook.execute({
411
- * query: { limit: '10' },
412
- * headers: { 'x-api-key': 'secret' },
413
- * body: { data: 'value' }
414
- * });
394
+ * const result = await webhook.execute(
395
+ * { limit: '10' },
396
+ * { 'x-api-key': 'secret' },
397
+ * { data: 'value' }
398
+ * );
415
399
  * ```
416
400
  */
417
- async execute(input) {
418
- const validatedInput = {};
401
+ async execute(query, headers, body) {
402
+ let validatedQuery = query;
403
+ let validatedHeaders = headers;
404
+ let validatedBody = body;
419
405
  // Validate query parameters if schema is provided
420
406
  if (this.querySchema) {
421
407
  try {
422
- validatedInput.query = this.querySchema.parse(input.query || {});
408
+ validatedQuery = this.querySchema.parse(query || {});
423
409
  }
424
410
  catch (error) {
425
411
  throw new Error(`Query parameter validation failed: ${error}`);
426
412
  }
427
413
  }
428
- else {
429
- validatedInput.query = input.query;
430
- }
431
414
  // Validate headers if schema is provided
432
415
  if (this.headerSchema) {
433
416
  try {
434
- validatedInput.headers = this.headerSchema.parse(input.headers || {});
417
+ validatedHeaders = this.headerSchema.parse(headers || {});
435
418
  }
436
419
  catch (error) {
437
420
  throw new Error(`Header validation failed: ${error}`);
438
421
  }
439
422
  }
440
- else {
441
- validatedInput.headers = input.headers;
442
- }
443
423
  // Validate body if schema is provided
444
424
  if (this.bodySchema) {
445
425
  try {
446
- validatedInput.body = this.bodySchema.parse(input.body);
426
+ validatedBody = this.bodySchema.parse(body);
447
427
  }
448
428
  catch (error) {
449
429
  throw new Error(`Body validation failed: ${error}`);
450
430
  }
451
431
  }
452
- else {
453
- validatedInput.body = input.body;
454
- }
455
- // Execute the webhook function with validated input
456
- return this.executeFunction(validatedInput);
432
+ // Execute the webhook function with validated inputs as separate parameters
433
+ return this.executeFunction(validatedQuery, validatedHeaders, validatedBody);
457
434
  }
458
435
  }
459
436
  /**
460
437
  * PreProcessor class.
461
438
  * Processes user messages before they reach the agent.
439
+ * Can handle rich content (text, images, files).
462
440
  *
463
441
  * @example
464
442
  * ```typescript
465
- * const languageDetector = new PreProcessor({
466
- * name: 'language-detector',
443
+ * const contentFilter = new PreProcessor({
444
+ * name: 'content-filter',
467
445
  * version: '1.0.0',
468
- * description: 'Detects and translates messages',
469
- * context: 'Detects language and translates to English if needed',
470
- * execute: async (user, message, channel) => {
471
- * const language = await detectLanguage(message);
472
- * if (language !== 'en') {
473
- * return await translate(message, 'en');
474
- * }
475
- * return message;
446
+ * description: 'Filters and processes message content',
447
+ * context: 'Filters spam, validates images, and adds context',
448
+ * execute: async (user, messages, channel) => {
449
+ * // Process each message
450
+ * return messages.map(msg => {
451
+ * if (msg.type === 'text') {
452
+ * // Filter spam from text
453
+ * const filtered = msg.text.replace(/spam/gi, '[filtered]');
454
+ * return { type: 'text', text: filtered };
455
+ * }
456
+ * if (msg.type === 'image') {
457
+ * // Could validate image, add watermark, etc.
458
+ * return msg;
459
+ * }
460
+ * return msg;
461
+ * });
476
462
  * }
477
463
  * });
478
464
  * ```
@@ -483,6 +469,7 @@ export class PreProcessor {
483
469
  this.version = config.version || '1.0.0';
484
470
  this.description = config.description;
485
471
  this.context = config.context;
472
+ this.asyncMode = config.async ?? false; // Default to synchronous
486
473
  this.executeFunction = config.execute;
487
474
  }
488
475
  getName() {
@@ -497,8 +484,11 @@ export class PreProcessor {
497
484
  getContext() {
498
485
  return this.context;
499
486
  }
500
- async execute(user, message, channel) {
501
- return this.executeFunction(user, message, channel);
487
+ getAsync() {
488
+ return this.asyncMode;
489
+ }
490
+ async execute(user, messages, channel) {
491
+ return this.executeFunction(user, messages, channel);
502
492
  }
503
493
  }
504
494
  /**
@@ -524,6 +514,7 @@ export class PostProcessor {
524
514
  this.version = config.version || '1.0.0';
525
515
  this.description = config.description;
526
516
  this.context = config.context;
517
+ this.asyncMode = config.async ?? false; // Default to synchronous
527
518
  this.executeFunction = config.execute;
528
519
  }
529
520
  getName() {
@@ -538,6 +529,9 @@ export class PostProcessor {
538
529
  getContext() {
539
530
  return this.context;
540
531
  }
532
+ getAsync() {
533
+ return this.asyncMode;
534
+ }
541
535
  async execute(user, message, response, channel) {
542
536
  return this.executeFunction(user, message, response, channel);
543
537
  }