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

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 (61) 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/cli/command-definitions.js +13 -6
  10. package/dist/commands/chat.js +32 -5
  11. package/dist/commands/compile.js +16 -2
  12. package/dist/commands/dev.js +23 -2
  13. package/dist/commands/push.d.ts +6 -2
  14. package/dist/commands/push.js +412 -6
  15. package/dist/commands/test.js +18 -2
  16. package/dist/common/job.instance.d.ts +3 -0
  17. package/dist/common/job.instance.js +8 -0
  18. package/dist/config/constants.d.ts +6 -5
  19. package/dist/config/constants.js +12 -10
  20. package/dist/interfaces/chat.d.ts +30 -1
  21. package/dist/interfaces/jobs.d.ts +21 -0
  22. package/dist/types/skill.d.ts +75 -56
  23. package/dist/types/skill.js +53 -59
  24. package/dist/utils/bundling.d.ts +13 -4
  25. package/dist/utils/bundling.js +83 -26
  26. package/dist/utils/compile.js +27 -6
  27. package/dist/utils/dev-api.d.ts +42 -2
  28. package/dist/utils/dev-api.js +177 -4
  29. package/dist/utils/dev-server.d.ts +1 -1
  30. package/dist/utils/dev-server.js +4 -4
  31. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  32. package/dist/utils/dynamic-job-bundler.js +143 -0
  33. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  34. package/dist/utils/pre-bundle-jobs.js +176 -0
  35. package/dist/utils/sandbox-storage.d.ts +48 -0
  36. package/dist/utils/sandbox-storage.js +114 -0
  37. package/dist/utils/sandbox.d.ts +2 -2
  38. package/dist/utils/sandbox.js +23 -7
  39. package/package.json +1 -1
  40. package/template/lua.skill.yaml +47 -0
  41. package/template/package-lock.json +10505 -0
  42. package/template/package.json +2 -1
  43. package/template/src/index.ts +65 -3
  44. package/template/src/tools/CreateInlineJob.ts +42 -0
  45. package/API_REFERENCE.md +0 -1408
  46. package/CHANGELOG.md +0 -236
  47. package/CLI_REFERENCE.md +0 -908
  48. package/GETTING_STARTED.md +0 -1040
  49. package/INSTANCE_TYPES.md +0 -1158
  50. package/README.md +0 -865
  51. package/TEMPLATE_GUIDE.md +0 -1398
  52. package/USER_DATA_INSTANCE.md +0 -621
  53. package/template/AGENT_CONFIGURATION.md +0 -251
  54. package/template/COMPLEX_JOB_EXAMPLES.md +0 -795
  55. package/template/DYNAMIC_JOB_CREATION.md +0 -371
  56. package/template/TOOL_EXAMPLES.md +0 -655
  57. package/template/WEBHOOKS_JOBS_QUICKSTART.md +0 -318
  58. package/template/WEBHOOK_JOB_EXAMPLES.md +0 -817
  59. package/template/src/index-agent-example.ts +0 -201
  60. package/template/src/postprocessors/ResponseFormatter.ts +0 -151
  61. package/template/src/preprocessors/MessageFilter.ts +0 -91
