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
@@ -2,6 +2,9 @@
2
2
  * Push Command
3
3
  * Orchestrates pushing skill versions to the server
4
4
  */
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import yaml from 'js-yaml';
5
8
  import { compileCommand } from './compile.js';
6
9
  import { checkApiKey, loadApiKey } from '../services/auth.js';
7
10
  import { readSkillConfig } from '../utils/files.js';
@@ -11,6 +14,8 @@ import { readDeployJson, validatePushConfig, validateDeployData, promptSkillSele
11
14
  import { pushVersion } from '../utils/push-api.js';
12
15
  import { fetchVersions, publishVersion, } from '../utils/deploy-api.js';
13
16
  import { BASE_URLS } from '../config/constants.js';
17
+ import PreProcessorApi from '../api/preprocessor.api.service.js';
18
+ import PostProcessorApi from '../api/postprocessor.api.service.js';
14
19
  /**
15
20
  * Main push command - pushes a skill or persona version to the server.
16
21
  *
@@ -35,12 +40,16 @@ export async function pushCommand(type) {
35
40
  // Step 1: Check if type was provided as argument
36
41
  if (type) {
37
42
  // Validate the provided type
38
- if (type !== 'skill' && type !== 'persona') {
39
- console.error(`❌ Invalid type: "${type}". Must be "skill" or "persona".`);
43
+ if (type !== 'skill' && type !== 'persona' && type !== 'webhook' && type !== 'job' && type !== 'preprocessor' && type !== 'postprocessor') {
44
+ console.error(`❌ Invalid type: "${type}". Must be "skill", "persona", "webhook", "job", "preprocessor", or "postprocessor".`);
40
45
  console.log('\nUsage:');
41
- console.log(' lua push - Interactive selection');
42
- console.log(' lua push skill - Push a skill directly');
43
- console.log(' lua push persona - Push a persona directly');
46
+ console.log(' lua push - Interactive selection');
47
+ console.log(' lua push skill - Push a skill directly');
48
+ console.log(' lua push persona - Push a persona directly');
49
+ console.log(' lua push webhook - Push a webhook directly');
50
+ console.log(' lua push job - Push a job directly');
51
+ console.log(' lua push preprocessor - Push a preprocessor directly');
52
+ console.log(' lua push postprocessor - Push a postprocessor directly');
44
53
  process.exit(1);
45
54
  }
46
55
  selectedType = type;
@@ -54,6 +63,10 @@ export async function pushCommand(type) {
54
63
  message: 'What would you like to push?',
55
64
  choices: [
56
65
  { name: '🛠️ Skill', value: 'skill' },
66
+ { name: '🪝 Webhook', value: 'webhook' },
67
+ { name: '⏰ Job', value: 'job' },
68
+ { name: '📥 PreProcessor', value: 'preprocessor' },
69
+ { name: '📤 PostProcessor', value: 'postprocessor' },
57
70
  { name: '🌙 Persona', value: 'persona' }
58
71
  ]
59
72
  }
@@ -68,6 +81,18 @@ export async function pushCommand(type) {
68
81
  if (selectedType === 'skill') {
69
82
  await pushSkillVersion();
70
83
  }
84
+ else if (selectedType === 'webhook') {
85
+ await pushWebhookVersion();
86
+ }
87
+ else if (selectedType === 'job') {
88
+ await pushJobVersion();
89
+ }
90
+ else if (selectedType === 'preprocessor') {
91
+ await pushPreProcessorVersion();
92
+ }
93
+ else if (selectedType === 'postprocessor') {
94
+ await pushPostProcessorVersion();
95
+ }
71
96
  else {
72
97
  await pushPersonaVersion();
73
98
  }
@@ -305,6 +330,662 @@ async function deployPersonaVersionAfterPush(apiKey, agentId, versionNum) {
305
330
  console.log('💡 You can deploy later using: lua persona\n');
306
331
  }
307
332
  }
333
+ /**
334
+ * Push webhook version to the server.
335
+ *
336
+ * Steps:
337
+ * 1. Run compilation
338
+ * 2. Validate config and deploy data
339
+ * 3. Select webhook to push
340
+ * 4. Confirm or update version
341
+ * 5. Push to server
342
+ * 6. Optionally deploy immediately
343
+ */
344
+ async function pushWebhookVersion() {
345
+ try {
346
+ // Step 1: Run compilation
347
+ writeProgress("📦 Compiling project...");
348
+ await compileCommand();
349
+ writeSuccess("✅ Compilation complete");
350
+ // Step 2: Authenticate
351
+ const apiKey = await loadApiKey();
352
+ if (!apiKey) {
353
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
354
+ process.exit(1);
355
+ }
356
+ await checkApiKey(apiKey);
357
+ writeSuccess("✅ Authentication verified");
358
+ // Step 3: Read configuration
359
+ const config = readSkillConfig();
360
+ if (!config?.agent?.agentId) {
361
+ console.error("❌ No agent ID found in lua.skill.yaml. Please run 'lua init' first.");
362
+ process.exit(1);
363
+ }
364
+ const webhooks = config.webhooks || [];
365
+ if (webhooks.length === 0) {
366
+ console.error("❌ No webhooks found in lua.skill.yaml.");
367
+ console.log("💡 Make sure you have created a webhook using LuaWebhook in your code.");
368
+ process.exit(1);
369
+ }
370
+ // Step 4: Select webhook to push
371
+ const webhookAnswer = await safePrompt([
372
+ {
373
+ type: 'list',
374
+ name: 'selectedWebhook',
375
+ message: 'Select a webhook to push:',
376
+ choices: webhooks.map((webhook) => ({
377
+ name: `${webhook.name} (v${webhook.version})`,
378
+ value: webhook
379
+ }))
380
+ }
381
+ ]);
382
+ if (!webhookAnswer) {
383
+ console.log("Push cancelled.");
384
+ return;
385
+ }
386
+ const selectedWebhook = webhookAnswer.selectedWebhook;
387
+ // Step 4.5: Load bundled webhook data
388
+ const bundledWebhooksPath = path.join(process.cwd(), 'dist', 'webhooks.json');
389
+ let bundledWebhookData = {};
390
+ if (fs.existsSync(bundledWebhooksPath)) {
391
+ const bundledWebhooks = JSON.parse(fs.readFileSync(bundledWebhooksPath, 'utf8'));
392
+ bundledWebhookData = bundledWebhooks.find((w) => w.name === selectedWebhook.name) || {};
393
+ // Validate that the webhook exists in compiled code
394
+ if (!bundledWebhookData || Object.keys(bundledWebhookData).length === 0) {
395
+ console.error(`\n❌ Webhook "${selectedWebhook.name}" not found in compiled code.`);
396
+ console.log("💡 This webhook may have been removed or commented out in your code.");
397
+ console.log("💡 Please uncomment the webhook or remove it from lua.skill.yaml.");
398
+ process.exit(1);
399
+ }
400
+ }
401
+ else {
402
+ console.error('❌ Bundled webhook data not found.');
403
+ console.log("💡 Please ensure your webhook code is properly compiled.");
404
+ process.exit(1);
405
+ }
406
+ // Step 5: Confirm or update version (same as skills)
407
+ const confirmedVersion = await promptVersionConfirmOrUpdate(selectedWebhook.version);
408
+ let versionToPush = confirmedVersion;
409
+ if (confirmedVersion !== selectedWebhook.version) {
410
+ writeInfo(`📝 Updating version from ${selectedWebhook.version} to ${confirmedVersion}`);
411
+ updateWebhookVersionInYaml(selectedWebhook.name, confirmedVersion);
412
+ versionToPush = confirmedVersion;
413
+ }
414
+ // Step 6: Prepare webhook data for push (include bundled data)
415
+ const webhookData = {
416
+ name: selectedWebhook.name,
417
+ version: versionToPush,
418
+ description: bundledWebhookData.description || selectedWebhook.description || `Webhook: ${selectedWebhook.name}`,
419
+ context: bundledWebhookData.context || selectedWebhook.context || '',
420
+ webhookId: selectedWebhook.webhookId,
421
+ querySchema: bundledWebhookData.querySchema,
422
+ headerSchema: bundledWebhookData.headerSchema,
423
+ bodySchema: bundledWebhookData.bodySchema,
424
+ code: bundledWebhookData.code, // Bundled and compressed code for execution
425
+ executeFunction: bundledWebhookData.executeFunction // Raw function for display/editing
426
+ };
427
+ // Step 7: Push to server
428
+ writeProgress(`\n🚀 Pushing ${selectedWebhook.name} v${versionToPush} to server...`);
429
+ const response = await fetch(`${BASE_URLS.API}/developer/webhooks/${config.agent.agentId}/${selectedWebhook.webhookId}/version`, {
430
+ method: 'POST',
431
+ headers: {
432
+ 'Authorization': `Bearer ${apiKey}`,
433
+ 'Content-Type': 'application/json'
434
+ },
435
+ body: JSON.stringify(webhookData)
436
+ });
437
+ if (!response.ok) {
438
+ const errorText = await response.text();
439
+ console.error(`\n❌ Push Error: ${response.status} - ${errorText}\n`);
440
+ throw new Error(`HTTP error! status: ${response.status}`);
441
+ }
442
+ const result = await response.json();
443
+ writeSuccess(`\n✅ Successfully pushed ${selectedWebhook.name} v${versionToPush}\n`);
444
+ writeInfo(`📦 Webhook URL: ${BASE_URLS.WEBHOOK}/${config.agent.agentId}/${selectedWebhook.webhookId}`);
445
+ // Step 8: Ask if user wants to deploy now
446
+ const deployAnswer = await safePrompt([
447
+ {
448
+ type: 'confirm',
449
+ name: 'deployNow',
450
+ message: 'Would you like to deploy this webhook version to production now?',
451
+ default: false
452
+ }
453
+ ]);
454
+ if (deployAnswer && deployAnswer.deployNow) {
455
+ await deployWebhookVersionAfterPush(apiKey, config.agent.agentId, selectedWebhook, versionToPush);
456
+ }
457
+ else {
458
+ writeInfo("💡 You can deploy this version later using: lua webhooks production");
459
+ }
460
+ }
461
+ catch (error) {
462
+ console.error('❌ Error pushing webhook version:', error);
463
+ process.exit(1);
464
+ }
465
+ }
466
+ /**
467
+ * Deploy a webhook version immediately after pushing
468
+ */
469
+ async function deployWebhookVersionAfterPush(apiKey, agentId, selectedWebhook, pushedVersion) {
470
+ try {
471
+ // Show warning
472
+ console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
473
+ console.log("⚠️ This will affect ALL users immediately.\n");
474
+ const confirmAnswer = await safePrompt([
475
+ {
476
+ type: 'confirm',
477
+ name: 'confirm',
478
+ message: 'Are you absolutely sure you want to deploy?',
479
+ default: false
480
+ }
481
+ ]);
482
+ if (!confirmAnswer || !confirmAnswer.confirm) {
483
+ console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
484
+ return;
485
+ }
486
+ writeProgress("🔄 Publishing webhook version...");
487
+ const publishResponse = await fetch(`${BASE_URLS.API}/developer/webhooks/${agentId}/${selectedWebhook.webhookId}/${pushedVersion}/publish`, {
488
+ method: 'POST',
489
+ headers: {
490
+ 'Authorization': `Bearer ${apiKey}`,
491
+ 'Content-Type': 'application/json'
492
+ },
493
+ body: JSON.stringify({})
494
+ });
495
+ if (!publishResponse.ok) {
496
+ const errorText = await publishResponse.text();
497
+ console.error(`\n❌ Deploy Error: ${publishResponse.status} - ${errorText}\n`);
498
+ throw new Error(`HTTP error! status: ${publishResponse.status}`);
499
+ }
500
+ writeSuccess(`\n✅ Webhook ${selectedWebhook.name} v${pushedVersion} deployed successfully to production\n`);
501
+ writeInfo("💡 The new webhook version is now active for all users.");
502
+ }
503
+ catch (error) {
504
+ console.error('\n❌ Error deploying webhook version:', error);
505
+ console.log('💡 You can deploy later using: lua webhooks production\n');
506
+ }
507
+ }
508
+ /**
509
+ * Updates webhook version in lua.skill.yaml
510
+ */
511
+ function updateWebhookVersionInYaml(webhookName, newVersion) {
512
+ try {
513
+ const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
514
+ const yamlContent = fs.readFileSync(yamlPath, 'utf8');
515
+ const config = yaml.load(yamlContent);
516
+ if (config.webhooks) {
517
+ const webhook = config.webhooks.find((w) => w.name === webhookName);
518
+ if (webhook) {
519
+ webhook.version = newVersion;
520
+ fs.writeFileSync(yamlPath, yaml.dump(config, { indent: 2, lineWidth: 120, noRefs: true }));
521
+ }
522
+ }
523
+ }
524
+ catch (error) {
525
+ console.warn('⚠️ Could not update webhook version in YAML:', error);
526
+ }
527
+ }
528
+ /**
529
+ * Updates job version in lua.skill.yaml
530
+ */
531
+ function updateJobVersionInYaml(jobName, newVersion) {
532
+ try {
533
+ const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
534
+ const yamlContent = fs.readFileSync(yamlPath, 'utf8');
535
+ const config = yaml.load(yamlContent);
536
+ if (config.jobs) {
537
+ const job = config.jobs.find((j) => j.name === jobName);
538
+ if (job) {
539
+ job.version = newVersion;
540
+ fs.writeFileSync(yamlPath, yaml.dump(config, { indent: 2, lineWidth: 120, noRefs: true }));
541
+ }
542
+ }
543
+ }
544
+ catch (error) {
545
+ console.warn('⚠️ Could not update job version in YAML:', error);
546
+ }
547
+ }
548
+ /**
549
+ * Push job version to the server (simplified version)
550
+ */
551
+ async function pushJobVersion() {
552
+ try {
553
+ writeProgress("📦 Compiling project...");
554
+ await compileCommand();
555
+ writeSuccess("✅ Compilation complete");
556
+ const apiKey = await loadApiKey();
557
+ if (!apiKey) {
558
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
559
+ process.exit(1);
560
+ }
561
+ await checkApiKey(apiKey);
562
+ const config = readSkillConfig();
563
+ if (!config?.agent?.agentId) {
564
+ console.error("❌ No agent ID found in lua.skill.yaml.");
565
+ process.exit(1);
566
+ }
567
+ const jobs = config.jobs || [];
568
+ if (jobs.length === 0) {
569
+ console.error("❌ No jobs found in lua.skill.yaml.");
570
+ console.log("💡 Make sure you have created a job using LuaJob in your code.");
571
+ process.exit(1);
572
+ }
573
+ const jobAnswer = await safePrompt([
574
+ {
575
+ type: 'list',
576
+ name: 'selectedJob',
577
+ message: 'Select a job to push:',
578
+ choices: jobs.map((job) => ({
579
+ name: `${job.name} (v${job.version})`,
580
+ value: job
581
+ }))
582
+ }
583
+ ]);
584
+ if (!jobAnswer)
585
+ return;
586
+ const selectedJob = jobAnswer.selectedJob;
587
+ // Load bundled job data
588
+ const bundledJobsPath = path.join(process.cwd(), 'dist', 'jobs.json');
589
+ let bundledJobData = {};
590
+ if (fs.existsSync(bundledJobsPath)) {
591
+ const bundledJobs = JSON.parse(fs.readFileSync(bundledJobsPath, 'utf8'));
592
+ bundledJobData = bundledJobs.find((j) => j.name === selectedJob.name) || {};
593
+ // Validate that the job exists in compiled code
594
+ if (!bundledJobData || Object.keys(bundledJobData).length === 0) {
595
+ console.error(`\n❌ Job "${selectedJob.name}" not found in compiled code.`);
596
+ console.log("💡 This job may have been removed or commented out in your code.");
597
+ console.log("💡 Please uncomment the job or remove it from lua.skill.yaml.");
598
+ process.exit(1);
599
+ }
600
+ }
601
+ else {
602
+ console.error('❌ Bundled job data not found.');
603
+ console.log("💡 Please ensure your job code is properly compiled.");
604
+ process.exit(1);
605
+ }
606
+ // Confirm or update version (same as skills and webhooks)
607
+ const confirmedVersion = await promptVersionConfirmOrUpdate(selectedJob.version);
608
+ let versionToPush = confirmedVersion;
609
+ if (confirmedVersion !== selectedJob.version) {
610
+ writeInfo(`📝 Updating version from ${selectedJob.version} to ${confirmedVersion}`);
611
+ updateJobVersionInYaml(selectedJob.name, confirmedVersion);
612
+ versionToPush = confirmedVersion;
613
+ }
614
+ const jobData = {
615
+ name: selectedJob.name,
616
+ version: versionToPush,
617
+ description: bundledJobData.description || selectedJob.description || `Job: ${selectedJob.name}`,
618
+ context: bundledJobData.context || selectedJob.context || '',
619
+ jobId: selectedJob.jobId,
620
+ schedule: bundledJobData.schedule || selectedJob.schedule,
621
+ timeout: bundledJobData.timeout,
622
+ retry: bundledJobData.retry,
623
+ code: bundledJobData.code, // Bundled and compressed code for execution
624
+ executeFunction: bundledJobData.executeFunction, // Raw function for display/editing
625
+ metadata: bundledJobData.metadata || selectedJob.metadata // Optional metadata
626
+ };
627
+ writeProgress(`\n🚀 Pushing ${selectedJob.name} v${selectedJob.version} to server...`);
628
+ const response = await fetch(`${BASE_URLS.API}/developer/jobs/${config.agent.agentId}/${selectedJob.jobId}/version`, {
629
+ method: 'POST',
630
+ headers: {
631
+ 'Authorization': `Bearer ${apiKey}`,
632
+ 'Content-Type': 'application/json'
633
+ },
634
+ body: JSON.stringify(jobData)
635
+ });
636
+ if (!response.ok) {
637
+ const errorText = await response.text();
638
+ console.error(`\n❌ Push Error: ${response.status} - ${errorText}\n`);
639
+ throw new Error(`HTTP error! status: ${response.status}`);
640
+ }
641
+ writeSuccess(`\n✅ Successfully pushed ${selectedJob.name} v${versionToPush}\n`);
642
+ // Ask if user wants to deploy now
643
+ const deployAnswer = await safePrompt([
644
+ {
645
+ type: 'confirm',
646
+ name: 'deployNow',
647
+ message: 'Would you like to deploy this job version to production now?',
648
+ default: false
649
+ }
650
+ ]);
651
+ if (deployAnswer && deployAnswer.deployNow) {
652
+ await deployJobVersionAfterPush(apiKey, config.agent.agentId, selectedJob, versionToPush);
653
+ }
654
+ else {
655
+ writeInfo("💡 You can deploy this version later using: lua jobs production");
656
+ }
657
+ }
658
+ catch (error) {
659
+ console.error('❌ Error pushing job version:', error);
660
+ process.exit(1);
661
+ }
662
+ }
663
+ /**
664
+ * Deploy a job version immediately after pushing
665
+ */
666
+ async function deployJobVersionAfterPush(apiKey, agentId, selectedJob, pushedVersion) {
667
+ try {
668
+ // Show warning
669
+ console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
670
+ console.log("⚠️ This will affect ALL users immediately.\n");
671
+ const confirmAnswer = await safePrompt([
672
+ {
673
+ type: 'confirm',
674
+ name: 'confirm',
675
+ message: 'Are you absolutely sure you want to deploy?',
676
+ default: false
677
+ }
678
+ ]);
679
+ if (!confirmAnswer || !confirmAnswer.confirm) {
680
+ console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
681
+ return;
682
+ }
683
+ writeProgress("🔄 Publishing job version...");
684
+ const publishResponse = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${selectedJob.jobId}/${pushedVersion}/publish`, {
685
+ method: 'POST',
686
+ headers: {
687
+ 'Authorization': `Bearer ${apiKey}`,
688
+ 'Content-Type': 'application/json'
689
+ },
690
+ body: JSON.stringify({})
691
+ });
692
+ if (!publishResponse.ok) {
693
+ const errorText = await publishResponse.text();
694
+ console.error(`\n❌ Deploy Error: ${publishResponse.status} - ${errorText}\n`);
695
+ throw new Error(`HTTP error! status: ${publishResponse.status}`);
696
+ }
697
+ writeSuccess(`\n✅ Job ${selectedJob.name} v${pushedVersion} deployed successfully to production\n`);
698
+ writeInfo("💡 The new job version is now active and will run on schedule.");
699
+ }
700
+ catch (error) {
701
+ console.error('\n❌ Error deploying job version:', error);
702
+ console.log('💡 You can deploy later using: lua jobs production\n');
703
+ }
704
+ }
705
+ /**
706
+ * Push preprocessor version to the server.
707
+ */
708
+ async function pushPreProcessorVersion() {
709
+ try {
710
+ writeProgress("📦 Compiling project...");
711
+ await compileCommand();
712
+ writeSuccess("✅ Compilation complete");
713
+ const apiKey = await loadApiKey();
714
+ if (!apiKey) {
715
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
716
+ process.exit(1);
717
+ }
718
+ await checkApiKey(apiKey);
719
+ const config = readSkillConfig();
720
+ if (!config?.agent?.agentId) {
721
+ console.error("❌ No agent ID found in lua.skill.yaml.");
722
+ process.exit(1);
723
+ }
724
+ const preprocessors = config.preprocessors || [];
725
+ if (preprocessors.length === 0) {
726
+ console.error("❌ No preprocessors found in lua.skill.yaml.");
727
+ process.exit(1);
728
+ }
729
+ // Load bundled preprocessor data
730
+ const preprocessorsPath = path.join(process.cwd(), 'dist', 'preprocessors.json');
731
+ let bundledData = {};
732
+ if (fs.existsSync(preprocessorsPath)) {
733
+ const bundled = JSON.parse(fs.readFileSync(preprocessorsPath, 'utf8'));
734
+ // Select preprocessor
735
+ const answer = await safePrompt([
736
+ {
737
+ type: 'list',
738
+ name: 'selected',
739
+ message: 'Select a preprocessor to push:',
740
+ choices: preprocessors.map((p) => ({
741
+ name: `${p.name} (v${p.version})`,
742
+ value: p
743
+ }))
744
+ }
745
+ ]);
746
+ if (!answer)
747
+ return;
748
+ const selected = answer.selected;
749
+ bundledData = bundled.find((p) => p.name === selected.name) || {};
750
+ if (!bundledData || !bundledData.code) {
751
+ console.error(`❌ PreProcessor "${selected.name}" not found in compiled code.`);
752
+ console.log("💡 Please uncomment the preprocessor or remove it from lua.skill.yaml.");
753
+ process.exit(1);
754
+ }
755
+ // Version confirmation
756
+ const confirmedVersion = await promptVersionConfirmOrUpdate(selected.version);
757
+ if (confirmedVersion !== selected.version) {
758
+ writeInfo(`📝 Updating version from ${selected.version} to ${confirmedVersion}`);
759
+ updateProcessorVersionInYaml('preprocessors', selected.name, confirmedVersion);
760
+ }
761
+ const versionData = {
762
+ name: selected.name,
763
+ version: confirmedVersion,
764
+ description: bundledData.description || selected.description,
765
+ context: bundledData.context || selected.context,
766
+ preprocessorId: selected.preprocessorId,
767
+ code: bundledData.code,
768
+ executeFunction: bundledData.executeFunction,
769
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
770
+ };
771
+ writeProgress(`\n🚀 Pushing ${selected.name} v${confirmedVersion}...`);
772
+ const api = new PreProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
773
+ const result = await api.pushPreProcessor(selected.preprocessorId, versionData);
774
+ if (result.success) {
775
+ writeSuccess(`\n✅ PreProcessor "${selected.name}" v${confirmedVersion} pushed successfully\n`);
776
+ // Ask if user wants to deploy now
777
+ const deployAnswer = await safePrompt([
778
+ {
779
+ type: 'confirm',
780
+ name: 'deployNow',
781
+ message: 'Would you like to deploy this preprocessor version to production now?',
782
+ default: false
783
+ }
784
+ ]);
785
+ if (deployAnswer && deployAnswer.deployNow) {
786
+ await deployPreProcessorVersionAfterPush(apiKey, config.agent.agentId, selected, confirmedVersion);
787
+ }
788
+ else {
789
+ writeInfo("💡 You can deploy this version later using: lua preprocessors production");
790
+ }
791
+ }
792
+ else {
793
+ console.error(`❌ Failed to push: ${result.error?.message}`);
794
+ }
795
+ }
796
+ }
797
+ catch (error) {
798
+ console.error('❌ Error pushing preprocessor:', error);
799
+ process.exit(1);
800
+ }
801
+ }
802
+ /**
803
+ * Deploy a preprocessor version immediately after pushing
804
+ */
805
+ async function deployPreProcessorVersionAfterPush(apiKey, agentId, selected, pushedVersion) {
806
+ try {
807
+ // Show warning
808
+ console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
809
+ console.log("⚠️ This will affect ALL users immediately.\n");
810
+ const confirmAnswer = await safePrompt([
811
+ {
812
+ type: 'confirm',
813
+ name: 'confirm',
814
+ message: 'Are you absolutely sure you want to deploy?',
815
+ default: false
816
+ }
817
+ ]);
818
+ if (!confirmAnswer || !confirmAnswer.confirm) {
819
+ console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
820
+ return;
821
+ }
822
+ writeProgress("🔄 Publishing preprocessor version...");
823
+ const api = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
824
+ const publishResponse = await api.publishPreProcessorVersion(selected.preprocessorId, pushedVersion);
825
+ if (!publishResponse.success) {
826
+ console.error(`\n❌ Deploy Error: ${publishResponse.error?.message || 'Unknown error'}\n`);
827
+ throw new Error(publishResponse.error?.message || 'Failed to publish preprocessor version');
828
+ }
829
+ writeSuccess(`\n✅ PreProcessor ${selected.name} v${pushedVersion} deployed successfully to production\n`);
830
+ writeInfo("💡 The new preprocessor version is now active for all users.");
831
+ }
832
+ catch (error) {
833
+ console.error('\n❌ Error deploying preprocessor version:', error);
834
+ console.log('💡 You can deploy later using: lua preprocessors production\n');
835
+ }
836
+ }
837
+ /**
838
+ * Push postprocessor version to the server.
839
+ */
840
+ async function pushPostProcessorVersion() {
841
+ try {
842
+ writeProgress("📦 Compiling project...");
843
+ await compileCommand();
844
+ writeSuccess("✅ Compilation complete");
845
+ const apiKey = await loadApiKey();
846
+ if (!apiKey) {
847
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
848
+ process.exit(1);
849
+ }
850
+ await checkApiKey(apiKey);
851
+ const config = readSkillConfig();
852
+ if (!config?.agent?.agentId) {
853
+ console.error("❌ No agent ID found in lua.skill.yaml.");
854
+ process.exit(1);
855
+ }
856
+ const postprocessors = config.postprocessors || [];
857
+ if (postprocessors.length === 0) {
858
+ console.error("❌ No postprocessors found in lua.skill.yaml.");
859
+ process.exit(1);
860
+ }
861
+ // Load bundled postprocessor data
862
+ const postprocessorsPath = path.join(process.cwd(), 'dist', 'postprocessors.json');
863
+ let bundledData = {};
864
+ if (fs.existsSync(postprocessorsPath)) {
865
+ const bundled = JSON.parse(fs.readFileSync(postprocessorsPath, 'utf8'));
866
+ // Select postprocessor
867
+ const answer = await safePrompt([
868
+ {
869
+ type: 'list',
870
+ name: 'selected',
871
+ message: 'Select a postprocessor to push:',
872
+ choices: postprocessors.map((p) => ({
873
+ name: `${p.name} (v${p.version})`,
874
+ value: p
875
+ }))
876
+ }
877
+ ]);
878
+ if (!answer)
879
+ return;
880
+ const selected = answer.selected;
881
+ bundledData = bundled.find((p) => p.name === selected.name) || {};
882
+ if (!bundledData || !bundledData.code) {
883
+ console.error(`❌ PostProcessor "${selected.name}" not found in compiled code.`);
884
+ console.log("💡 Please uncomment the postprocessor or remove it from lua.skill.yaml.");
885
+ process.exit(1);
886
+ }
887
+ // Version confirmation
888
+ const confirmedVersion = await promptVersionConfirmOrUpdate(selected.version);
889
+ if (confirmedVersion !== selected.version) {
890
+ writeInfo(`📝 Updating version from ${selected.version} to ${confirmedVersion}`);
891
+ updateProcessorVersionInYaml('postprocessors', selected.name, confirmedVersion);
892
+ }
893
+ const versionData = {
894
+ name: selected.name,
895
+ version: confirmedVersion,
896
+ description: bundledData.description || selected.description,
897
+ context: bundledData.context || selected.context,
898
+ postprocessorId: selected.postprocessorId,
899
+ code: bundledData.code,
900
+ executeFunction: bundledData.executeFunction,
901
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
902
+ };
903
+ writeProgress(`\n🚀 Pushing ${selected.name} v${confirmedVersion}...`);
904
+ const api = new PostProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
905
+ const result = await api.pushPostProcessor(selected.postprocessorId, versionData);
906
+ if (result.success) {
907
+ writeSuccess(`\n✅ PostProcessor "${selected.name}" v${confirmedVersion} pushed successfully\n`);
908
+ // Ask if user wants to deploy now
909
+ const deployAnswer = await safePrompt([
910
+ {
911
+ type: 'confirm',
912
+ name: 'deployNow',
913
+ message: 'Would you like to deploy this postprocessor version to production now?',
914
+ default: false
915
+ }
916
+ ]);
917
+ if (deployAnswer && deployAnswer.deployNow) {
918
+ await deployPostProcessorVersionAfterPush(apiKey, config.agent.agentId, selected, confirmedVersion);
919
+ }
920
+ else {
921
+ writeInfo("💡 You can deploy this version later using: lua postprocessors production");
922
+ }
923
+ }
924
+ else {
925
+ console.error(`❌ Failed to push: ${result.error?.message}`);
926
+ }
927
+ }
928
+ }
929
+ catch (error) {
930
+ console.error('❌ Error pushing postprocessor:', error);
931
+ process.exit(1);
932
+ }
933
+ }
934
+ /**
935
+ * Deploy a postprocessor version immediately after pushing
936
+ */
937
+ async function deployPostProcessorVersionAfterPush(apiKey, agentId, selected, pushedVersion) {
938
+ try {
939
+ // Show warning
940
+ console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
941
+ console.log("⚠️ This will affect ALL users immediately.\n");
942
+ const confirmAnswer = await safePrompt([
943
+ {
944
+ type: 'confirm',
945
+ name: 'confirm',
946
+ message: 'Are you absolutely sure you want to deploy?',
947
+ default: false
948
+ }
949
+ ]);
950
+ if (!confirmAnswer || !confirmAnswer.confirm) {
951
+ console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
952
+ return;
953
+ }
954
+ writeProgress("🔄 Publishing postprocessor version...");
955
+ const api = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
956
+ const publishResponse = await api.publishPostProcessorVersion(selected.postprocessorId, pushedVersion);
957
+ if (!publishResponse.success) {
958
+ console.error(`\n❌ Deploy Error: ${publishResponse.error?.message || 'Unknown error'}\n`);
959
+ throw new Error(publishResponse.error?.message || 'Failed to publish postprocessor version');
960
+ }
961
+ writeSuccess(`\n✅ PostProcessor ${selected.name} v${pushedVersion} deployed successfully to production\n`);
962
+ writeInfo("💡 The new postprocessor version is now active for all users.");
963
+ }
964
+ catch (error) {
965
+ console.error('\n❌ Error deploying postprocessor version:', error);
966
+ console.log('💡 You can deploy later using: lua postprocessors production\n');
967
+ }
968
+ }
969
+ /**
970
+ * Updates processor version in lua.skill.yaml
971
+ */
972
+ function updateProcessorVersionInYaml(processorType, processorName, newVersion) {
973
+ try {
974
+ const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
975
+ const yamlContent = fs.readFileSync(yamlPath, 'utf8');
976
+ const config = yaml.load(yamlContent);
977
+ if (config[processorType]) {
978
+ const processor = config[processorType].find((p) => p.name === processorName);
979
+ if (processor) {
980
+ processor.version = newVersion;
981
+ fs.writeFileSync(yamlPath, yaml.dump(config, { indent: 2, lineWidth: 120, noRefs: true }));
982
+ }
983
+ }
984
+ }
985
+ catch (error) {
986
+ console.warn('⚠️ Could not update processor version in YAML:', error);
987
+ }
988
+ }
308
989
  /**
309
990
  * Deploy a version immediately after pushing
310
991
  */