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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/api/chat.api.service.d.ts +8 -0
  2. package/dist/api/chat.api.service.js +50 -0
  3. package/dist/api/job.api.service.d.ts +16 -7
  4. package/dist/api/job.api.service.js +21 -5
  5. package/dist/api/postprocessor.api.service.d.ts +61 -1
  6. package/dist/api/postprocessor.api.service.js +35 -0
  7. package/dist/api/preprocessor.api.service.d.ts +61 -1
  8. package/dist/api/preprocessor.api.service.js +35 -0
  9. package/dist/api-exports.d.ts +26 -6
  10. package/dist/api-exports.js +42 -29
  11. package/dist/cli/command-definitions.js +13 -6
  12. package/dist/commands/chat.js +73 -36
  13. package/dist/commands/compile.js +16 -2
  14. package/dist/commands/dev.js +23 -2
  15. package/dist/commands/push.d.ts +3 -2
  16. package/dist/commands/push.js +536 -6
  17. package/dist/commands/test.js +18 -2
  18. package/dist/common/job.instance.d.ts +3 -0
  19. package/dist/common/job.instance.js +8 -0
  20. package/dist/config/constants.d.ts +6 -5
  21. package/dist/config/constants.js +12 -10
  22. package/dist/interfaces/chat.d.ts +30 -1
  23. package/dist/interfaces/jobs.d.ts +21 -0
  24. package/dist/services/auth.d.ts +8 -2
  25. package/dist/services/auth.js +35 -3
  26. package/dist/types/skill.d.ts +75 -56
  27. package/dist/types/skill.js +53 -59
  28. package/dist/utils/bundling.d.ts +13 -4
  29. package/dist/utils/bundling.js +83 -26
  30. package/dist/utils/compile.js +27 -6
  31. package/dist/utils/dev-api.d.ts +42 -2
  32. package/dist/utils/dev-api.js +177 -4
  33. package/dist/utils/dev-server.d.ts +1 -1
  34. package/dist/utils/dev-server.js +4 -4
  35. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  36. package/dist/utils/dynamic-job-bundler.js +143 -0
  37. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  38. package/dist/utils/pre-bundle-jobs.js +176 -0
  39. package/dist/utils/sandbox-storage.d.ts +48 -0
  40. package/dist/utils/sandbox-storage.js +114 -0
  41. package/dist/utils/sandbox.d.ts +2 -2
  42. package/dist/utils/sandbox.js +23 -7
  43. package/package.json +1 -1
  44. package/template/env.example +5 -0
  45. package/template/lua.skill.yaml +47 -0
  46. package/template/package-lock.json +10505 -0
  47. package/template/package.json +2 -1
  48. package/template/src/index.ts +65 -3
  49. package/template/src/tools/CreateInlineJob.ts +42 -0
  50. package/API_REFERENCE.md +0 -1408
  51. package/CHANGELOG.md +0 -236
  52. package/CLI_REFERENCE.md +0 -908
  53. package/GETTING_STARTED.md +0 -1040
  54. package/INSTANCE_TYPES.md +0 -1158
  55. package/README.md +0 -865
  56. package/TEMPLATE_GUIDE.md +0 -1398
  57. package/USER_DATA_INSTANCE.md +0 -621
  58. package/template/AGENT_CONFIGURATION.md +0 -251
  59. package/template/COMPLEX_JOB_EXAMPLES.md +0 -795
  60. package/template/DYNAMIC_JOB_CREATION.md +0 -371
  61. package/template/TOOL_EXAMPLES.md +0 -655
  62. package/template/WEBHOOKS_JOBS_QUICKSTART.md +0 -318
  63. package/template/WEBHOOK_JOB_EXAMPLES.md +0 -817
  64. package/template/src/index-agent-example.ts +0 -201
  65. package/template/src/postprocessors/ResponseFormatter.ts +0 -151
  66. package/template/src/preprocessors/MessageFilter.ts +0 -91
@@ -31,17 +31,34 @@ import PostProcessorApi from '../api/postprocessor.api.service.js';
31
31
  *
32
32
  * Note: This does NOT deploy to production. Use `lua deploy` for that.
33
33
  *
34
- * @param type - Optional type argument ('skill' or 'persona')
34
+ * @param type - Optional type argument ('skill', 'persona', 'webhook', 'job', 'preprocessor', 'postprocessor', or 'all')
35
+ * @param cmdObj - Commander command object with options
35
36
  * @returns Promise that resolves when push completes
36
37
  */