@@ -69,8 +69,8 @@ export interface JobExecutionResponse {
69
69
  * Handles all job-related API calls
70
70
  */
71
71
  export default class JobApi extends HttpClient {
72
- private apiKey;
73
- private agentId;
72
+ apiKey: string;
73
+ agentId: string;
74
74
  /**
75
75
  * Creates an instance of JobApi
76
76
  * @param baseUrl - The base URL for the API
@@ -92,19 +92,28 @@ export default class JobApi extends HttpClient {
92
92
  */
93
93
  getJob(jobId: string): Promise<JobInstance>;
94
94
  /**
95
- * Creates a new job for the agent
96
- * @param jobData - The job data including name, description, and optional context
95
+ * Creates a new job for the agent.
96
+ * Optionally creates initial version and activates the job in one call.
97
+ *
98
+ * @param jobData - The job data including name, description, schedule, and optional version
99
+ * @param jobData.version - If provided, creates first version automatically
100
+ * @param jobData.activate - If true, activates the job immediately
97
101
  * @returns Promise resolving to an ApiResponse containing the created job details
98
102
  * @throws Error if the job creation fails or validation errors occur
99
103
  */
100
104
  createJob(jobData: CreateJobDTO): Promise<ApiResponse<CreateJobResponse>>;
101
105
  /**
102
- * Creates a new job for the agent
103
- * @param jobData - The job data including name, description, and optional context
104
- * @returns Promise resolving to an JobInstance containing the created job details
106
+ * Creates a new job for the agent and returns a JobInstance.
107
+ * Supports automatic version creation and activation.
108
+ *
109
+ * @param jobData - The job data including name, description, schedule, and optional version
110
+ * @param jobData.version - If provided, creates first version automatically
111
+ * @param jobData.activate - If true, activates the job immediately
112
+ * @returns Promise resolving to a JobInstance containing the created job details
105
113
  * @throws Error if the job creation fails or validation errors occur
106
114
  */
107
115
  createJobInstance(jobData: CreateJobDTO): Promise<JobInstance>;
116
+ private compressCode;
108
117
  /**
109
118
  * Pushes a new version of a job to production
110
119
  * @param jobId - The unique identifier of the job
@@ -1,5 +1,6 @@
1
1
  import { HttpClient } from "../common/http.client.js";
2
2
  import { JobInstance } from "../common/job.instance.js";
3
+ import { gzipSync } from "zlib";
3
4
  /**
4
5
  * Job API Service
5
6
  * Handles all job-related API calls
@@ -42,8 +43,12 @@ export default class JobApi extends HttpClient {
42
43
  throw new Error(response.error?.message || 'Failed to get job');
43
44
  }
44
45
  /**
45
- * Creates a new job for the agent
46
- * @param jobData - The job data including name, description, and optional context
46
+ * Creates a new job for the agent.
47
+ * Optionally creates initial version and activates the job in one call.
48
+ *
49
+ * @param jobData - The job data including name, description, schedule, and optional version
50
+ * @param jobData.version - If provided, creates first version automatically
51
+ * @param jobData.activate - If true, activates the job immediately
47
52
  * @returns Promise resolving to an ApiResponse containing the created job details
48
53
  * @throws Error if the job creation fails or validation errors occur
49
54
  */
@@ -53,12 +58,19 @@ export default class JobApi extends HttpClient {
53
58
  });
54
59
  }
55
60
  /**
56
- * Creates a new job for the agent
57
- * @param jobData - The job data including name, description, and optional context
58
- * @returns Promise resolving to an JobInstance containing the created job details
61
+ * Creates a new job for the agent and returns a JobInstance.
62
+ * Supports automatic version creation and activation.
63
+ *
64
+ * @param jobData - The job data including name, description, schedule, and optional version
65
+ * @param jobData.version - If provided, creates first version automatically
66
+ * @param jobData.activate - If true, activates the job immediately
67
+ * @returns Promise resolving to a JobInstance containing the created job details
59
68
  * @throws Error if the job creation fails or validation errors occur
60
69
  */
61
70
  async createJobInstance(jobData) {
71
+ if (jobData.version?.executeFunction && jobData.version?.executeFunction.length > 0) {
72
+ jobData.version.code = this.compressCode(jobData.version.executeFunction);
73
+ }
62
74
  const response = await this.httpPost(`/developer/jobs/${this.agentId}`, jobData, {
63
75
  Authorization: `Bearer ${this.apiKey}`,
64
76
  });
@@ -67,6 +79,10 @@ export default class JobApi extends HttpClient {
67
79
  }
68
80
  throw new Error(response.error?.message || 'Failed to create job');
69
81
  }
82
+ compressCode(code) {
83
+ const compressed = gzipSync(code);
84
+ return compressed.toString('base64');
85
+ }
70
86
  /**
71
87
  * Pushes a new version of a job to production
72
88
  * @param jobId - The unique identifier of the job
@@ -59,8 +59,26 @@ export default class PostProcessorApi extends HttpClient {
59
59
  }): Promise<ApiResponse<CreatePostProcessorResponse>>;
60
60
  /**
61
61
  * Pushes a new version of a postprocessor
62
+ *
63
+ * @param postprocessorId - The postprocessor ID
64
+ * @param versionData - Version data including code, description, context, and async flag
65
+ * @param versionData.version - Version number
66
+ * @param versionData.code - Compressed execute function code
67
+ * @param versionData.executeFunction - Raw execute function code
68
+ * @param versionData.description - Postprocessor description
69
+ * @param versionData.context - Postprocessor context
70
+ * @param versionData.async - Async execution flag (true = background, false = blocking)
62
71
  */
