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

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 (59) hide show
  1. package/dist/api/job.api.service.d.ts +16 -7
  2. package/dist/api/job.api.service.js +21 -5
  3. package/dist/api/postprocessor.api.service.d.ts +61 -1
  4. package/dist/api/postprocessor.api.service.js +35 -0
  5. package/dist/api/preprocessor.api.service.d.ts +61 -1
  6. package/dist/api/preprocessor.api.service.js +35 -0
  7. package/dist/api-exports.d.ts +26 -6
  8. package/dist/api-exports.js +42 -29
  9. package/dist/commands/chat.js +32 -5
  10. package/dist/commands/compile.js +16 -2
  11. package/dist/commands/dev.js +23 -2
  12. package/dist/commands/push.js +5 -3
  13. package/dist/commands/test.js +18 -2
  14. package/dist/common/job.instance.d.ts +3 -0
  15. package/dist/common/job.instance.js +8 -0
  16. package/dist/config/constants.d.ts +6 -5
  17. package/dist/config/constants.js +12 -10
  18. package/dist/interfaces/chat.d.ts +30 -1
  19. package/dist/interfaces/jobs.d.ts +21 -0
  20. package/dist/types/skill.d.ts +75 -56
  21. package/dist/types/skill.js +53 -59
  22. package/dist/utils/bundling.d.ts +13 -4
  23. package/dist/utils/bundling.js +83 -26
  24. package/dist/utils/compile.js +27 -6
  25. package/dist/utils/dev-api.d.ts +42 -2
  26. package/dist/utils/dev-api.js +177 -4
  27. package/dist/utils/dev-server.d.ts +1 -1
  28. package/dist/utils/dev-server.js +4 -4
  29. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  30. package/dist/utils/dynamic-job-bundler.js +143 -0
  31. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  32. package/dist/utils/pre-bundle-jobs.js +176 -0
  33. package/dist/utils/sandbox-storage.d.ts +48 -0
  34. package/dist/utils/sandbox-storage.js +114 -0
  35. package/dist/utils/sandbox.d.ts +2 -2
  36. package/dist/utils/sandbox.js +23 -7
  37. package/package.json +1 -1
  38. package/template/lua.skill.yaml +47 -0
  39. package/template/package-lock.json +10505 -0
  40. package/template/package.json +2 -1
  41. package/template/src/index.ts +65 -3
  42. package/template/src/tools/CreateInlineJob.ts +42 -0
  43. package/API_REFERENCE.md +0 -1408
  44. package/CHANGELOG.md +0 -236
  45. package/CLI_REFERENCE.md +0 -908
  46. package/GETTING_STARTED.md +0 -1040
  47. package/INSTANCE_TYPES.md +0 -1158
  48. package/README.md +0 -865
  49. package/TEMPLATE_GUIDE.md +0 -1398
  50. package/USER_DATA_INSTANCE.md +0 -621
  51. package/template/AGENT_CONFIGURATION.md +0 -251
  52. package/template/COMPLEX_JOB_EXAMPLES.md +0 -795
  53. package/template/DYNAMIC_JOB_CREATION.md +0 -371
  54. package/template/TOOL_EXAMPLES.md +0 -655
  55. package/template/WEBHOOKS_JOBS_QUICKSTART.md +0 -318
  56. package/template/WEBHOOK_JOB_EXAMPLES.md +0 -817
  57. package/template/src/index-agent-example.ts +0 -201
  58. package/template/src/postprocessors/ResponseFormatter.ts +0 -151
  59. package/template/src/preprocessors/MessageFilter.ts +0 -91
@@ -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
  }
@@ -2,8 +2,15 @@
2
2
  * Bundling Utilities
3
3
  * Handles esbuild bundling of tools and main index
4
4
  */
5
+ import { Plugin } from "esbuild";
5
6
  import { Project } from "ts-morph";
6
7
  import { ToolInfo } from '../interfaces/compile.js';
8
+ /**
9
+ * esbuild plugin to inject sandbox globals instead of requiring lua-cli
10
+ * This removes require("lua-cli") statements and injects the global API objects
11
+ * that are available in the sandbox (Products, User, Data, Baskets, Orders, Webhooks, Jobs)
12
+ */
13
+ export declare const sandboxGlobalsPlugin: Plugin;
7
14
  /**
8
15
  * Bundles a tool's TypeScript code into a standalone JavaScript file.
9
16
  * Uses esbuild to:
@@ -16,7 +23,7 @@ import { ToolInfo } from '../interfaces/compile.js';
16
23
  * @param tool - The tool to bundle
17
24
  * @param distDir - The distribution directory for output
18
25
  */
