lua-cli 2.5.8 → 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 (115) hide show
  1. package/dist/api/job.api.service.d.ts +219 -0
  2. package/dist/api/job.api.service.js +216 -0
  3. package/dist/api/lazy-instances.d.ts +24 -0
  4. package/dist/api/lazy-instances.js +48 -0
  5. package/dist/api/postprocessor.api.service.d.ts +158 -0
  6. package/dist/api/postprocessor.api.service.js +111 -0
  7. package/dist/api/preprocessor.api.service.d.ts +158 -0
  8. package/dist/api/preprocessor.api.service.js +111 -0
  9. package/dist/api/user.data.api.service.d.ts +13 -0
  10. package/dist/api/user.data.api.service.js +20 -0
  11. package/dist/api/webhook.api.service.d.ts +151 -0
  12. package/dist/api/webhook.api.service.js +134 -0
  13. package/dist/api-exports.d.ts +176 -41
  14. package/dist/api-exports.js +195 -21
  15. package/dist/cli/command-definitions.js +75 -5
  16. package/dist/commands/chat.js +32 -5
  17. package/dist/commands/compile.js +140 -7
  18. package/dist/commands/dev.js +23 -2
  19. package/dist/commands/index.d.ts +4 -0
  20. package/dist/commands/index.js +4 -0
  21. package/dist/commands/init.js +53 -7
  22. package/dist/commands/jobs.d.ts +20 -0
  23. package/dist/commands/jobs.js +533 -0
  24. package/dist/commands/logs.js +2 -5
  25. package/dist/commands/postprocessors.d.ts +8 -0
  26. package/dist/commands/postprocessors.js +431 -0
  27. package/dist/commands/preprocessors.d.ts +8 -0
  28. package/dist/commands/preprocessors.js +431 -0
  29. package/dist/commands/push.js +686 -5
  30. package/dist/commands/test.d.ts +9 -18
  31. package/dist/commands/test.js +574 -82
  32. package/dist/commands/webhooks.d.ts +18 -0
  33. package/dist/commands/webhooks.js +424 -0
  34. package/dist/common/job.instance.d.ts +80 -0
  35. package/dist/common/job.instance.js +116 -0
  36. package/dist/common/user.instance.d.ts +1 -0
  37. package/dist/common/user.instance.js +9 -0
  38. package/dist/config/constants.d.ts +4 -3
  39. package/dist/config/constants.js +10 -8
  40. package/dist/interfaces/agent.d.ts +2 -1
  41. package/dist/interfaces/chat.d.ts +52 -1
  42. package/dist/interfaces/index.d.ts +10 -0
  43. package/dist/interfaces/index.js +7 -0
  44. package/dist/interfaces/jobs.d.ts +193 -0
  45. package/dist/interfaces/jobs.js +5 -0
  46. package/dist/interfaces/postprocessors.d.ts +35 -0
  47. package/dist/interfaces/postprocessors.js +4 -0
  48. package/dist/interfaces/preprocessors.d.ts +35 -0
  49. package/dist/interfaces/preprocessors.js +4 -0
  50. package/dist/interfaces/webhooks.d.ts +104 -0
  51. package/dist/interfaces/webhooks.js +5 -0
  52. package/dist/types/api-contracts.d.ts +5 -0
  53. package/dist/types/compile.types.d.ts +49 -0
  54. package/dist/types/index.d.ts +1 -1
  55. package/dist/types/index.js +1 -1
  56. package/dist/types/skill.d.ts +521 -0
  57. package/dist/types/skill.js +471 -0
  58. package/dist/utils/agent-management.d.ts +25 -0
  59. package/dist/utils/agent-management.js +67 -0
  60. package/dist/utils/bundling.d.ts +44 -5
  61. package/dist/utils/bundling.js +723 -23
  62. package/dist/utils/compile.d.ts +63 -0
  63. package/dist/utils/compile.js +712 -36
  64. package/dist/utils/deployment.d.ts +2 -1
  65. package/dist/utils/deployment.js +16 -2
  66. package/dist/utils/dev-api.d.ts +42 -2
  67. package/dist/utils/dev-api.js +177 -4
  68. package/dist/utils/dev-server.d.ts +1 -1
  69. package/dist/utils/dev-server.js +4 -4
  70. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  71. package/dist/utils/dynamic-job-bundler.js +143 -0
  72. package/dist/utils/init-agent.d.ts +3 -1
  73. package/dist/utils/init-agent.js +6 -4
  74. package/dist/utils/init-prompts.d.ts +2 -1
  75. package/dist/utils/init-prompts.js +14 -9
  76. package/dist/utils/job-management.d.ts +24 -0
  77. package/dist/utils/job-management.js +264 -0
  78. package/dist/utils/postprocessor-management.d.ts +9 -0
  79. package/dist/utils/postprocessor-management.js +118 -0
  80. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  81. package/dist/utils/pre-bundle-jobs.js +176 -0
  82. package/dist/utils/preprocessor-management.d.ts +9 -0
  83. package/dist/utils/preprocessor-management.js +118 -0
  84. package/dist/utils/sandbox-storage.d.ts +48 -0
  85. package/dist/utils/sandbox-storage.js +114 -0
  86. package/dist/utils/sandbox.d.ts +61 -1
  87. package/dist/utils/sandbox.js +299 -72
  88. package/dist/utils/tool-detection.d.ts +3 -2
  89. package/dist/utils/tool-detection.js +18 -4
  90. package/dist/utils/webhook-management.d.ts +24 -0
  91. package/dist/utils/webhook-management.js +256 -0
  92. package/package.json +1 -1
  93. package/template/README.md +30 -2
  94. package/template/lua.skill.yaml +47 -0
  95. package/template/package-lock.json +10505 -0
  96. package/template/package.json +2 -1
  97. package/template/src/index.ts +103 -2
  98. package/template/src/jobs/AbandonedBasketProcessorJob.ts +139 -0
  99. package/template/src/jobs/DailyCleanupJob.ts +100 -0
  100. package/template/src/jobs/DataMigrationJob.ts +133 -0
  101. package/template/src/jobs/HealthCheckJob.ts +87 -0
  102. package/template/src/tools/CreateInlineJob.ts +42 -0
  103. package/template/src/tools/GameScoreTrackerTool.ts +356 -0
  104. package/template/src/tools/SmartBasketTool.ts +188 -0
  105. package/template/src/webhooks/PaymentWebhook.ts +113 -0
  106. package/template/src/webhooks/UserEventWebhook.ts +77 -0
  107. package/API_REFERENCE.md +0 -1408
  108. package/CHANGELOG.md +0 -236
  109. package/CLI_REFERENCE.md +0 -908
  110. package/GETTING_STARTED.md +0 -1040
  111. package/INSTANCE_TYPES.md +0 -1158
  112. package/README.md +0 -865
  113. package/TEMPLATE_GUIDE.md +0 -1398
  114. package/USER_DATA_INSTANCE.md +0 -621
  115. package/template/TOOL_EXAMPLES.md +0 -655