37
- export async function pushCommand(type) {
38
+ export async function pushCommand(type, cmdObj) {
38
39
  return withErrorHandling(async () => {
40
+ // Extract options from Commander command object
41
+ const options = {
42
+ force: cmdObj?.force || false,
43
+ autoDeploy: cmdObj?.autoDeploy || false
44
+ };
39
45
  let selectedType;
46
+ // Handle 'all' type with force flag
47
+ if (type === 'all') {
48
+ if (!options.force) {
49
+ console.error('āŒ The "all" type requires the --force flag');
50
+ console.log('\nUsage:');
51
+ console.log(' lua push all --force Push all components without prompts');
52
+ console.log(' lua push all --force --auto-deploy Push and deploy all to production');
53
+ process.exit(1);
54
+ }
55
+ return await pushAllCommand(options);
56
+ }
40
57
  // Step 1: Check if type was provided as argument
41
58
  if (type) {
42
59
  // Validate the provided type
43
60
  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".`);
61
+ console.error(`āŒ Invalid type: "${type}". Must be "skill", "persona", "webhook", "job", "preprocessor", "postprocessor", or "all".`);
45
62
  console.log('\nUsage:');
46
63
  console.log(' lua push - Interactive selection');
47
64
  console.log(' lua push skill - Push a skill directly');
@@ -50,6 +67,7 @@ export async function pushCommand(type) {
50
67
  console.log(' lua push job - Push a job directly');
51
68
  console.log(' lua push preprocessor - Push a preprocessor directly');
52
69
  console.log(' lua push postprocessor - Push a postprocessor directly');
70
+ console.log(' lua push all --force - Push all components without prompts');
53
71
  process.exit(1);
54
72
  }
55
73
  selectedType = type;
@@ -441,7 +459,7 @@ async function pushWebhookVersion() {
441
459
  }
442
460
  const result = await response.json();
443
461
  writeSuccess(`\nāœ… Successfully pushed ${selectedWebhook.name} v${versionToPush}\n`);
444
- writeInfo(`šŸ“¦ Webhook URL: ${BASE_URLS.API}/webhooks/${config.agent.agentId}/${selectedWebhook.webhookId}`);
462
+ writeInfo(`šŸ“¦ Webhook URL: ${BASE_URLS.WEBHOOK}/${config.agent.agentId}/${selectedWebhook.webhookId}`);
445
463
  // Step 8: Ask if user wants to deploy now
446
464
  const deployAnswer = await safePrompt([
447
465
  {
@@ -765,7 +783,8 @@ async function pushPreProcessorVersion() {
765
783
  context: bundledData.context || selected.context,
766
784
  preprocessorId: selected.preprocessorId,
767
785
  code: bundledData.code,
768
- executeFunction: bundledData.executeFunction
786
+ executeFunction: bundledData.executeFunction,
787
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
769
788
  };
770
789
  writeProgress(`\nšŸš€ Pushing ${selected.name} v${confirmedVersion}...`);
771
790
  const api = new PreProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
@@ -896,7 +915,8 @@ async function pushPostProcessorVersion() {
896
915
  context: bundledData.context || selected.context,
897
916
  postprocessorId: selected.postprocessorId,
898
917
  code: bundledData.code,
899
- executeFunction: bundledData.executeFunction
918
+ executeFunction: bundledData.executeFunction,
919
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
900
920
  };
901
921
  writeProgress(`\nšŸš€ Pushing ${selected.name} v${confirmedVersion}...`);
902
922
  const api = new PostProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
@@ -1029,3 +1049,513 @@ async function deployVersionAfterPush(apiKey, agentId, selectedSkill, pushedVers
1029
1049
  console.log('šŸ’” You can deploy later using: lua deploy\n');
1030
1050
  }
1031
1051
  }
1052
+ /**
1053
+ * Push all command - Pushes all components (skills, webhooks, jobs, processors) without prompts
1054
+ *
1055
+ * This command:
1056
+ * 1. Compiles the project
1057
+ * 2. Reads lua.skill.yaml to get all components
1058
+ * 3. Auto-bumps patch versions
1059
+ * 4. Pushes all components
1060
+ * 5. Optionally auto-deploys to production
1061
+ *
1062
+ * @param options - Command options (force is required, autoDeploy is optional)
1063
+ */
1064
+ async function pushAllCommand(options) {
1065
+ writeProgress("šŸš€ Push All - Pushing all components to server...\n");
1066
+ if (options.autoDeploy) {
1067
+ writeInfo("šŸš€ Auto-deploy to production is ENABLED\n");
1068
+ }
1069
+ // Step 1: Compile first
1070
+ writeProgress("šŸ“¦ Compiling project...");
1071
+ await compileCommand();
1072
+ // Step 2: Load configuration and API key
1073
+ const config = readSkillConfig();
1074
+ if (!config?.agent?.agentId) {
1075
+ console.error('āŒ No agent ID found in lua.skill.yaml. Run "lua init" first.');
1076
+ process.exit(1);
1077
+ }
1078
+ const apiKey = await loadApiKey();
1079
+ if (!apiKey) {
1080
+ console.error('āŒ No API key found. Run "lua auth configure" first.');
1081
+ process.exit(1);
1082
+ }
1083
+ const agentId = config.agent.agentId; // Validated above, safe to assert
1084
+ // Step 3: Read deploy.json for component data
1085
+ const deployJsonPath = path.join(process.cwd(), '.lua', 'deploy.json');
1086
+ if (!fs.existsSync(deployJsonPath)) {
1087
+ console.error('āŒ No deploy.json found. Compilation may have failed.');
1088
+ process.exit(1);
1089
+ }
1090
+ const deployData = JSON.parse(fs.readFileSync(deployJsonPath, 'utf8'));
1091
+ // Step 3b: Read bundled webhooks and jobs from dist/
1092
+ const webhooksJsonPath = path.join(process.cwd(), 'dist', 'webhooks.json');
1093
+ const jobsJsonPath = path.join(process.cwd(), 'dist', 'jobs.json');
1094
+ const preprocessorsJsonPath = path.join(process.cwd(), 'dist', 'preprocessors.json');
1095
+ const postprocessorsJsonPath = path.join(process.cwd(), 'dist', 'postprocessors.json');
1096
+ const bundledWebhooks = fs.existsSync(webhooksJsonPath)
1097
+ ? JSON.parse(fs.readFileSync(webhooksJsonPath, 'utf8'))
1098
+ : [];
1099
+ const bundledJobs = fs.existsSync(jobsJsonPath)
1100
+ ? JSON.parse(fs.readFileSync(jobsJsonPath, 'utf8'))
1101
+ : [];
1102
+ const bundledPreprocessors = fs.existsSync(preprocessorsJsonPath)
1103
+ ? JSON.parse(fs.readFileSync(preprocessorsJsonPath, 'utf8'))
1104
+ : [];
1105
+ const bundledPostprocessors = fs.existsSync(postprocessorsJsonPath)
1106
+ ? JSON.parse(fs.readFileSync(postprocessorsJsonPath, 'utf8'))
1107
+ : [];
1108
+ // Track results for both push and deploy
1109
+ const results = {
1110
+ skills: [],
1111
+ webhooks: [],
1112
+ jobs: [],
1113
+ preprocessors: [],
1114
+ postprocessors: []
1115
+ };
1116
+ // Track what needs to be deployed
1117
+ const toDeploySkills = [];
1118
+ const toDeployWebhooks = [];
1119
+ const toDeployJobs = [];
1120
+ const toDeployPreprocessors = [];
1121
+ const toDeployPostprocessors = [];
1122
+ // Step 4: Push all skills
1123
+ if (config.skills && config.skills.length > 0) {
1124
+ writeProgress(`\nšŸ“¦ Pushing ${config.skills.length} skill(s)...`);
1125
+ for (const skillConfig of config.skills) {
1126
+ try {
1127
+ const skillData = deployData.skills.find((s) => s.name === skillConfig.name);
1128
+ if (!skillData) {
1129
+ console.warn(`āš ļø Skill "${skillConfig.name}" not found in deploy.json, skipping`);
1130
+ continue;
1131
+ }
1132
+ // Validate skillId and version exist
1133
+ const skillId = skillConfig.skillId;
1134
+ const currentVersion = skillConfig.version;
1135
+ if (!skillId) {
1136
+ console.warn(`āš ļø Skill "${skillConfig.name}" has no skillId, skipping`);
1137
+ continue;
1138
+ }
1139
+ if (!currentVersion) {
1140
+ console.warn(`āš ļø Skill "${skillConfig.name}" has no version, skipping`);
1141
+ continue;
1142
+ }
1143
+ // Auto-bump patch version
1144
+ const newVersion = bumpPatchVersion(currentVersion);
1145
+ writeInfo(` šŸ“ ${skillConfig.name}: ${currentVersion} → ${newVersion}`);
1146
+ // Push version - use the full skillData with tools
1147
+ const pushResult = await pushVersion(apiKey, agentId, skillId, {
1148
+ ...skillData, // Include all fields from deploy.json (tools, name, etc.)
1149
+ version: newVersion, // Override with new version
1150
+ });
1151
+ if (!pushResult.success) {
1152
+ console.error(` āŒ Failed to push ${skillConfig.name}:`, pushResult.error?.message);
1153
+ continue;
1154
+ }
1155
+ // Update YAML with new version
1156
+ updateSkillVersionInYaml(skillConfig.name, newVersion);
1157
+ results.skills.push({ name: skillConfig.name, version: newVersion, skillId });
1158
+ writeSuccess(` āœ… ${skillConfig.name} v${newVersion} pushed`);
1159
+ // Queue for deployment if requested
1160
+ if (options.autoDeploy) {
1161
+ toDeploySkills.push({ skillId, version: newVersion, name: skillConfig.name });
1162
+ }
1163
+ }
1164
+ catch (error) {
1165
+ console.error(` āŒ Failed to push ${skillConfig.name}:`, error.message);
1166
+ }
1167
+ }
1168
+ }
1169
+ // Step 5: Push all webhooks
1170
+ if (config.webhooks && config.webhooks.length > 0) {
1171
+ writeProgress(`\nšŸŖ Pushing ${config.webhooks.length} webhook(s)...`);
1172
+ for (const webhookConfig of config.webhooks) {
1173
+ try {
1174
+ const webhookData = bundledWebhooks.find((w) => w.name === webhookConfig.name);
1175
+ if (!webhookData) {
1176
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" not found in compiled data, skipping`);
1177
+ continue;
1178
+ }
1179
+ // Validate webhookId and version exist
1180
+ if (!webhookConfig.webhookId) {
1181
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" has no webhookId, skipping`);
1182
+ continue;
1183
+ }
1184
+ if (!webhookConfig.version) {
1185
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" has no version, skipping`);
1186
+ continue;
1187
+ }
1188
+ // Auto-bump patch version
1189
+ const newVersion = bumpPatchVersion(webhookConfig.version);
1190
+ writeInfo(` šŸ“ ${webhookConfig.name}: ${webhookConfig.version} → ${newVersion}`);
1191
+ // Prepare webhook data for push
1192
+ const pushData = {
1193
+ name: webhookConfig.name,
1194
+ version: newVersion,
1195
+ description: webhookData.description || webhookConfig.description || '',
1196
+ context: webhookData.context || webhookConfig.context || '',
1197
+ webhookId: webhookConfig.webhookId,
1198
+ querySchema: webhookData.querySchema,
1199
+ headerSchema: webhookData.headerSchema,
1200
+ bodySchema: webhookData.bodySchema,
1201
+ code: webhookData.code,
1202
+ executeFunction: webhookData.executeFunction
1203
+ };
1204
+ // Push version using fetch (like existing webhook push)
1205
+ const response = await fetch(`${BASE_URLS.API}/developer/webhooks/${agentId}/${webhookConfig.webhookId}/version`, {
1206
+ method: 'POST',
1207
+ headers: {
1208
+ 'Authorization': `Bearer ${apiKey}`,
1209
+ 'Content-Type': 'application/json'
1210
+ },
1211
+ body: JSON.stringify(pushData)
1212
+ });
1213
+ if (!response.ok) {
1214
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
1215
+ }
1216
+ // Update YAML
1217
+ updateWebhookVersionInYaml(webhookConfig.name, newVersion);
1218
+ results.webhooks.push({ name: webhookConfig.name, version: newVersion });
1219
+ writeSuccess(` āœ… ${webhookConfig.name} v${newVersion} pushed`);
1220
+ // Queue for deployment if requested
1221
+ if (options.autoDeploy) {
1222
+ toDeployWebhooks.push({ webhookId: webhookConfig.webhookId, version: newVersion, name: webhookConfig.name });
1223
+ }
1224
+ }
1225
+ catch (error) {
1226
+ console.error(` āŒ Failed to push ${webhookConfig.name}:`, error.message);
1227
+ }
1228
+ }
1229
+ }
1230
+ // Step 6: Push all jobs
1231
+ if (config.jobs && config.jobs.length > 0) {
1232
+ writeProgress(`\nā° Pushing ${config.jobs.length} job(s)...`);
1233
+ for (const jobConfig of config.jobs) {
1234
+ try {
1235
+ const jobData = bundledJobs.find((j) => j.name === jobConfig.name);
1236
+ if (!jobData) {
1237
+ console.warn(`āš ļø Job "${jobConfig.name}" not found in compiled data, skipping`);
1238
+ continue;
1239
+ }
1240
+ // Validate jobId and version exist
1241
+ if (!jobConfig.jobId) {
1242
+ console.warn(`āš ļø Job "${jobConfig.name}" has no jobId, skipping`);
1243
+ continue;
1244
+ }
1245
+ if (!jobConfig.version) {
1246
+ console.warn(`āš ļø Job "${jobConfig.name}" has no version, skipping`);
1247
+ continue;
1248
+ }
1249
+ // Auto-bump patch version
1250
+ const newVersion = bumpPatchVersion(jobConfig.version);
1251
+ writeInfo(` šŸ“ ${jobConfig.name}: ${jobConfig.version} → ${newVersion}`);
1252
+ // Prepare job data for push
1253
+ const pushData = {
1254
+ name: jobConfig.name,
1255
+ version: newVersion,
1256
+ description: jobData.description || jobConfig.description || '',
1257
+ context: jobData.context || jobConfig.context || '',
1258
+ jobId: jobConfig.jobId,
1259
+ schedule: jobData.schedule || jobConfig.schedule,
1260
+ timeout: jobData.timeout,
1261
+ retry: jobData.retry,
1262
+ code: jobData.code,
1263
+ executeFunction: jobData.executeFunction,
1264
+ metadata: jobData.metadata || jobConfig.metadata
1265
+ };
1266
+ // Push version using fetch
1267
+ const response = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${jobConfig.jobId}/version`, {
1268
+ method: 'POST',
1269
+ headers: {
1270
+ 'Authorization': `Bearer ${apiKey}`,
1271
+ 'Content-Type': 'application/json'
1272
+ },
1273
+ body: JSON.stringify(pushData)
1274
+ });
1275
+ if (!response.ok) {
1276
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
1277
+ }
1278
+ // Update YAML
1279
+ updateJobVersionInYaml(jobConfig.name, newVersion);
1280
+ results.jobs.push({ name: jobConfig.name, version: newVersion });
1281
+ writeSuccess(` āœ… ${jobConfig.name} v${newVersion} pushed`);
1282
+ // Queue for deployment if requested
1283
+ if (options.autoDeploy) {
1284
+ toDeployJobs.push({ jobId: jobConfig.jobId, version: newVersion, name: jobConfig.name });
1285
+ }
1286
+ }
1287
+ catch (error) {
1288
+ console.error(` āŒ Failed to push ${jobConfig.name}:`, error.message);
1289
+ }
1290
+ }
1291
+ }
1292
+ // Step 7: Push all preprocessors
1293
+ if (config.preprocessors && config.preprocessors.length > 0) {
1294
+ writeProgress(`\nšŸ“„ Pushing ${config.preprocessors.length} preprocessor(s)...`);
1295
+ const preprocessorService = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
1296
+ for (const processorConfig of config.preprocessors) {
1297
+ try {
1298
+ const processorData = bundledPreprocessors.find((p) => p.name === processorConfig.name);
1299
+ if (!processorData) {
1300
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" not found in compiled data, skipping`);
1301
+ continue;
1302
+ }
1303
+ // Validate preprocessorId and version exist
1304
+ const preprocessorId = processorConfig.preprocessorId;
1305
+ const currentVersion = processorConfig.version;
1306
+ if (!preprocessorId) {
1307
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" has no preprocessorId, skipping`);
1308
+ continue;
1309
+ }
1310
+ if (!currentVersion) {
1311
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" has no version, skipping`);
1312
+ continue;
1313
+ }
1314
+ // Auto-bump patch version
1315
+ const newVersion = bumpPatchVersion(currentVersion);
1316
+ writeInfo(` šŸ“ ${processorConfig.name}: ${currentVersion} → ${newVersion}`);
1317
+ // Prepare version data
1318
+ const versionData = {
1319
+ name: processorConfig.name,
1320
+ version: newVersion,
1321
+ description: processorData.description || processorConfig.description || '',
1322
+ context: processorData.context || processorConfig.context || '',
1323
+ preprocessorId: preprocessorId,
1324
+ code: processorData.code,
1325
+ executeFunction: processorData.executeFunction,
1326
+ async: Boolean(processorData.async ?? false)
1327
+ };
1328
+ // Push version
1329
+ const result = await preprocessorService.pushPreProcessor(preprocessorId, versionData);
1330
+ if (!result.success) {
1331
+ throw new Error(result.error?.message || 'Failed to push preprocessor');
1332
+ }
1333
+ // Update YAML
1334
+ updateProcessorVersionInYaml('preprocessors', processorConfig.name, newVersion);
1335
+ results.preprocessors.push({ name: processorConfig.name, version: newVersion });
1336
+ writeSuccess(` āœ… ${processorConfig.name} v${newVersion} pushed`);
1337
+ // Queue for deployment if requested
1338
+ if (options.autoDeploy) {
1339
+ toDeployPreprocessors.push({ preprocessorId, version: newVersion, name: processorConfig.name });
1340
+ }
1341
+ }
1342
+ catch (error) {
1343
+ console.error(` āŒ Failed to push ${processorConfig.name}:`, error.message);
1344
+ }
1345
+ }
1346
+ }
1347
+ // Step 8: Push all postprocessors
1348
+ if (config.postprocessors && config.postprocessors.length > 0) {
1349
+ writeProgress(`\nšŸ“¤ Pushing ${config.postprocessors.length} postprocessor(s)...`);
1350
+ const postprocessorService = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
1351
+ for (const processorConfig of config.postprocessors) {
1352
+ try {
1353
+ const processorData = bundledPostprocessors.find((p) => p.name === processorConfig.name);
1354
+ if (!processorData) {
1355
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" not found in compiled data, skipping`);
1356
+ continue;
1357
+ }
1358
+ // Validate postprocessorId and version exist
1359
+ const postprocessorId = processorConfig.postprocessorId;
1360
+ const currentVersion = processorConfig.version;
1361
+ if (!postprocessorId) {
1362
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" has no postprocessorId, skipping`);
1363
+ continue;
1364
+ }
1365
+ if (!currentVersion) {
1366
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" has no version, skipping`);
1367
+ continue;
1368
+ }
1369
+ // Auto-bump patch version
1370
+ const newVersion = bumpPatchVersion(currentVersion);
1371
+ writeInfo(` šŸ“ ${processorConfig.name}: ${currentVersion} → ${newVersion}`);
1372
+ // Prepare version data
1373
+ const versionData = {
1374
+ name: processorConfig.name,
1375
+ version: newVersion,
1376
+ description: processorData.description || processorConfig.description || '',
1377
+ context: processorData.context || processorConfig.context || '',
1378
+ postprocessorId: postprocessorId,
1379
+ code: processorData.code,
1380
+ executeFunction: processorData.executeFunction,
1381
+ async: Boolean(processorData.async ?? false)
1382
+ };
1383
+ // Push version
1384
+ const result = await postprocessorService.pushPostProcessor(postprocessorId, versionData);
1385
+ if (!result.success) {
1386
+ throw new Error(result.error?.message || 'Failed to push postprocessor');
1387
+ }
1388
+ // Update YAML
1389
+ updateProcessorVersionInYaml('postprocessors', processorConfig.name, newVersion);
1390
+ results.postprocessors.push({ name: processorConfig.name, version: newVersion });
1391
+ writeSuccess(` āœ… ${processorConfig.name} v${newVersion} pushed`);
1392
+ // Queue for deployment if requested
1393
+ if (options.autoDeploy) {
1394
+ toDeployPostprocessors.push({ postprocessorId, version: newVersion, name: processorConfig.name });
1395
+ }
1396
+ }
1397
+ catch (error) {
1398
+ console.error(` āŒ Failed to push ${processorConfig.name}:`, error.message);
1399
+ }
1400
+ }
1401
+ }
1402
+ // Step 9: Deploy all components if autoDeploy is enabled
1403
+ if (options.autoDeploy && (toDeploySkills.length > 0 || toDeployWebhooks.length > 0 || toDeployJobs.length > 0 || toDeployPreprocessors.length > 0 || toDeployPostprocessors.length > 0)) {
1404
+ writeProgress('\nšŸš€ Deploying all pushed versions to production...');
1405
+ writeInfo('ā±ļø Waiting for server to process versions (5 seconds)...\n');
1406
+ // Wait for server to process all pushed versions
1407
+ await new Promise(resolve => setTimeout(resolve, 5000));
1408
+ // Deploy all skills
1409
+ if (toDeploySkills.length > 0) {
1410
+ writeProgress(`šŸ“¦ Deploying ${toDeploySkills.length} skill(s)...`);
1411
+ for (const skill of toDeploySkills) {
1412
+ const deployed = await retryDeploy(() => publishVersion(apiKey, agentId, skill.skillId, skill.version), skill.name, skill.version, 2 // Only 2 retries since we already waited
1413
+ );
1414
+ if (deployed) {
1415
+ writeSuccess(` šŸš€ ${skill.name} v${skill.version} deployed`);
1416
+ }
1417
+ else {
1418
+ console.warn(` āš ļø ${skill.name} deployment failed`);
1419
+ }
1420
+ }
1421
+ }
1422
+ // Deploy all webhooks
1423
+ if (toDeployWebhooks.length > 0) {
1424
+ writeProgress(`šŸŖ Deploying ${toDeployWebhooks.length} webhook(s)...`);
1425
+ for (const webhook of toDeployWebhooks) {
1426
+ const deployed = await retryDeploy(async () => {
1427
+ const response = await fetch(`${BASE_URLS.API}/developer/webhooks/${agentId}/${webhook.webhookId}/${webhook.version}/publish`, {
1428
+ method: 'PUT',
1429
+ headers: {
1430
+ 'Authorization': `Bearer ${apiKey}`,
1431
+ 'Content-Type': 'application/json'
1432
+ }
1433
+ });
1434
+ if (!response.ok) {
1435
+ throw new Error(`HTTP ${response.status}`);
1436
+ }
1437
+ }, webhook.name, webhook.version, 2);
1438
+ if (deployed) {
1439
+ writeSuccess(` šŸš€ ${webhook.name} v${webhook.version} deployed`);
1440
+ }
1441
+ else {
1442
+ console.warn(` āš ļø ${webhook.name} deployment failed`);
1443
+ }
1444
+ }
1445
+ }
1446
+ // Deploy all jobs
1447
+ if (toDeployJobs.length > 0) {
1448
+ writeProgress(`ā° Deploying ${toDeployJobs.length} job(s)...`);
1449
+ for (const job of toDeployJobs) {
1450
+ const deployed = await retryDeploy(async () => {
1451
+ const response = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${job.jobId}/${job.version}/publish`, {
1452
+ method: 'PUT',
1453
+ headers: {
1454
+ 'Authorization': `Bearer ${apiKey}`,
1455
+ 'Content-Type': 'application/json'
1456
+ }
1457
+ });
1458
+ if (!response.ok) {
1459
+ throw new Error(`HTTP ${response.status}`);
1460
+ }
1461
+ }, job.name, job.version, 2);
1462
+ if (deployed) {
1463
+ writeSuccess(` šŸš€ ${job.name} v${job.version} deployed`);
1464
+ }
1465
+ else {
1466
+ console.warn(` āš ļø ${job.name} deployment failed`);
1467
+ }
1468
+ }
1469
+ }
1470
+ // Deploy all preprocessors
1471
+ if (toDeployPreprocessors.length > 0) {
1472
+ writeProgress(`šŸ“„ Deploying ${toDeployPreprocessors.length} preprocessor(s)...`);
1473
+ const preprocessorService = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
1474
+ for (const processor of toDeployPreprocessors) {
1475
+ const deployed = await retryDeploy(() => preprocessorService.publishPreProcessorVersion(processor.preprocessorId, processor.version), processor.name, processor.version, 2);
1476
+ if (deployed) {
1477
+ writeSuccess(` šŸš€ ${processor.name} v${processor.version} deployed`);
1478
+ }
1479
+ else {
1480
+ console.warn(` āš ļø ${processor.name} deployment failed`);
1481
+ }
1482
+ }
1483
+ }
1484
+ // Deploy all postprocessors
1485
+ if (toDeployPostprocessors.length > 0) {
1486
+ writeProgress(`šŸ“¤ Deploying ${toDeployPostprocessors.length} postprocessor(s)...`);
1487
+ const postprocessorService = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
1488
+ for (const processor of toDeployPostprocessors) {
1489
+ const deployed = await retryDeploy(() => postprocessorService.publishPostProcessorVersion(processor.postprocessorId, processor.version), processor.name, processor.version, 2);
1490
+ if (deployed) {
1491
+ writeSuccess(` šŸš€ ${processor.name} v${processor.version} deployed`);
1492
+ }
1493
+ else {
1494
+ console.warn(` āš ļø ${processor.name} deployment failed`);
1495
+ }
1496
+ }
1497
+ }
1498
+ }
1499
+ // Step 10: Print summary
1500
+ writeSuccess('\nāœ… Push All Complete!\n');
1501
+ if (results.skills.length > 0) {
1502
+ console.log(`šŸ› ļø Skills (${results.skills.length}):`);
1503
+ results.skills.forEach(s => console.log(` • ${s.name} v${s.version}`));
1504
+ }
1505
+ if (results.webhooks.length > 0) {
1506
+ console.log(`šŸŖ Webhooks (${results.webhooks.length}):`);
1507
+ results.webhooks.forEach(w => console.log(` • ${w.name} v${w.version}`));
1508
+ }
1509
+ if (results.jobs.length > 0) {
1510
+ console.log(`ā° Jobs (${results.jobs.length}):`);
1511
+ results.jobs.forEach(j => console.log(` • ${j.name} v${j.version}`));
1512
+ }
1513
+ if (results.preprocessors.length > 0) {
1514
+ console.log(`šŸ“„ PreProcessors (${results.preprocessors.length}):`);
1515
+ results.preprocessors.forEach(p => console.log(` • ${p.name} v${p.version}`));
1516
+ }
1517
+ if (results.postprocessors.length > 0) {
1518
+ console.log(`šŸ“¤ PostProcessors (${results.postprocessors.length}):`);
1519
+ results.postprocessors.forEach(p => console.log(` • ${p.name} v${p.version}`));
1520
+ }
1521
+ if (options.autoDeploy) {
1522
+ writeSuccess('\nšŸš€ All components deployed to production!');
1523
+ }
1524
+ console.log('');
1525
+ }
1526
+ /**
1527
+ * Bumps the patch version of a semantic version string
1528
+ * e.g., "1.2.3" -> "1.2.4"
1529
+ */
1530
+ function bumpPatchVersion(version) {
1531
+ const parts = version.split('.');
1532
+ if (parts.length !== 3) {
1533
+ // If not a valid semver, just return incremented version
1534
+ return version + '.1';
1535
+ }
1536
+ const [major, minor, patch] = parts;
1537
+ const newPatch = parseInt(patch, 10) + 1;
1538
+ return `${major}.${minor}.${newPatch}`;
1539
+ }
1540
+ /**
1541
+ * Retry deployment with exponential backoff
1542
+ * The server needs time to process pushed versions before they can be deployed
1543
+ */
1544
+ async function retryDeploy(deployFn, componentName, version, maxRetries = 3) {
1545
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1546
+ try {
1547
+ const delay = attempt * 2000; // 2s, 4s, 6s (longer delays)
1548
+ await new Promise(resolve => setTimeout(resolve, delay));
1549
+ await deployFn();
1550
+ return true;
1551
+ }
1552
+ catch (error) {
1553
+ if (attempt === maxRetries) {
1554
+ console.error(` [Retry ${attempt}/${maxRetries}] Deploy failed: ${error.message}`);
1555
+ return false;
1556
+ }
1557
+ // Continue to next retry silently
1558
+ }
1559
+ }
1560
+ return false;
1561
+ }
@@ -434,15 +434,31 @@ async function testPreProcessor() {
434
434
  process.env[key] = value;
435
435
  }
436
436
  try {
437
+ // Convert string message to ChatMessage array
438
+ const messages = [{ type: 'text', text: messageAnswer.message }];
437
439
  const result = await executePreProcessor({
438
440
  processorCode: preprocessorCode,
439
- message: messageAnswer.message,
441
+ messages: messages, // Pass array instead of string
440
442
  channel: channelAnswer.channel,
441
443
  apiKey,
442
444
  agentId
443
445
  });
444
446
  writeSuccess("\nāœ… PreProcessor execution successful!");
445
- console.log(`Processed message: ${result}`);
447
+ console.log(`\nProcessed messages (${result.length}):`);
448
+ result.forEach((msg, idx) => {
449
+ if (msg.type === 'text') {
450
+ console.log(` ${idx + 1}. [TEXT] ${msg.text}`);
451
+ }
452
+ else if (msg.type === 'image') {
453
+ console.log(` ${idx + 1}. [IMAGE] ${msg.mimeType}`);
454
+ }
455
+ else if (msg.type === 'file') {
456
+ console.log(` ${idx + 1}. [FILE] ${msg.mimeType}`);
457
+ }
458
+ else {
459
+ console.log(` ${idx + 1}. [${msg.type}]`, msg);
460
+ }
461
+ });
446
462
  }
447
463
  catch (error) {
448
464
  console.error("\nāŒ PreProcessor execution failed:");
@@ -3,6 +3,7 @@
3
3
  * Provides a convenient interface for interacting with a job
4
4
  */
5
5
  import JobApi from '../api/job.api.service.js';
6
+ import UserDataInstance from './user.instance.js';
6
7
  /**
7
8
  * Job Instance class.
8
9
  * Represents a single job with helper methods for common operations.
@@ -38,6 +39,7 @@ export declare class JobInstance {
38
39
  readonly jobId: string;
39
40
  readonly schedule: any;
40
41
  metadata: Record<string, any>;
42
+ private userApi;
41
43
  constructor(jobApi: JobApi, jobData: any);
42
44
  /**
43
45
  * Gets the full job data.
@@ -70,6 +72,7 @@ export declare class JobInstance {
70
72
  * ```
71
73
  */
72
74
  delete(): Promise<void>;
75
+ user(): Promise<UserDataInstance>;
73
76
  /**
74
77
  * Converts the job instance to JSON.
75
78
  */
@@ -2,6 +2,9 @@
2
2
  * Job Instance
3
3
  * Provides a convenient interface for interacting with a job
4
4
  */
5
+ import UserDataInstance from './user.instance.js';
6
+ import UserDataApi from '../api/user.data.api.service.js';
7
+ import { BASE_URLS } from '../config/constants.js';
5
8
  /**
6
9
  * Job Instance class.
7
10
  * Represents a single job with helper methods for common operations.
@@ -38,6 +41,7 @@ export class JobInstance {
38
41
  this.name = jobData.name;
39
42
  this.schedule = jobData.schedule;
40
43
  this.metadata = jobData.metadata || {};
44
+ this.userApi = new UserDataApi(BASE_URLS.API, jobApi.apiKey, jobApi.agentId);
41
45
  }
42
46
  /**
43
47
  * Gets the full job data.
@@ -92,6 +96,10 @@ export class JobInstance {
92
96
  console.warn(`Job "${this.name}" has versions and was deactivated instead of deleted.`);
93
97
  }
94
98
  }
99
+ async user() {
100
+ const result = await this.userApi.get();
101
+ return new UserDataInstance(this.userApi, result);
102
+ }
95
103
  /**
96
104
  * Converts the job instance to JSON.
97
105
  */