19
- export declare function bundleTool(tool: ToolInfo, distDir: string): Promise<void>;
26
+ export declare function bundleTool(tool: ToolInfo, distDir: string, modifiedSource?: string): Promise<void>;
20
27
  /**
21
28
  * Bundles the main index.ts file into a standalone JavaScript file.
22
29
  * This creates the entry point for the skill.
@@ -57,10 +64,12 @@ export declare function bundlePostProcessor(postprocessor: any, indexFile: any,
57
64
  * Extracts execute code and input schema from a tool.
58
65
  * This function:
59
66
  * 1. Reads the bundled tool code
60
- * 2. Extracts the execute function
61
- * 3. Converts Zod schema to JSON Schema format
67
+ * 2. Detects and bundles any Jobs.create() calls within execute
68
+ * 3. Extracts the execute function
69
+ * 4. Converts Zod schema to JSON Schema format
62
70
  *
63
71
  * @param tool - The tool to extract metadata from (mutated with executeCode and inputSchema)
64
72
  * @param project - The ts-morph Project instance for AST analysis
73
+ * @param distDir - Distribution directory for bundling nested jobs
65
74
  */
66
- export declare function extractExecuteCode(tool: ToolInfo, project: Project): Promise<void>;
75
+ export declare function extractExecuteCode(tool: ToolInfo, project: Project, distDir?: string): Promise<void>;
@@ -8,13 +8,34 @@ import { build } from "esbuild";
8
8
  import { Project, Node } from "ts-morph";
9
9
  import { writeProgress } from "./cli.js";
10
10
  import { COMPILE_DIRS, COMPILE_FILES, ESBUILD_TOOL_CONFIG, ESBUILD_INDEX_CONFIG, DEFAULT_INPUT_SCHEMA, } from '../config/compile.constants.js';
11
- import { wrapToolForVM, createExecuteFunction, evaluateZodSchemaToJsonSchema, } from './compile.js';
11
+ import { wrapToolForVM, createExecuteFunction, evaluateZodSchemaToJsonSchema } from './compile.js';
12
+ /**
13
+ * Helper function to remove lua-cli and api-exports imports from source code.
14
+ * Used when bundling via stdin or temp files where the plugin can't process them.
15
+ */
16
+ function stripLuaCliImports(sourceCode) {
17
+ return sourceCode
18
+ // Remove api-exports imports
19
+ .replace(/import\s+{([^}]+)}\s+from\s+["'][^"']*api-exports["'];?/g, '// api-exports imports removed - using sandbox globals')
20
+ // Remove lua-cli imports
21
+ .replace(/import\s+{([^}]+)}\s+from\s+["']lua-cli["'];?/g, '// lua-cli imports removed - using sandbox globals')
22
+ // Remove lua-cli/skill imports (but keep LuaTool, etc. for type checking in temp files)
23
+ .replace(/import\s+{([^}]+)}\s+from\s+["']lua-cli\/skill["'];?/g, (match, imports) => {
24
+ // Keep only LuaTool, LuaWebhook, LuaJob types for temp files
25
+ const typeImports = imports.split(',')
26
+ .map((imp) => imp.trim())
27
+ .filter((imp) => /^(LuaTool|LuaWebhook|LuaJob|LuaPreProcessor|LuaPostProcessor)$/.test(imp));
28
+ return typeImports.length > 0
29
+ ? `// lua-cli/skill imports removed - using sandbox globals (types kept for compilation)`
30
+ : '// lua-cli/skill imports removed - using sandbox globals';
31
+ });
32
+ }
12
33
  /**
13
34
  * esbuild plugin to inject sandbox globals instead of requiring lua-cli
14
35
  * This removes require("lua-cli") statements and injects the global API objects
15
36
  * that are available in the sandbox (Products, User, Data, Baskets, Orders, Webhooks, Jobs)
16
37
  */