@@ -18,8 +18,9 @@
18
18
  "@types/js-yaml": "^4.0.9",
19
19
  "axios": "^1.6.0",
20
20
  "inquirer": "^12.9.6",
21
+ "stripe": "^17.5.0",
21
22
  "js-yaml": "^4.1.0",
22
- "lua-cli": "^2.5.8",
23
+ "lua-cli": "^3.0.0-alpha.4",
23
24
  "openai": "^5.23.0",
24
25
  "uuid": "^13.0.0",
25
26
  "zod": "^3.24.1"
@@ -1,4 +1,4 @@
1
- import { LuaSkill, User, Products, Orders, Data, Baskets } from "lua-cli";
1
+ import { LuaSkill, User, Products, Orders, Data, Baskets, LuaJob, JobInstance, LuaWebhook, Jobs } from "lua-cli";
2
2
  import GetWeatherTool from "./tools/GetWeatherTool";
3
3
  import { GetUserDataTool, UpdateUserDataTool } from "./tools/UserDataTool";
4
4
  import CreatePostTool from "./tools/CreatePostTool";
@@ -7,6 +7,47 @@ import CreatePaymentLinkTool from "./tools/PaymentTool";
7
7
  import { CreateBasketTool, GetBasketsTool, AddItemToBasketTool, RemoveItemFromBasketTool, ClearBasketTool, UpdateBasketStatusTool, UpdateBasketMetadataTool, CheckoutBasketTool, GetBasketByIdTool } from "./tools/BasketTool";