63
- pushPostProcessor(postprocessorId: string, versionData: any): Promise<ApiResponse<PostProcessorVersionResponse>>;
72
+ pushPostProcessor(postprocessorId: string, versionData: {
73
+ name: string;
74
+ version: string;
75
+ description?: string;
76
+ context?: string;
77
+ postprocessorId: string;
78
+ code: string;
79
+ executeFunction: string;
80
+ async?: boolean;
81
+ }): Promise<ApiResponse<PostProcessorVersionResponse>>;
64
82
  /**
65
83
  * Retrieves all versions of a specific postprocessor
66
84
  */
@@ -95,4 +113,46 @@ export default class PostProcessorApi extends HttpClient {
95
113
  * Deletes a postprocessor
96
114
  */
97
115
  deletePostProcessor(postprocessorId: string): Promise<ApiResponse<DeletePostProcessorResponse>>;
116
+ /**
117
+ * Pushes a new sandbox (dev) version of a postprocessor
118
+ * Creates a new sandbox version for testing without affecting production
119
+ *
120
+ * @param postprocessorId - The postprocessor ID
121
+ * @param versionData - Version data including code and async flag
122
+ * @returns Sandbox version response with sandboxId
123
+ */
124
+ pushDevPostProcessor(postprocessorId: string, versionData: {
125
+ name: string;
126
+ version?: string;
127
+ description?: string;
128
+ context?: string;
129
+ code: string;
130
+ executeFunction: string;
131
+ async?: boolean;
132
+ }): Promise<ApiResponse<{
133
+ versionId: string;
134
+ postprocessorId: string;
135
+ version: string;
136
+ createdAt: string;
137
+ }>>;
138
+ /**
139
+ * Updates an existing sandbox version of a postprocessor
140
+ *
141
+ * @param postprocessorId - The postprocessor ID
142
+ * @param sandboxVersionId - The sandbox version ID to update
143
+ * @param versionData - Updated version data
144
+ * @returns Update response
145
+ */
146
+ updateDevPostProcessor(postprocessorId: string, sandboxVersionId: string, versionData: {
147
+ name: string;
148
+ version?: string;
149
+ description?: string;
150
+ context?: string;
151
+ code: string;
152
+ executeFunction: string;
153
+ async?: boolean;
154
+ }): Promise<ApiResponse<{
155
+ message: string;
156
+ versionId: string;
157
+ }>>;
98
158
  }
@@ -27,6 +27,15 @@ export default class PostProcessorApi extends HttpClient {
27
27
  }
28
28
  /**
29
29
  * Pushes a new version of a postprocessor
30
+ *
31
+ * @param postprocessorId - The postprocessor ID
32
+ * @param versionData - Version data including code, description, context, and async flag
33
+ * @param versionData.version - Version number
34
+ * @param versionData.code - Compressed execute function code
35
+ * @param versionData.executeFunction - Raw execute function code
36
+ * @param versionData.description - Postprocessor description
37
+ * @param versionData.context - Postprocessor context
38
+ * @param versionData.async - Async execution flag (true = background, false = blocking)
30
39
  */
31
40
  async pushPostProcessor(postprocessorId, versionData) {
32
41
  return this.httpPost(`/developer/postprocessors/${this.agentId}/${postprocessorId}/version`, versionData, {
@@ -73,4 +82,30 @@ export default class PostProcessorApi extends HttpClient {
73
82
  Authorization: `Bearer ${this.apiKey}`,
74
83
  });
75
84
  }
85
+ /**
86
+ * Pushes a new sandbox (dev) version of a postprocessor
87
+ * Creates a new sandbox version for testing without affecting production
88
+ *
89
+ * @param postprocessorId - The postprocessor ID
90
+ * @param versionData - Version data including code and async flag
91
+ * @returns Sandbox version response with sandboxId
92
+ */
93
+ async pushDevPostProcessor(postprocessorId, versionData) {
94
+ return this.httpPost(`/developer/postprocessors/${this.agentId}/${postprocessorId}/version/sandbox`, versionData, {
95
+ Authorization: `Bearer ${this.apiKey}`,
96
+ });
97
+ }
98
+ /**
99
+ * Updates an existing sandbox version of a postprocessor
100
+ *
101
+ * @param postprocessorId - The postprocessor ID
102
+ * @param sandboxVersionId - The sandbox version ID to update
103
+ * @param versionData - Updated version data
104
+ * @returns Update response
105
+ */
106
+ async updateDevPostProcessor(postprocessorId, sandboxVersionId, versionData) {
107
+ return this.httpPut(`/developer/postprocessors/${this.agentId}/${postprocessorId}/version/sandbox/${sandboxVersionId}`, versionData, {
108
+ Authorization: `Bearer ${this.apiKey}`,
109
+ });
110
+ }
76
111
  }