17
- const sandboxGlobalsPlugin = {
38
+ export const sandboxGlobalsPlugin = {
18
39
  name: 'sandbox-globals',
19
40
  setup(build) {
20
41
  // Only process user files, not node_modules
@@ -24,12 +45,18 @@ const sandboxGlobalsPlugin = {
24
45
  return null;
25
46
  }
26
47
  const contents = await fs.promises.readFile(args.path, 'utf8');
27
- // Only transform files that import from lua-cli
28
- if (!contents.includes('lua-cli')) {
48
+ // Only transform files that import from lua-cli or api-exports
49
+ if (!contents.includes('lua-cli') && !contents.includes('api-exports')) {
29
50
  return null;
30
51
  }
31
52
  // Replace lua-cli imports with global references
32
53
  let transformedContents = contents;
54
+ // Replace named imports from api-exports (e.g., ../../../dist/api-exports)
55
+ // Match: import { Jobs, Products, etc. } from "../../../dist/api-exports"
56
+ transformedContents = transformedContents.replace(/import\s+{([^}]+)}\s+from\s+["'][^"']*api-exports["'];?/g, (match, imports) => {
57
+ // Just remove the import, globals will be available in sandbox
58
+ return '// api-exports imports removed - using sandbox globals';
59
+ });
33
60
  // Replace named imports from lua-cli
34
61
  // Match: import { Products, User, Data, etc. } from "lua-cli"
35
62
  transformedContents = transformedContents.replace(/import\s+{([^}]+)}\s+from\s+["']lua-cli["'];?/g, (match, imports) => {
@@ -83,12 +110,13 @@ const sandboxGlobalsPlugin = {
83
110
  * @param tool - The tool to bundle
84
111
  * @param distDir - The distribution directory for output
85
112
  */
86
- export async function bundleTool(tool, distDir) {
113
+ export async function bundleTool(tool, distDir, modifiedSource) {
87
114
  writeProgress(`📦 Bundling ${tool.className}...`);
88
115
  try {
89
116
  const outputPath = path.join(distDir, COMPILE_DIRS.TOOLS, `${tool.className}.js`);
90
117
  let entryPoint = tool.filePath;
91
118
  let tempFile = null;
119
+ // Note: modifiedSource is handled via stdin below, no temp file needed
92
120
  // Check if tool is inline (in index.ts or src/index.ts)
93
121
  const isInlineInIndex = tool.filePath.endsWith('index.ts') || tool.filePath.endsWith('index.tsx');
94
122
  if (isInlineInIndex) {
@@ -121,12 +149,30 @@ export async function bundleTool(tool, distDir) {
121
149
  entryPoint = tempFile;
122
150
  }
123
151
  }
124
- await build({
125
- ...ESBUILD_TOOL_CONFIG,
126
- entryPoints: [entryPoint],
127
- outfile: outputPath,
128
- plugins: [sandboxGlobalsPlugin],
129
- });
152
+ // Use stdin for modified source to preserve import resolution
153
+ if (modifiedSource && !isInlineInIndex) {
154
+ // Remove api-exports and lua-cli imports (they're available in sandbox)
155
+ const transformedSource = stripLuaCliImports(modifiedSource);
156
+ await build({
157
+ ...ESBUILD_TOOL_CONFIG,
158
+ stdin: {
159
+ contents: transformedSource,
160
+ resolveDir: path.dirname(tool.filePath),
161
+ sourcefile: tool.filePath,
162
+ loader: 'ts',
163
+ },
164
+ outfile: outputPath,
165
+ plugins: [sandboxGlobalsPlugin],
166
+ });
167
+ }
168
+ else {
169
+ await build({
170
+ ...ESBUILD_TOOL_CONFIG,
171
+ entryPoints: [entryPoint],
172
+ outfile: outputPath,
173
+ plugins: [sandboxGlobalsPlugin],
174
+ });
175
+ }
130
176
  // Wrap the bundled code for VM execution environment
131
177
  await wrapToolForVM(outputPath, tool);
132
178
  // Clean up temp file if created
@@ -303,10 +349,10 @@ async function bundleAndCompressWebhookCode(executeFunction, webhookName, distDi
303
349
  const tempOutput = path.join(tempDir, `${webhookName}-webhook.js`);
304
350
  try {
305
351
  // Write execute function as a module export
306
- const moduleCode = `
352
+ const moduleCode = stripLuaCliImports(`
307
353
  // Webhook execute function for ${webhookName}
308
354
  export default ${executeFunction};
309
- `;
355
+ `);
310
356
  fs.writeFileSync(tempFile, moduleCode);
311
357
  // Bundle with esbuild
312
358
  await build({
@@ -323,8 +369,7 @@ export default ${executeFunction};
323
369
  // Read bundled code
324
370
  let bundledCode = fs.readFileSync(tempOutput, 'utf8');
325
371
  // Wrap for webhook VM execution (similar to tools)
326
- const wrappedCode = `(async (input) => {
327
- const { query, headers, body } = input;
372
+ const wrappedCode = `(async (query, headers, body) => {
328
373
 
329
374
  // Execute the bundled webhook code
330
375
  ${bundledCode}
@@ -332,8 +377,8 @@ export default ${executeFunction};
332
377
  // Get the execute function from exports
333
378
  const executeFunction = module.exports.default || module.exports;
334
379
 
335
- // Execute with proper input structure
336
- return await executeFunction({ query, headers, body });
380
+ // Execute with three separate parameters (not an object)
381
+ return await executeFunction(query, headers, body);
337
382
  })`;
338
383
  // Compress the wrapped code
339
384
  const compressed = compressCode(wrappedCode);
@@ -472,10 +517,10 @@ async function bundleAndCompressJobCode(executeFunction, jobName, distDir) {
472
517
  const tempOutput = path.join(tempDir, `${jobName}-job.js`);
473
518
  try {
474
519
  // Write execute function as a module export
475
- const moduleCode = `
520
+ const moduleCode = stripLuaCliImports(`
476
521
  // Job execute function for ${jobName}
477
522
  export default ${executeFunction};
478
- `;
523
+ `);
479
524
  fs.writeFileSync(tempFile, moduleCode);
480
525
  // Bundle with esbuild
481
526
  await build({
@@ -597,7 +642,11 @@ export async function bundlePreProcessor(preprocessor, indexFile, distDir, proje
597
642
  compressedCode = await bundleAndCompressProcessorCode(executeFunction, preprocessor.name, 'pre', distDir);
598
643
  }
599
644
  return {
600
- ...preprocessor,
645
+ name: preprocessor.name,
646
+ version: preprocessor.version,
647
+ description: preprocessor.description,
648
+ context: preprocessor.context,
649
+ async: preprocessor.async === true ? true : false, // Explicitly set boolean
601
650
  executeFunction,
602
651
  code: compressedCode
603
652
  };
@@ -675,7 +724,11 @@ export async function bundlePostProcessor(postprocessor, indexFile, distDir, pro
675
724
  compressedCode = await bundleAndCompressProcessorCode(executeFunction, postprocessor.name, 'post', distDir);
676
725
  }
677
726
  return {
678
- ...postprocessor,
727
+ name: postprocessor.name,
728
+ version: postprocessor.version,
729
+ description: postprocessor.description,
730
+ context: postprocessor.context,
731
+ async: postprocessor.async === true ? true : false, // Explicitly set boolean
679
732
  executeFunction,
680
733
  code: compressedCode
681
734
  };
@@ -699,10 +752,10 @@ async function bundleAndCompressProcessorCode(executeFunction, processorName, ty
699
752
  try {
700
753
  // Processor execute functions receive: (user, message, [response], channel)
701
754
  const paramList = type === 'pre' ? 'user, message, channel' : 'user, message, response, channel';
702
- const moduleCode = `
755
+ const moduleCode = stripLuaCliImports(`
703
756
  // ${type === 'pre' ? 'Pre' : 'Post'}Processor execute function for ${processorName}
704
757
  export default ${executeFunction};
705
- `;
758
+ `);
706
759
  fs.writeFileSync(tempFile, moduleCode);
707
760
  await build({
708
761
  entryPoints: [tempFile],
@@ -751,13 +804,15 @@ export default ${executeFunction};
751
804
  * Extracts execute code and input schema from a tool.
752
805
  * This function:
753
806
  * 1. Reads the bundled tool code
754
- * 2. Extracts the execute function
755
- * 3. Converts Zod schema to JSON Schema format
807
+ * 2. Detects and bundles any Jobs.create() calls within execute
808
+ * 3. Extracts the execute function
809
+ * 4. Converts Zod schema to JSON Schema format
756
810
  *
757
811
  * @param tool - The tool to extract metadata from (mutated with executeCode and inputSchema)
758
812
  * @param project - The ts-morph Project instance for AST analysis
813
+ * @param distDir - Distribution directory for bundling nested jobs
759
814
  */
760
- export async function extractExecuteCode(tool, project) {
815
+ export async function extractExecuteCode(tool, project, distDir) {
761
816
  try {
762
817
  const toolSourceFile = project.getSourceFile(tool.filePath);
763
818
  if (!toolSourceFile) {
@@ -793,6 +848,8 @@ export async function extractExecuteCode(tool, project) {
793
848
  }
794
849
  // Extract execute code from bundled file
795
850
  tool.executeCode = extractExecuteCodeFromBundledFile(tool);
851
+ // NOTE: Dynamic job bundling moved to source-level processing
852
+ // Attempting to extract from minified bundled code is too fragile
796
853
  // Extract and convert input schema
797
854
  tool.inputSchema = await extractInputSchema(classDecl, tool);
798
855
  }
@@ -423,6 +423,7 @@ export function extractPreProcessorsMetadata(indexFile) {
423
423
  let version = '';
424
424
  let description = '';
425
425
  let context = '';
426
+ let asyncMode = false;
426
427
  configObj.getProperties().forEach((prop) => {
427
428
  if (Node.isPropertyAssignment(prop)) {
428
429
  const propName = prop.getName();
@@ -439,6 +440,11 @@ export function extractPreProcessorsMetadata(indexFile) {
439
440
  else if (propName === 'context' && value) {
440
441
  context = value.getText().replace(/['"]/g, '');
441
442
  }
443
+ else if (propName === 'async' && value) {
444
+ // Properly extract boolean value by checking node kind
445
+ const nodeKind = value.getKind();
446
+ asyncMode = nodeKind === 110; // TrueKeyword = 110, FalseKeyword = 95
447
+ }
442
448
  }
443
449
  });
444
450
  if (name) {
@@ -446,7 +452,8 @@ export function extractPreProcessorsMetadata(indexFile) {
446
452
  name,
447
453
  version: version || '1.0.0',
448
454
  description,
449
- context
455
+ context,
456
+ async: asyncMode
450
457
  });
451
458
  }
452
459
  }
@@ -472,6 +479,7 @@ export function extractPostProcessorsMetadata(indexFile) {
472
479
  let version = '';
473
480
  let description = '';
474
481
  let context = '';
482
+ let asyncMode = false;
475
483
  configObj.getProperties().forEach((prop) => {
476
484
  if (Node.isPropertyAssignment(prop)) {
477
485
  const propName = prop.getName();
@@ -488,6 +496,11 @@ export function extractPostProcessorsMetadata(indexFile) {
488
496
  else if (propName === 'context' && value) {
489
497
  context = value.getText().replace(/['"]/g, '');
490
498
  }
499
+ else if (propName === 'async' && value) {
500
+ // Properly extract boolean value by checking node kind
501
+ const nodeKind = value.getKind();
502
+ asyncMode = nodeKind === 110; // TrueKeyword = 110, FalseKeyword = 95
503
+ }
491
504
  }
492
505
  });
493
506
  if (name) {
@@ -495,7 +508,8 @@ export function extractPostProcessorsMetadata(indexFile) {
495
508
  name,
496
509
  version: version || '1.0.0',
497
510
  description,
498
- context
511
+ context,
512
+ async: asyncMode
499
513
  });
500
514
  }
501
515
  }
@@ -674,10 +688,12 @@ function extractValueFromNode(node) {
674
688
  if (Node.isNumericLiteral(node)) {
675
689
  return node.getLiteralValue();
676
690
  }
677
- // Boolean literal
678
- if (node.getKind() === 110 || node.getKind() === 95) { // TrueKeyword or FalseKeyword
679
- return node.getText() === 'true';
680
- }
691
+ // Boolean literal (TrueKeyword = 110, FalseKeyword = 95)
692
+ const nodeKind = node.getKind();
693
+ if (nodeKind === 110)
694
+ return true; // TrueKeyword
695
+ if (nodeKind === 95)
696
+ return false; // FalseKeyword
681
697
  // New expression (for tools: [new ToolClass()])
682
698
  // Extract just the class name for compatibility with buildSkillsArray
683
699
  if (Node.isNewExpression(node)) {
@@ -699,6 +715,11 @@ function extractValueFromNode(node) {
699
715
  // Template literal or other complex expressions
700
716
  // For persona, context, etc. that might be multiline
701
717
  const text = node.getText();
718
+ // Handle boolean strings (fallback if node kind check didn't catch it)
719
+ if (text === 'true')
720
+ return true;
721
+ if (text === 'false')
722
+ return false;
702
723
  // If it starts with a quote, remove quotes
703
724
  if ((text.startsWith('"') && text.endsWith('"')) ||
704
725
  (text.startsWith("'") && text.endsWith("'")) ||
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { DevVersionResponse, UpdateDevVersionResponse, SandboxIdsMap } from '../interfaces/dev.js';
6
6
  /**
7
- * Sends a chat message to the API with skill override for sandbox testing.
7
+ * Sends a chat message to the API with skill and processor overrides for sandbox testing.
8
8
  *
9
9
  * @param apiKey - User's API key
10
10
  * @param agentId - Agent ID
@@ -13,9 +13,10 @@ import { DevVersionResponse, UpdateDevVersionResponse, SandboxIdsMap } from '../
13
13
  * @param message - Message to send
14
14
  * @param persona - Optional persona override
15
15
  * @param deployData - Deploy data containing all skills
16
+ * @param config - Optional config for processor overrides
16
17
  * @returns The chat response text or null if failed
17
18
  */
18
- export declare function sendChatMessage(apiKey: string, agentId: string, skillId: string, sandboxId: string, message: string, persona: string | undefined, deployData: any): Promise<string | null>;
19
+ export declare function sendChatMessage(apiKey: string, agentId: string, skillId: string, sandboxId: string, message: string, persona: string | undefined, deployData: any, config?: any): Promise<string | null>;
19
20
  /**
20
21
  * Updates an existing sandbox version.
21
22
  *
@@ -59,3 +60,42 @@ export declare function pushSingleSkillToSandbox(apiKey: string, agentId: string
59
60
  * @returns Map of skill names to their sandbox IDs
60
61
  */
61
62
  export declare function pushSkillsToSandbox(apiKey: string, agentId: string, deployData: any, isInitial?: boolean): Promise<SandboxIdsMap>;
63
+ /**
64
+ * Pushes a single preprocessor to the sandbox.
65
+ * Attempts to update existing sandbox version, creates new one if update fails.
66
+ *
67
+ * @param apiKey - User's API key
68
+ * @param agentId - Agent ID
69
+ * @param preprocessorId - PreProcessor ID
70
+ * @param preprocessorData - PreProcessor data to push
71
+ * @param isInitial - Whether this is the initial push (affects logging)
72
+ * @returns True if successful, false otherwise
73
+ */
74
+ export declare function pushSinglePreProcessorToSandbox(apiKey: string, agentId: string, preprocessorId: string, preprocessorData: any, isInitial?: boolean): Promise<boolean>;
75
+ /**
76
+ * Pushes a single postprocessor to the sandbox.
77
+ * Attempts to update existing sandbox version, creates new one if update fails.
78
+ *
79
+ * @param apiKey - User's API key
80
+ * @param agentId - Agent ID
81
+ * @param postprocessorId - PostProcessor ID
82
+ * @param postprocessorData - PostProcessor data to push
83
+ * @param isInitial - Whether this is the initial push (affects logging)
84
+ * @returns True if successful, false otherwise
85
+ */
86
+ export declare function pushSinglePostProcessorToSandbox(apiKey: string, agentId: string, postprocessorId: string, postprocessorData: any, isInitial?: boolean): Promise<boolean>;
87
+ /**
88
+ * Pushes preprocessors and postprocessors to sandbox.
89
+ *
90
+ * @param apiKey - User's API key
91
+ * @param agentId - Agent ID
92
+ * @param config - Configuration with preprocessors and postprocessors
93
+ * @param bundledPreProcessors - Bundled preprocessor data from compilation
94
+ * @param bundledPostProcessors - Bundled postprocessor data from compilation
95
+ * @param isInitial - Whether this is the initial push
96
+ * @returns Object with counts of pushed processors
97
+ */
98
+ export declare function pushProcessorsToSandbox(apiKey: string, agentId: string, config: any, bundledPreProcessors: any[], bundledPostProcessors: any[], isInitial?: boolean): Promise<{
99
+ preprocessors: number;
100
+ postprocessors: number;
101
+ }>;