8
8
  import { CreateOrderTool, UpdateOrderStatusTool, GetOrderByIdTool, GetUserOrdersTool } from "./tools/OrderTool";
9
9
  import { CreateMovieTool, GetMoviesTool, GetMovieByIdTool, UpdateMovieTool, SearchMoviesTool, DeleteMovieTool } from "./tools/CustomDataTool";
10
+ import CreateInlineJobTool from "./tools/CreateInlineJob";
11
+ import { v4 } from 'uuid';
12
+
13
+ // ============================================================================
14
+ // WEBHOOK EXAMPLES (Uncomment to enable)
15
+ // ============================================================================
16
+ // Webhooks receive HTTP requests from external systems
17
+ // See: WEBHOOK_JOB_EXAMPLES.md for detailed explanations
18
+
19
+ // import userEventWebhook from "./webhooks/UserEventWebhook";
20
+ // import paymentWebhook from "./webhooks/PaymentWebhook";
21
+
22
+ // ============================================================================
23
+ // JOB EXAMPLES (Uncomment to enable)
24
+ // ============================================================================
25
+ // Jobs are scheduled tasks that run at specific times or intervals
26
+ // See: WEBHOOK_JOB_EXAMPLES.md for detailed explanations
27
+
28
+ import dailyCleanupJob from "./jobs/DailyCleanupJob";
29
+ // import healthCheckJob from "./jobs/HealthCheckJob";
30
+ // import dataMigrationJob from "./jobs/DataMigrationJob";
31
+ // import abandonedBasketProcessorJob from "./jobs/AbandonedBasketProcessorJob";
32
+
33
+ // ============================================================================
34
+ // SMART BASKET TOOL (Uncomment to enable)
35
+ // ============================================================================
36
+ // This tool creates baskets with automatic abandoned cart reminders
37
+ // Uses Jobs.create() to schedule one-time check 3 hours after creation
38
+
39
+ // import { CreateSmartBasketTool, CheckAbandonedBasketsTool } from "./tools/SmartBasketTool";
40
+
41
+ // ============================================================================
42
+ // GAME SCORE TRACKER (Uncomment to enable) - ADVANCED EXAMPLE
43
+ // ============================================================================
44
+ // Complex example showing:
45
+ // - Interval jobs that start at specific time
46
+ // - Jobs that stop themselves when condition is met
47
+ // - Real-time monitoring with external API integration
48
+ // See: COMPLEX_JOB_EXAMPLES.md for detailed explanation
49
+
50
+ // import { TrackGameScoresTool, GetGameScoresTool, StopGameTrackingTool } from "./tools/GameScoreTrackerTool";
10
51
 
11
52
 
12
53
  // Initialize skill with tools
@@ -17,7 +58,8 @@ const generalSkill = new LuaSkill({
17
58
  context: "This skill provides various utilities including weather information, user data retrieval, post creation, basic calculator operations, and advanced mathematical functions. Use get_weather to fetch current weather conditions for any city, get_user_data to retrieve user information, create_post to publish new posts, calculator for basic arithmetic operations, and advanced_math for complex mathematical computations like factorials, prime checking, fibonacci sequences, and greatest common divisor calculations.",
18
59
  tools: [
19
60
  new GetWeatherTool(),
20
- new CreatePostTool()
61
+ new CreatePostTool(),
62
+ new CreateInlineJobTool()
21
63
  ]
22
64
  });
23
65
 
@@ -120,6 +162,65 @@ const testCases = [
120
162
  { tool: "get_weather", cityLong: "London", apiKey: "123" }
121
163
  ];
122
164
 