@@ -59,8 +59,26 @@ export default class PreProcessorApi extends HttpClient {
59
59
  }): Promise<ApiResponse<CreatePreProcessorResponse>>;
60
60
  /**
61
61
  * Pushes a new version of a preprocessor
62
+ *
63
+ * @param preprocessorId - The preprocessor ID
64
+ * @param versionData - Version data including code, description, context, and async flag
65
+ * @param versionData.version - Version number
66
+ * @param versionData.code - Compressed execute function code
67
+ * @param versionData.executeFunction - Raw execute function code
68
+ * @param versionData.description - Preprocessor description
69
+ * @param versionData.context - Preprocessor context
70
+ * @param versionData.async - Async execution flag (true = background, false = blocking)
62
71
  */
63
- pushPreProcessor(preprocessorId: string, versionData: any): Promise<ApiResponse<PreProcessorVersionResponse>>;
72
+ pushPreProcessor(preprocessorId: string, versionData: {
73
+ name: string;
74
+ version: string;
75
+ description?: string;
76
+ context?: string;
77
+ preprocessorId: string;
78
+ code: string;
79
+ executeFunction: string;
80
+ async?: boolean;
81
+ }): Promise<ApiResponse<PreProcessorVersionResponse>>;
64
82
  /**
65
83
  * Retrieves all versions of a specific preprocessor
66
84
  */
@@ -95,4 +113,46 @@ export default class PreProcessorApi extends HttpClient {
95
113
  * Deletes a preprocessor
96
114
  */
97
115
  deletePreProcessor(preprocessorId: string): Promise<ApiResponse<DeletePreProcessorResponse>>;
116
+ /**
117
+ * Pushes a new sandbox (dev) version of a preprocessor
118
+ * Creates a new sandbox version for testing without affecting production
119
+ *
120
+ * @param preprocessorId - The preprocessor ID
121
+ * @param versionData - Version data including code and async flag
122
+ * @returns Sandbox version response with sandboxId
123
+ */
124
+ pushDevPreProcessor(preprocessorId: string, versionData: {
125
+ name: string;
126
+ version?: string;
127
+ description?: string;
128
+ context?: string;
129
+ code: string;
130
+ executeFunction: string;
131
+ async?: boolean;
132
+ }): Promise<ApiResponse<{
133
+ versionId: string;
134
+ preprocessorId: string;
135
+ version: string;
136
+ createdAt: string;
137
+ }>>;
138
+ /**
139
+ * Updates an existing sandbox version of a preprocessor
140
+ *
141
+ * @param preprocessorId - The preprocessor ID
142
+ * @param sandboxVersionId - The sandbox version ID to update
143
+ * @param versionData - Updated version data
144
+ * @returns Update response
145
+ */
146
+ updateDevPreProcessor(preprocessorId: string, sandboxVersionId: string, versionData: {
147
+ name: string;
148
+ version?: string;
149
+ description?: string;
150
+ context?: string;
151
+ code: string;
152
+ executeFunction: string;
153
+ async?: boolean;
154
+ }): Promise<ApiResponse<{
155
+ message: string;
156
+ versionId: string;
157
+ }>>;
98
158
  }
@@ -27,6 +27,15 @@ export default class PreProcessorApi extends HttpClient {
27
27
  }
28
28
  /**
29
29
  * Pushes a new version of a preprocessor
30
+ *
31
+ * @param preprocessorId - The preprocessor ID
32
+ * @param versionData - Version data including code, description, context, and async flag
33
+ * @param versionData.version - Version number
34
+ * @param versionData.code - Compressed execute function code
35
+ * @param versionData.executeFunction - Raw execute function code
36
+ * @param versionData.description - Preprocessor description
37
+ * @param versionData.context - Preprocessor context
38
+ * @param versionData.async - Async execution flag (true = background, false = blocking)
30
39
  */
31
40
  async pushPreProcessor(preprocessorId, versionData) {
32
41
  return this.httpPost(`/developer/preprocessors/${this.agentId}/${preprocessorId}/version`, versionData, {
@@ -73,4 +82,30 @@ export default class PreProcessorApi extends HttpClient {
73
82
  Authorization: `Bearer ${this.apiKey}`,
74
83
  });
75
84
  }
85
+ /**
86
+ * Pushes a new sandbox (dev) version of a preprocessor
87
+ * Creates a new sandbox version for testing without affecting production
88
+ *
89
+ * @param preprocessorId - The preprocessor ID
90
+ * @param versionData - Version data including code and async flag
91
+ * @returns Sandbox version response with sandboxId
92
+ */
93
+ async pushDevPreProcessor(preprocessorId, versionData) {
94
+ return this.httpPost(`/developer/preprocessors/${this.agentId}/${preprocessorId}/version/sandbox`, versionData, {
95
+ Authorization: `Bearer ${this.apiKey}`,
96
+ });
97
+ }
98
+ /**
99
+ * Updates an existing sandbox version of a preprocessor
100
+ *
101
+ * @param preprocessorId - The preprocessor ID
102
+ * @param sandboxVersionId - The sandbox version ID to update
103
+ * @param versionData - Updated version data
104
+ * @returns Update response
105
+ */
106
+ async updateDevPreProcessor(preprocessorId, sandboxVersionId, versionData) {
107
+ return this.httpPut(`/developer/preprocessors/${this.agentId}/${preprocessorId}/version/sandbox/${sandboxVersionId}`, versionData, {
108
+ Authorization: `Bearer ${this.apiKey}`,
109
+ });
110
+ }
76
111
  }
@@ -29,7 +29,7 @@
29
29
  import { LuaSkill, LuaTool, LuaWebhook, LuaWebhookConfig, LuaJob, LuaJobConfig, JobSchedule, PreProcessor, PreProcessorConfig, PostProcessor, PostProcessorConfig, LuaAgent, LuaAgentConfig, env } from "./types/skill.js";
30
30
  import { Basket, BasketStatus, UpdateBasketMetadataResponse } from "./interfaces/baskets.js";
31
31
  import { OrderResponse, OrderStatus } from "./interfaces/orders.js";
32
- import { ChatHistoryMessage, ChatHistoryContent } from "./interfaces/chat.js";
32
+ import { ChatHistoryMessage, ChatHistoryContent, ChatMessage, TextMessage, ImageMessage, FileMessage, PreProcessorOverride, PostProcessorOverride } from "./interfaces/chat.js";
33
33
  import { JobInstance } from "./common/job.instance.js";
34
34
  import { DeleteProductResponse, Product } from "./interfaces/product.js";
35
35
  import ProductInstance from "./common/product.instance.js";