165
+ const job = new LuaJob({
166
+ description: "Test job",
167
+ context: "Test job context",
168
+ name: "test-job",
169
+ schedule: {
170
+ type: "once",
171
+ executeAt: new Date(Date.now() + 1000).toISOString()
172
+ },
173
+ metadata: {
174
+ test: "test"
175
+ },
176
+ execute: async (job: JobInstance) => {
177
+ console.log("Job executed");
178
+ return { success: true, message: "Job executed successfully" };
179
+ }
180
+ });
181
+
182
+ //create webhook
183
+ const webhook = new LuaWebhook({
184
+ description: "Test webhook",
185
+ context: "Test webhook context",
186
+ name: "test-webhook",
187
+ execute: async (query: any, headers: any, body: any) => {
188
+ console.log("Webhook executed");
189
+ return { success: true, message: "Webhook executed successfully" };
190
+ }
191
+ });
192
+
193
+ const newJob = new LuaJob({
194
+ description: "Test job",
195
+ context: "Test job context",
196
+ name: "test-job",
197
+ schedule: {
198
+ type: "once",
199
+ executeAt: new Date(Date.now() + 1000).toISOString()
200
+ },
201
+ execute: async (job: JobInstance) => {
202
+ console.log("Job executed", job);
203
+ const realtimeJob = await Jobs.create({
204
+ name: `realtime-job-new-this-again`,
205
+ description: "Realtime job",
206
+ schedule: {
207
+ type: "once",
208
+ executeAt: new Date(Date.now() + 1000).toISOString()
209
+ },
210
+ execute: async (job: JobInstance) => {
211
+ // console.log("Executing realtime job", job.data);
212
+ console.log("Realtime job metadata", job.metadata);
213
+ console.log("Realtime job user", job.user);
214
+ return { success: true, message: "Realtime job executed successfully" };
215
+ }
216
+ });
217
+ return { success: true, message: "Job executed successfully" };
218
+ }
219
+ });
220
+
221
+
222
+ console.log("Job created:", job);
223
+
123
224
  async function runTests() {
124
225
  // await seedProducts();
125
226
  console.log("🧪 Running tool tests...\n");
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Abandoned Basket Processor Job
3
+ *
4
+ * This job runs every 15 minutes to process basket checkout reminders.
5
+ * Works together with CreateSmartBasketTool to send abandoned cart notifications.
6
+ *
7
+ * Flow:
8
+ * 1. User creates basket → Tool schedules reminder in custom data
9
+ * 2. This job runs every 15 minutes
10
+ * 3. Checks which reminders are due
11
+ * 4. Checks if baskets were checked out
12
+ * 5. Sends reminders for abandoned baskets
13
+ */
14
+
15
+ import { LuaJob, Data, Baskets } from "lua-cli";
16
+
17
+ const abandonedBasketProcessorJob = new LuaJob({
18
+ name: "process-basket-reminders",
19
+ version: "1.0.0",
20
+ description: "Processes abandoned basket reminders",
21
+ context: "Runs every 15 minutes to check for abandoned baskets and send recovery emails. " +
22
+ "Works with basket creation tools that schedule reminders.",
23
+
24
+ // Run every 15 minutes
25
+ schedule: {
26
+ type: 'interval',
27
+ seconds: 900 // 15 minutes = 900 seconds
28
+ },
29
+
30
+ timeout: 120, // 2 minutes
31
+
32
+ execute: async () => {
33
+ console.log('🔍 Processing basket reminders...');
34
+
35
+ // Get all pending reminders
36
+ const remindersResponse = await Data.get('basket-reminders', {}, 1, 500);
37
+ const reminders = remindersResponse.data || [];
38
+ const now = new Date();
39
+
40
+ let processedCount = 0;
41
+ let abandonedCount = 0;
42
+ let checkedOutCount = 0;
43
+
44
+ for (const reminder of reminders) {
45
+ // Skip if not yet time
46
+ const scheduledTime = new Date(reminder.data.scheduledFor);
47
+ if (scheduledTime > now) continue;
48
+
49
+ // Skip if already processed
50
+ if (reminder.data.status !== 'pending') continue;
51
+
52
+ try {
53
+ // Get the basket
54
+ const basketInstance = await Baskets.getById(reminder.data.basketId);
55
+ const basket = await basketInstance.getData();
56
+
57
+ // Check basket status
58
+ const isAbandoned = basket.status === 'active';
59
+
60
+ if (isAbandoned) {
61
+ // Basket is abandoned - send reminder
62
+ console.log(`🛒 Abandoned basket found: ${basket.id}`);
63
+ abandonedCount++;
64
+
65
+ // Calculate basket value
66
+ const totalValue = basket.items?.reduce((sum: number, item: any) => {
67
+ return sum + (item.price * item.quantity);
68
+ }, 0) || 0;
69
+
70
+ // Log abandoned basket
71
+ await Data.create('abandoned-baskets', {
72
+ basketId: basket.id,
73
+ currency: basket.currency,
74
+ itemCount: basket.items?.length || 0,
75
+ totalValue,
76
+ items: basket.items,
77
+ abandonedAt: new Date().toISOString(),
78
+ reminderSent: true
79
+ });
80
+
81
+ // Update reminder status
82
+ await Data.update('basket-reminders', reminder.id, {
83
+ ...reminder.data,
84
+ status: 'completed',
85
+ result: 'abandoned',
86
+ processedAt: new Date().toISOString()
87
+ });
88
+
89
+ // TODO: Send actual reminder email/SMS
90
+ console.log(`📧 Would send reminder: "You left ${basket.items?.length || 0} items in your cart!"`);
91
+
92
+ } else {
93
+ // Basket was checked out
94
+ console.log(`✅ Basket ${basket.id} was checked out (${basket.status})`);
95
+ checkedOutCount++;
96
+
97
+ // Update reminder status
98
+ await Data.update('basket-reminders', reminder.id, {
99
+ ...reminder.data,
100
+ status: 'completed',
101
+ result: 'checked-out',
102
+ processedAt: new Date().toISOString()
103
+ });
104
+ }
105
+
106
+ processedCount++;
107
+
108
+ } catch (error) {
109
+ console.error(`❌ Error processing basket ${reminder.data.basketId}:`, error);
110
+
111
+ // Mark as error
112
+ try {
113
+ await Data.update('basket-reminders', reminder.id, {
114
+ ...reminder.data,
115
+ status: 'error',
116
+ error: String(error),
117
+ processedAt: new Date().toISOString()
118
+ });
119
+ } catch (updateError) {
120
+ console.error('Failed to update reminder status:', updateError);
121
+ }
122
+ }
123
+ }
124
+
125
+ console.log('✅ Reminder processing complete');
126
+ console.log(`📊 Processed: ${processedCount}, Abandoned: ${abandonedCount}, Checked out: ${checkedOutCount}`);
127
+
128
+ return {
129
+ success: true,
130
+ processedCount,
131
+ abandonedCount,
132
+ checkedOutCount,
133
+ timestamp: new Date().toISOString()
134
+ };
135
+ }
136
+ });
137
+
138
+ export default abandonedBasketProcessorJob;
139
+
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Daily Cleanup Job Example
3
+ *
4
+ * This job runs daily at 2 AM to clean up old data and maintain database performance.
5
+ * Demonstrates: Cron scheduling, data cleanup, and error handling.
6
+ */
7
+
8
+ import { LuaJob, Data } from "lua-cli";
9
+
10
+ const dailyCleanupJob = new LuaJob({
11
+ name: "daily-cleanup",
12
+ version: "1.0.0",
13
+ description: "Daily database cleanup and maintenance",
14
+ context: "Runs at 2 AM EST daily to remove old logs, expired sessions, and optimize data collections. " +
15
+ "This job helps maintain database performance and storage costs.",
16
+
17
+ // Cron schedule: Every day at 2 AM EST
18
+ schedule: {
19
+ type: 'cron',
20
+ expression: '0 2 * * *', // minute hour day month day-of-week
21
+ timezone: 'America/New_York'
22
+ },
23
+
24
+ // Give it 10 minutes to complete
25
+ timeout: 600,
26
+
27
+ // Retry up to 3 times if it fails
28
+ retry: {
29
+ maxAttempts: 3,
30
+ backoffSeconds: 60 // Wait 60s between retries
31
+ },
32
+
33
+ execute: async () => {
34
+ console.log('🧹 Starting daily cleanup...');
35
+ const startTime = Date.now();
36
+
37
+ let totalRecordsDeleted = 0;
38
+
39
+ // 1. Clean up old user events (older than 90 days)
40
+ const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000);
41
+
42
+ try {
43
+ const oldEventsResponse = await Data.get('user-events', {}, 1, 1000);
44
+ const oldEvents = oldEventsResponse.data || [];
45
+
46
+ for (const event of oldEvents) {
47
+ const eventDate = new Date(event.data.receivedAt);
48
+ if (eventDate < ninetyDaysAgo) {
49
+ await Data.delete('user-events', event.id);
50
+ totalRecordsDeleted++;
51
+ }
52
+ }
53
+
54
+ console.log(`✅ Deleted ${totalRecordsDeleted} old user events`);
55
+ } catch (error) {
56
+ console.error('❌ Error cleaning user events:', error);
57
+ }
58
+
59
+ // 2. Clean up old payment logs (older than 180 days)
60
+ const oneEightyDaysAgo = new Date(Date.now() - 180 * 24 * 60 * 60 * 1000);
61
+
62
+ try {
63
+ const oldLogsResponse = await Data.get('payment-logs', {}, 1, 1000);
64
+ const oldLogs = oldLogsResponse.data || [];
65
+ let logsDeleted = 0;
66
+
67
+ for (const log of oldLogs) {
68
+ const logDate = new Date(log.data.receivedAt);
69
+ if (logDate < oneEightyDaysAgo) {
70
+ await Data.delete('payment-logs', log.id);
71
+ logsDeleted++;
72
+ totalRecordsDeleted++;
73
+ }
74
+ }
75
+
76
+ console.log(`✅ Deleted ${logsDeleted} old payment logs`);
77
+ } catch (error) {
78
+ console.error('❌ Error cleaning payment logs:', error);
79
+ }
80
+
81
+ // 3. Clean up abandoned baskets (older than 7 days)
82
+ // Note: This would require basket API support for deletion
83
+ // For now, we'll just log the count
84
+
85
+ const duration = Date.now() - startTime;
86
+
87
+ console.log(`✅ Cleanup complete in ${duration}ms`);
88
+
89
+ return {
90
+ success: true,
91
+ recordsDeleted: totalRecordsDeleted,
92
+ duration: `${duration}ms`,
93
+ completedAt: new Date().toISOString(),
94
+ collections: ['user-events', 'payment-logs']
95
+ };
96
+ }
97
+ });
98
+
99
+ export default dailyCleanupJob;
100
+
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Data Migration Job Example
3
+ *
4
+ * This is a one-time job that runs at a specific date/time to migrate data.
5
+ * Demonstrates: One-time scheduling, data migration, and batch processing.
6
+ */
7
+
8
+ import { LuaJob, Data } from "lua-cli";
9
+
10
+ const dataMigrationJob = new LuaJob({
11
+ name: "migrate-user-schema",
12
+ version: "1.0.0",
13
+ description: "One-time migration to new user event schema",
14
+ context: "Scheduled one-time task to migrate user events from old schema to new schema. " +
15
+ "Runs once at the specified time and then automatically deactivates.",
16
+
17
+ // One-time schedule: Run at specific date/time
18
+ schedule: {
19
+ type: 'once',
20
+ executeAt: new Date('2025-12-31T02:00:00Z') // December 31, 2025 at 2 AM UTC
21
+ },
22
+
23
+ // Give it 30 minutes for large migration
24
+ timeout: 1800,
25
+
26
+ // Retry important migrations
27
+ retry: {
28
+ maxAttempts: 3,
29
+ backoffSeconds: 300 // 5 minutes between retries
30
+ },
31
+
32
+ execute: async () => {
33
+ console.log('🔄 Starting data migration...');
34
+ const startTime = Date.now();
35
+
36
+ let totalMigrated = 0;
37
+ let totalErrors = 0;
38
+
39
+ try {
40
+ // Get all user events with old schema
41
+ const oldEventsResponse = await Data.get('user-events', {}, 1, 1000);
42
+ const oldEvents = oldEventsResponse.data || [];
43
+
44
+ console.log(`📊 Found ${oldEvents.length} events to migrate`);
45
+
46
+ // Migrate each event
47
+ for (const event of oldEvents) {
48
+ try {
49
+ // Transform old schema to new schema
50
+ const migratedEvent = {
51
+ // New fields
52
+ eventId: event.id,
53
+ eventType: event.data.type || 'unknown',
54
+ userId: event.data.userId || event.data.user_id, // Handle both formats
55
+ email: event.data.email,
56
+ name: event.data.name,
57
+
58
+ // Preserve metadata
59
+ metadata: {
60
+ ...event.data.metadata,
61
+ migratedFrom: 'old-schema',
62
+ migratedAt: new Date().toISOString()
63
+ },
64
+
65
+ // Copy timestamps
66
+ originalTimestamp: event.data.timestamp,
67
+ receivedAt: event.data.receivedAt
68
+ };
69
+
70
+ // Create in new collection
71
+ await Data.create('user-events-v2', migratedEvent,
72
+ `${migratedEvent.eventType} ${migratedEvent.email}`
73
+ );
74
+
75
+ totalMigrated++;
76
+
77
+ // Log progress every 100 records
78
+ if (totalMigrated % 100 === 0) {
79
+ console.log(`✅ Migrated ${totalMigrated} records...`);
80
+ }
81
+
82
+ } catch (error) {
83
+ console.error(`❌ Failed to migrate event ${event.id}:`, error);
84
+ totalErrors++;
85
+ }
86
+ }
87
+
88
+ const duration = Date.now() - startTime;
89
+ const successRate = ((totalMigrated / oldEvents.length) * 100).toFixed(2);
90
+
91
+ console.log(`✅ Migration complete!`);
92
+ console.log(`📊 Stats:`);
93
+ console.log(` - Total records: ${oldEvents.length}`);
94
+ console.log(` - Migrated: ${totalMigrated}`);
95
+ console.log(` - Errors: ${totalErrors}`);
96
+ console.log(` - Success rate: ${successRate}%`);
97
+ console.log(` - Duration: ${duration}ms`);
98
+
99
+ // Store migration report
100
+ await Data.create('migration-reports', {
101
+ jobName: 'migrate-user-schema',
102
+ totalRecords: oldEvents.length,
103
+ migrated: totalMigrated,
104
+ errors: totalErrors,
105
+ successRate: parseFloat(successRate),
106
+ duration,
107
+ completedAt: new Date().toISOString()
108
+ });
109
+
110
+ return {
111
+ success: true,
112
+ totalRecords: oldEvents.length,
113
+ migrated: totalMigrated,
114
+ errors: totalErrors,
115
+ successRate: `${successRate}%`,
116
+ duration: `${duration}ms`
117
+ };
118
+
119
+ } catch (error) {
120
+ console.error('💥 Migration failed:', error);
121
+
122
+ return {
123
+ success: false,
124
+ error: String(error),
125
+ totalMigrated,
126
+ totalErrors
127
+ };
128
+ }
129
+ }
130
+ });
131
+
132
+ export default dataMigrationJob;
133
+
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Health Check Job Example
3
+ *
4
+ * This job runs every 5 minutes to check system health and alert on issues.
5
+ * Demonstrates: Interval scheduling, monitoring, and alerting.
6
+ */
7
+
8
+ import { LuaJob, Data, Products } from "lua-cli";
9
+
10
+ const healthCheckJob = new LuaJob({
11
+ name: "health-check",
12
+ version: "1.0.0",
13
+ description: "System health monitoring",
14
+ context: "Runs every 5 minutes to check API health, database connectivity, and service availability. " +
15
+ "Logs health metrics and can trigger alerts if issues are detected.",
16
+
17
+ // Interval schedule: Every 5 minutes
18
+ schedule: {
19
+ type: 'interval',
20
+ seconds: 300 // 5 minutes = 300 seconds
21
+ },
22
+
23
+ // Quick timeout for health checks
24
+ timeout: 30,
25
+
26
+ execute: async () => {
27
+ console.log('❤️ Running health check...');
28
+ const checks: any = {};
29
+
30
+ // Check 1: Database connectivity
31
+ try {
32
+ const testQuery = await Data.get('health-checks', {}, 1, 1);
33
+ checks.database = {
34
+ status: 'healthy',
35
+ responseTime: Date.now()
36
+ };
37
+ } catch (error) {
38
+ checks.database = {
39
+ status: 'unhealthy',
40
+ error: String(error)
41
+ };
42
+ }
43
+
44
+ // Check 2: Products API
45
+ try {
46
+ const startTime = Date.now();
47
+ await Products.get(1, 1);
48
+ const responseTime = Date.now() - startTime;
49
+
50
+ checks.productsApi = {
51
+ status: 'healthy',
52
+ responseTime: `${responseTime}ms`
53
+ };
54
+ } catch (error) {
55
+ checks.productsApi = {
56
+ status: 'unhealthy',
57
+ error: String(error)
58
+ };
59
+ }
60
+
61
+ // Determine overall health
62
+ const allHealthy = Object.values(checks).every((check: any) => check.status === 'healthy');
63
+ const overallStatus = allHealthy ? 'healthy' : 'degraded';
64
+
65
+ // Log health check result
66
+ await Data.create('health-checks', {
67
+ status: overallStatus,
68
+ checks,
69
+ timestamp: new Date().toISOString()
70
+ });
71
+
72
+ // Alert if unhealthy (in production, send to monitoring service)
73
+ if (!allHealthy) {
74
+ console.warn('⚠️ System health degraded:', checks);
75
+ // TODO: Send alert to monitoring service
76
+ }
77
+
78
+ return {
79
+ status: overallStatus,
80
+ checks,
81
+ timestamp: new Date().toISOString()
82
+ };
83
+ }
84
+ });
85
+
86
+ export default healthCheckJob;
87
+
@@ -0,0 +1,42 @@
1
+ import { LuaTool } from "lua-cli/skill";
2
+ import { z } from "zod";
3
+ import { AI, JobInstance, Jobs } from "../../../dist/api-exports";
4
+ import ApiService from "../services/ApiService";
5
+ import { v4 as uuidv4 } from 'uuid';
6
+
7
+ export default class CreateInlineJobTool implements LuaTool {
8
+ name = "create_inline_job";
9
+ description = "Create a new inline job";
10
+ inputSchema = z.object({});
11
+
12
+ async execute(input: z.infer<typeof this.inputSchema>) {
13
+ const jobId = uuidv4();
14
+ const job = await Jobs.create({
15
+ name: `inline-job-${jobId}`,
16
+ description: "Inline job",
17
+ schedule: {
18
+ type: "once",
19
+ executeAt: new Date(Date.now() + 1000)
20
+ },
21
+ metadata: {
22
+ test: "test"
23
+ },
24
+ execute: async (job: JobInstance) => {
25
+ // console.log("Executing inline job", job);
26
+ console.log("Inline job metadata", job.metadata);
27
+ console.log("Inline job user", job.user());
28
+ console.log("Inline job data", job.data);
29
+ const response = await AI.generate("You are a poet. Write a poem about the following topic:", [{ type: "text", text: "A sheep in the field" }]);
30
+ console.log("AI response", response);
31
+ const apiService = new ApiService();
32
+ const data = await apiService.fetchUserData("123");
33
+ await job.updateMetadata({ test: "test2" });
34
+ const disabled = await job.delete();
35
+ console.log("Inline job deleted", disabled);
36
+ return { success: true, data: response, user: data };
37
+ }
38
+ });
39
+
40
+ return { success: true, job: job };
41
+ }
42
+ }