@@ -291,6 +291,13 @@ export declare const Jobs: {
291
291
  * Creates a new job dynamically from within a tool.
292
292
  * This allows tools to schedule one-time or recurring jobs programmatically.
293
293
  *
294
+ * **What this does:**
295
+ * The server handles everything in ONE API call:
296
+ * 1. Creates the job
297
+ * 2. Creates version 1.0.0 with your execute function
298
+ * 3. Optionally activates the job (if activate: true)
299
+ * 4. Returns a JobInstance for manipulation
300
+ *
294
301
  * @param config - Job configuration
295
302
  * @param config.name - Unique job name
296
303
  * @param config.description - Job description
@@ -298,26 +305,37 @@ export declare const Jobs: {
298
305
  * @param config.execute - Async function to execute
299
306
  * @param config.timeout - Optional timeout in seconds
300
307
  * @param config.retry - Optional retry configuration
301
- * @returns Promise resolving to created job details
308
+ * @param config.metadata - Optional metadata
309
+ * @returns Promise resolving to JobInstance (already created, versioned, and activated)
302
310
  *
303
311
  * @example
304
312
  * ```typescript
305
313
  * // Create a one-time job to check basket in 3 hours
306
- * await Jobs.create({
314
+ * const job = await Jobs.create({
307
315
  * name: `check-basket-${basketId}`,
308
316
  * description: 'Check if basket was abandoned',
309
317
  * schedule: {
310
318
  * type: 'once',
311
319
  * executeAt: new Date(Date.now() + 3 * 60 * 60 * 1000)
312
320
  * },
313
- * execute: async () => {
314
- * const basket = await Baskets.getById(basketId);
321
+ * metadata: {
322
+ * basketId: basketId,
323
+ * checkType: 'abandoned-cart'
324
+ * },
325
+ * execute: async (job, user) => {
326
+ * // Access user context and metadata
327
+ * console.log('Checking basket for user:', user.name);
328
+ * console.log('Basket ID from metadata:', metadata?.basketId);
329
+ *
330
+ * const basket = await Baskets.getById(metadata.basketId);
315
331
  * if (basket.status === 'active') {
316
332
  * // Send reminder
317
333
  * }
318
334
  * return { checked: true };
319
335
  * }
320
336
  * });
337
+ * // Job is now created, versioned as 1.0.0, and activated!
338
+ * console.log(`Job ${job.jobId} is active: ${job.active}`);
321
339
  * ```
322
340
  */
323
341
  create(config: {
@@ -331,6 +349,8 @@ export declare const Jobs: {
331
349
  backoffSeconds?: number;
332
350
  };
333
351
  metadata?: Record<string, any>;
352
+ /** Auto-activate the job after creation (default: true) */
353
+ activate?: boolean;
334
354
  }): Promise<JobInstance>;
335
355
  /**
336
356
  * Retrieves a job by its unique identifier
@@ -383,4 +403,4 @@ export declare const AI: {
383
403
  };
384
404
  export { LuaSkill, LuaTool, LuaWebhook, LuaWebhookConfig, LuaJob, LuaJobConfig, JobSchedule, PreProcessor, PreProcessorConfig, PostProcessor, PostProcessorConfig, LuaAgent, LuaAgentConfig, BasketStatus, OrderStatus, env };
385
405
  export { JobInstance };
386
- export { ChatHistoryMessage, ChatHistoryContent };
406
+ export { ChatHistoryMessage, ChatHistoryContent, ChatMessage, TextMessage, ImageMessage, FileMessage, PreProcessorOverride, PostProcessorOverride };
@@ -378,6 +378,13 @@ export const Jobs = {
378
378
  * Creates a new job dynamically from within a tool.
379
379
  * This allows tools to schedule one-time or recurring jobs programmatically.
380
380
  *
381
+ * **What this does:**
382
+ * The server handles everything in ONE API call:
383
+ * 1. Creates the job
384
+ * 2. Creates version 1.0.0 with your execute function
385
+ * 3. Optionally activates the job (if activate: true)
386
+ * 4. Returns a JobInstance for manipulation
387
+ *
381
388
  * @param config - Job configuration
382
389
  * @param config.name - Unique job name
383
390
  * @param config.description - Job description
@@ -385,72 +392,78 @@ export const Jobs = {
385
392
  * @param config.execute - Async function to execute
386
393
  * @param config.timeout - Optional timeout in seconds
387
394
  * @param config.retry - Optional retry configuration
388
- * @returns Promise resolving to created job details
395
+ * @param config.metadata - Optional metadata
396
+ * @returns Promise resolving to JobInstance (already created, versioned, and activated)
389
397
  *
390
398
  * @example
391
399
  * ```typescript
392
400
  * // Create a one-time job to check basket in 3 hours
393
- * await Jobs.create({
401
+ * const job = await Jobs.create({
394
402
  * name: `check-basket-${basketId}`,
395
403
  * description: 'Check if basket was abandoned',
396
404
  * schedule: {
397
405
  * type: 'once',
398
406
  * executeAt: new Date(Date.now() + 3 * 60 * 60 * 1000)
399
407
  * },
400
- * execute: async () => {
401
- * const basket = await Baskets.getById(basketId);
408
+ * metadata: {
409
+ * basketId: basketId,
410
+ * checkType: 'abandoned-cart'
411
+ * },
412
+ * execute: async (job, user) => {
413
+ * // Access user context and metadata
414
+ * console.log('Checking basket for user:', user.name);
415
+ * console.log('Basket ID from metadata:', metadata?.basketId);
416
+ *
417
+ * const basket = await Baskets.getById(metadata.basketId);
402
418
  * if (basket.status === 'active') {
403
419
  * // Send reminder
404
420
  * }
405
421
  * return { checked: true };
406
422
  * }
407
423
  * });
424
+ * // Job is now created, versioned as 1.0.0, and activated!
425
+ * console.log(`Job ${job.jobId} is active: ${job.active}`);
408
426
  * ```
409
427
  */
410
428
  async create(config) {
411
429
  const instance = await getJobInstance();
412
430
  // Convert the execute function to a string
413
431
  const executeString = config.execute.toString();
414
- // Step 1: Create the job
432
+ console.log('Creating Job');
433
+ // Create the job with initial version and activation in one call
415
434
  const createResult = await instance.createJobInstance({
435
+ dynamic: true,
416
436
  name: config.name,
417
437
  description: config.description,
418
438
  context: config.description || '',
419
439
  schedule: config.schedule,
420
440
  timeout: config.timeout,
421
441
  retry: config.retry,
422
- metadata: config.metadata
442
+ metadata: config.metadata,
443
+ // Include initial version data for automatic version creation
444
+ version: {
445
+ version: '1.0.0',
446
+ description: config.description,
447
+ context: config.description || '',
448
+ code: '', // Will be set by server
449
+ executeFunction: executeString,
450
+ timeout: config.timeout,
451
+ retry: config.retry,
452
+ metadata: config.metadata
453
+ },
454
+ // Activate immediately
455
+ activate: config.activate ?? true
423
456
  });
424
457
  const jobId = createResult.jobId;
425
- // Step 2: Push the initial version with execute function
426
- const pushResult = await instance.pushJob(jobId, {
427
- name: config.name,
428
- version: '1.0.0',
429
- description: config.description,
430
- context: config.description || '',
431
- jobId: jobId,
432
- schedule: config.schedule,
433
- timeout: config.timeout,
434
- retry: config.retry,
435
- executeFunction: executeString,
436
- metadata: config.metadata
437
- });
438
- if (!pushResult.success) {
439
- throw new Error(`Failed to push job version: ${pushResult.error?.message}`);
440
- }
441
- // Step 3: Activate the job so it starts running
442
- const activateResult = await instance.activateJob(jobId);
443
- if (!activateResult.success) {
444
- console.warn(`Job created but activation failed: ${activateResult.error?.message}`);
445
- }
446
- // Step 4: Return a JobInstance for easy manipulation
458
+ // Server has created the job, version, and activated it
459
+ // Return a JobInstance for easy manipulation
447
460
  return new JobInstance(instance, {
448
461
  id: jobId,
449
462
  jobId: jobId,
450
463
  name: config.name,
451
464
  schedule: config.schedule,
452
465
  metadata: config.metadata || {},
453
- active: activateResult.success
466
+ active: config.activate ?? true
454
467
  });
455
468
  },
456
469
  /**
@@ -70,16 +70,23 @@ Examples:
70
70
  program
71
71
  .command("push [type]")
72
72
  .description("☁️ Push skill, webhook, job, or persona version to server")
73
+ .option('--force', 'Skip all confirmation prompts (auto-confirm)')
74
+ .option('--auto-deploy', 'Automatically deploy to production after push')
73
75
  .addHelpText('after', `
74
76
  Arguments:
75
- type Optional: 'skill', 'webhook', 'job', or 'persona' (prompts if not provided)
77
+ type Optional: 'skill', 'webhook', 'job', 'preprocessor', 'postprocessor', 'persona', or 'all' (prompts if not provided)
78
+
79
+ Options:
80
+ --force Skip all confirmation prompts
81
+ --auto-deploy Automatically deploy to production after push
76
82
 
77
83
  Examples:
78
- $ lua push Interactive selection
79
- $ lua push skill Push a skill directly
80
- $ lua push webhook Push a webhook directly
81
- $ lua push job Push a job directly
82
- $ lua push persona Push a persona directly
84
+ $ lua push Interactive selection
85
+ $ lua push skill Push a skill directly
86
+ $ lua push webhook Push a webhook directly
87
+ $ lua push job Push a job directly
88
+ $ lua push all --force Push all components from YAML without prompts
89
+ $ lua push all --force --auto-deploy Push and deploy all to production
83
90
  `)
84
91
  .action(pushCommand);
85
92
  program
@@ -8,8 +8,8 @@ import { loadApiKey, checkApiKey } from '../services/auth.js';
8
8
  import { readSkillConfig } from '../utils/files.js';
9
9
  import { withErrorHandling, writeProgress, writeSuccess } from '../utils/cli.js';
10
10
  import { compileCommand } from './compile.js';
11
- import { pushSkillsToSandbox } from '../utils/dev-api.js';
12
- import { getAllSandboxSkillIds } from '../utils/sandbox-storage.js';
11
+ import { pushSkillsToSandbox, pushProcessorsToSandbox } from '../utils/dev-api.js';
12
+ import { getAllSandboxSkillIds, getAllSandboxPreProcessorIds, getAllSandboxPostProcessorIds } from '../utils/sandbox-storage.js';
13
13
  import ChatApi from '../api/chat.api.service.js';
14
14
  import { BASE_URLS } from '../config/constants.js';
15
15
  import { readDeployJson, validateConfig, validateDeployData, validateAgentConfig, } from '../utils/dev-helpers.js';
@@ -66,7 +66,7 @@ export async function chatCommand() {
66
66
  }, "chat");
67
67
  }
68
68
  /**
69
- * Sets up the sandbox environment by compiling and pushing skills
69
+ * Sets up the sandbox environment by compiling and pushing skills, preprocessors, and postprocessors
70
70
  */
71
71
  async function setupSandboxEnvironment(chatEnv, config) {
72
72
  writeProgress("🔄 Setting up sandbox environment...");
@@ -84,8 +84,31 @@ async function setupSandboxEnvironment(chatEnv, config) {
84
84
  process.exit(1);
85
85
  }
86
86
  writeSuccess(`✅ Pushed ${Object.keys(sandboxIds).length} skills to sandbox`);
87
+ // Push preprocessors and postprocessors to sandbox
88
+ const fs = await import('fs');
89
+ const path = await import('path');
90
+ const preprocessorsPath = path.join(process.cwd(), 'dist', 'preprocessors.json');
91
+ const postprocessorsPath = path.join(process.cwd(), 'dist', 'postprocessors.json');
92
+ let bundledPreProcessors = [];
93
+ let bundledPostProcessors = [];
94
+ if (fs.existsSync(preprocessorsPath)) {
95
+ bundledPreProcessors = JSON.parse(fs.readFileSync(preprocessorsPath, 'utf8'));
96
+ }
97
+ if (fs.existsSync(postprocessorsPath)) {
98
+ bundledPostProcessors = JSON.parse(fs.readFileSync(postprocessorsPath, 'utf8'));
99
+ }
100
+ if (bundledPreProcessors.length > 0 || bundledPostProcessors.length > 0) {
101
+ writeProgress("🔄 Pushing processors to sandbox...");
102
+ const processorCounts = await pushProcessorsToSandbox(chatEnv.apiKey, chatEnv.agentId, config, bundledPreProcessors, bundledPostProcessors, true);
103
+ if (processorCounts.preprocessors > 0 || processorCounts.postprocessors > 0) {
104
+ writeSuccess(`✅ Pushed ${processorCounts.preprocessors} preprocessor(s) and ${processorCounts.postprocessors} postprocessor(s) to sandbox`);
105
+ }
106
+ }
87
107
  // Store deploy data for skill overrides
88
108
  chatEnv.deployData = deployData;
109
+ // Get processor overrides for sandbox
110
+ chatEnv.preprocessorOverrides = await getAllSandboxPreProcessorIds(config);
111
+ chatEnv.postprocessorOverrides = await getAllSandboxPostProcessorIds(config);
89
112
  // Check for persona in config
90
113
  if (config.agent?.persona) {
91
114
  chatEnv.persona = config.agent.persona;
@@ -198,7 +221,9 @@ async function sendSandboxMessage(chatEnv, message) {
198
221
  }
199
222
  ],
200
223
  navigate: true,
201
- skillOverride: allSkillOverrides
224
+ skillOverride: allSkillOverrides,
225
+ preprocessorOverride: chatEnv.preprocessorOverrides || [],
226
+ postprocessorOverride: chatEnv.postprocessorOverrides || []
202
227
  };
203
228
  // Add persona override if available
204
229
  if (chatEnv.persona) {
@@ -224,7 +249,9 @@ async function sendProductionMessage(chatEnv, message) {
224
249
  }
225
250
  ],
226
251
  navigate: true,
227
- skillOverride: []
252
+ skillOverride: [],
253
+ preprocessorOverride: [],
254
+ postprocessorOverride: []
228
255
  };
229
256
  const chatApi = new ChatApi(BASE_URLS.CHAT, chatEnv.apiKey);
230
257
  const response = await chatApi.sendMessage(chatEnv.agentId, chatRequest);