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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/api/job.api.service.d.ts +16 -7
  2. package/dist/api/job.api.service.js +21 -5
  3. package/dist/api/postprocessor.api.service.d.ts +61 -1
  4. package/dist/api/postprocessor.api.service.js +35 -0
  5. package/dist/api/preprocessor.api.service.d.ts +61 -1
  6. package/dist/api/preprocessor.api.service.js +35 -0
  7. package/dist/api-exports.d.ts +26 -6
  8. package/dist/api-exports.js +42 -29
  9. package/dist/cli/command-definitions.js +13 -6
  10. package/dist/commands/chat.js +32 -5
  11. package/dist/commands/compile.js +16 -2
  12. package/dist/commands/dev.js +23 -2
  13. package/dist/commands/push.d.ts +6 -2
  14. package/dist/commands/push.js +412 -6
  15. package/dist/commands/test.js +18 -2
  16. package/dist/common/job.instance.d.ts +3 -0
  17. package/dist/common/job.instance.js +8 -0
  18. package/dist/config/constants.d.ts +6 -5
  19. package/dist/config/constants.js +12 -10
  20. package/dist/interfaces/chat.d.ts +30 -1
  21. package/dist/interfaces/jobs.d.ts +21 -0
  22. package/dist/types/skill.d.ts +75 -56
  23. package/dist/types/skill.js +53 -59
  24. package/dist/utils/bundling.d.ts +13 -4
  25. package/dist/utils/bundling.js +83 -26
  26. package/dist/utils/compile.js +27 -6
  27. package/dist/utils/dev-api.d.ts +42 -2
  28. package/dist/utils/dev-api.js +177 -4
  29. package/dist/utils/dev-server.d.ts +1 -1
  30. package/dist/utils/dev-server.js +4 -4
  31. package/dist/utils/dynamic-job-bundler.d.ts +17 -0
  32. package/dist/utils/dynamic-job-bundler.js +143 -0
  33. package/dist/utils/pre-bundle-jobs.d.ts +26 -0
  34. package/dist/utils/pre-bundle-jobs.js +176 -0
  35. package/dist/utils/sandbox-storage.d.ts +48 -0
  36. package/dist/utils/sandbox-storage.js +114 -0
  37. package/dist/utils/sandbox.d.ts +2 -2
  38. package/dist/utils/sandbox.js +23 -7
  39. package/package.json +1 -1
  40. package/template/lua.skill.yaml +47 -0
  41. package/template/package-lock.json +10505 -0
  42. package/template/package.json +2 -1
  43. package/template/src/index.ts +65 -3
  44. package/template/src/tools/CreateInlineJob.ts +42 -0
  45. package/API_REFERENCE.md +0 -1408
  46. package/CHANGELOG.md +0 -236
  47. package/CLI_REFERENCE.md +0 -908
  48. package/GETTING_STARTED.md +0 -1040
  49. package/INSTANCE_TYPES.md +0 -1158
  50. package/README.md +0 -865
  51. package/TEMPLATE_GUIDE.md +0 -1398
  52. package/USER_DATA_INSTANCE.md +0 -621
  53. package/template/AGENT_CONFIGURATION.md +0 -251
  54. package/template/COMPLEX_JOB_EXAMPLES.md +0 -795
  55. package/template/DYNAMIC_JOB_CREATION.md +0 -371
  56. package/template/TOOL_EXAMPLES.md +0 -655
  57. package/template/WEBHOOKS_JOBS_QUICKSTART.md +0 -318
  58. package/template/WEBHOOK_JOB_EXAMPLES.md +0 -817
  59. package/template/src/index-agent-example.ts +0 -201
  60. package/template/src/postprocessors/ResponseFormatter.ts +0 -151
  61. package/template/src/preprocessors/MessageFilter.ts +0 -91
@@ -78,9 +78,23 @@ export async function compileCommand() {
78
78
  const tools = await detectTools(indexFile, project, skillFilePaths);
79
79
  writeProgress(`šŸ“¦ Found ${tools.length} tools to bundle...`);
80
80
  // Step 3: Bundle each tool and extract metadata
81
+ const { preBundleJobsInSource, replaceJobPlaceholders } = await import('../utils/pre-bundle-jobs.js');
81
82
  for (const tool of tools) {
82
- await bundleTool(tool, distDir);
83
- await extractExecuteCode(tool, project);
83
+ // Step 3a: Pre-bundle any Jobs.create() in the tool source
84
+ const { modifiedSource, jobBundles } = await preBundleJobsInSource(tool.filePath, project, distDir);
85
+ // Step 3b: Bundle the tool (with placeholders for job execute functions)
86
+ await bundleTool(tool, distDir, modifiedSource);
87
+ // Step 3c: Replace placeholders in the bundled tool file
88
+ if (jobBundles.size > 0) {
89
+ const toolBundlePath = path.join(distDir, 'tools', `${tool.className}.js`);
90
+ if (fs.existsSync(toolBundlePath)) {
91
+ let bundledToolCode = fs.readFileSync(toolBundlePath, 'utf8');
92
+ bundledToolCode = replaceJobPlaceholders(bundledToolCode, jobBundles);
93
+ fs.writeFileSync(toolBundlePath, bundledToolCode);
94
+ }
95
+ }
96
+ // Step 3d: Extract execute code
97
+ await extractExecuteCode(tool, project, distDir);
84
98
  }
85
99
  // Step 4: Bundle the main index file
86
100
  await bundleMainIndex(indexPath, distDir);
@@ -7,7 +7,7 @@ import { compileCommand } from './compile.js';
7
7
  import { checkApiKey, loadApiKey } from '../services/auth.js';
8
8
  import { readSkillConfig } from '../utils/files.js';
9
9
  import { withErrorHandling, writeProgress, writeSuccess } from '../utils/cli.js';
10
- import { pushSkillsToSandbox } from '../utils/dev-api.js';
10
+ import { pushSkillsToSandbox, pushProcessorsToSandbox } from '../utils/dev-api.js';
11
11
  import { createChatServer } from '../utils/dev-server.js';
12
12
  import { createFileWatcher } from '../utils/dev-watcher.js';
13
13
  import { readConfigVersion, readDeployJson, extractSkillId, validateConfig, validateDeployData, validateAgentConfig, } from '../utils/dev-helpers.js';
@@ -75,6 +75,26 @@ export async function devCommand() {
75
75
  process.exit(1);
76
76
  }
77
77
  writeSuccess(`āœ… Pushed ${Object.keys(sandboxIds).length} skills to sandbox`);
78
+ // Step 6b: Push preprocessors and postprocessors to sandbox
79
+ const fs = await import('fs');
80
+ const path = await import('path');
81
+ const preprocessorsPath = path.join(process.cwd(), 'dist', 'preprocessors.json');
82
+ const postprocessorsPath = path.join(process.cwd(), 'dist', 'postprocessors.json');
83
+ let bundledPreProcessors = [];
84
+ let bundledPostProcessors = [];
85
+ if (fs.existsSync(preprocessorsPath)) {
86
+ bundledPreProcessors = JSON.parse(fs.readFileSync(preprocessorsPath, 'utf8'));
87
+ }
88
+ if (fs.existsSync(postprocessorsPath)) {
89
+ bundledPostProcessors = JSON.parse(fs.readFileSync(postprocessorsPath, 'utf8'));
90
+ }
91
+ if (bundledPreProcessors.length > 0 || bundledPostProcessors.length > 0) {
92
+ writeProgress("šŸ”„ Pushing processors to sandbox...");
93
+ const processorCounts = await pushProcessorsToSandbox(apiKey, agentId, updatedConfig, bundledPreProcessors, bundledPostProcessors, true);
94
+ if (processorCounts.preprocessors > 0 || processorCounts.postprocessors > 0) {
95
+ writeSuccess(`āœ… Pushed ${processorCounts.preprocessors} preprocessor(s) and ${processorCounts.postprocessors} postprocessor(s) to sandbox`);
96
+ }
97
+ }
78
98
  // Use the first skill's sandbox ID for the web interface
79
99
  const firstSkillName = Object.keys(sandboxIds)[0];
80
100
  const sandboxSkillId = sandboxIds[firstSkillName];
@@ -83,7 +103,8 @@ export async function devCommand() {
83
103
  process.exit(1);
84
104
  }
85
105
  // Step 7: Start web server for chat interface
86
- const { server, wss, broadcastLog } = createChatServer(apiKey, agentId, skillId, sandboxSkillId, DEV_SERVER_PORT);
106
+ const { server, wss, broadcastLog } = createChatServer(apiKey, agentId, skillId, sandboxSkillId, DEV_SERVER_PORT, updatedConfig // Pass config for processor overrides
107
+ );
87
108
  // Step 8: Open browser to chat interface
88
109
  try {
89
110
  await open(`http://localhost:${DEV_SERVER_PORT}`);
@@ -17,7 +17,11 @@
17
17
  *
18
18
  * Note: This does NOT deploy to production. Use `lua deploy` for that.
19
19
  *
20
- * @param type - Optional type argument ('skill' or 'persona')
20
+ * @param type - Optional type argument ('skill', 'persona', 'webhook', 'job', 'preprocessor', 'postprocessor', or 'all')
21
+ * @param options - Command options (force, autoDeploy)
21
22
  * @returns Promise that resolves when push completes
22
23
  */
23
- export declare function pushCommand(type?: string): Promise<void>;
24
+ export declare function pushCommand(type?: string, options?: {
25
+ force?: boolean;
26
+ autoDeploy?: boolean;
27
+ }): Promise<void>;
@@ -31,17 +31,29 @@ 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 options - Command options (force, autoDeploy)
35
36
  * @returns Promise that resolves when push completes
36
37
  */
37
- export async function pushCommand(type) {
38
+ export async function pushCommand(type, options) {
38
39
  return withErrorHandling(async () => {
39
40
  let selectedType;
41
+ // Handle 'all' type with force flag
42
+ if (type === 'all') {
43
+ if (!options?.force) {
44
+ console.error('āŒ The "all" type requires the --force flag');
45
+ console.log('\nUsage:');
46
+ console.log(' lua push all --force Push all components without prompts');
47
+ console.log(' lua push all --force --auto-deploy Push and deploy all to production');
48
+ process.exit(1);
49
+ }
50
+ return await pushAllCommand(options);
51
+ }
40
52
  // Step 1: Check if type was provided as argument
41
53
  if (type) {
42
54
  // Validate the provided type
43
55
  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".`);
56
+ console.error(`āŒ Invalid type: "${type}". Must be "skill", "persona", "webhook", "job", "preprocessor", "postprocessor", or "all".`);
45
57
  console.log('\nUsage:');
46
58
  console.log(' lua push - Interactive selection');
47
59
  console.log(' lua push skill - Push a skill directly');
@@ -50,6 +62,7 @@ export async function pushCommand(type) {
50
62
  console.log(' lua push job - Push a job directly');
51
63
  console.log(' lua push preprocessor - Push a preprocessor directly');
52
64
  console.log(' lua push postprocessor - Push a postprocessor directly');
65
+ console.log(' lua push all --force - Push all components without prompts');
53
66
  process.exit(1);
54
67
  }
55
68
  selectedType = type;
@@ -441,7 +454,7 @@ async function pushWebhookVersion() {
441
454
  }
442
455
  const result = await response.json();
443
456
  writeSuccess(`\nāœ… Successfully pushed ${selectedWebhook.name} v${versionToPush}\n`);
444
- writeInfo(`šŸ“¦ Webhook URL: ${BASE_URLS.API}/webhooks/${config.agent.agentId}/${selectedWebhook.webhookId}`);
457
+ writeInfo(`šŸ“¦ Webhook URL: ${BASE_URLS.WEBHOOK}/${config.agent.agentId}/${selectedWebhook.webhookId}`);
445
458
  // Step 8: Ask if user wants to deploy now
446
459
  const deployAnswer = await safePrompt([
447
460
  {
@@ -765,7 +778,8 @@ async function pushPreProcessorVersion() {
765
778
  context: bundledData.context || selected.context,
766
779
  preprocessorId: selected.preprocessorId,
767
780
  code: bundledData.code,
768
- executeFunction: bundledData.executeFunction
781
+ executeFunction: bundledData.executeFunction,
782
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
769
783
  };
770
784
  writeProgress(`\nšŸš€ Pushing ${selected.name} v${confirmedVersion}...`);
771
785
  const api = new PreProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
@@ -896,7 +910,8 @@ async function pushPostProcessorVersion() {
896
910
  context: bundledData.context || selected.context,
897
911
  postprocessorId: selected.postprocessorId,
898
912
  code: bundledData.code,
899
- executeFunction: bundledData.executeFunction
913
+ executeFunction: bundledData.executeFunction,
914
+ async: Boolean(bundledData.async ?? false) // Ensure boolean type
900
915
  };
901
916
  writeProgress(`\nšŸš€ Pushing ${selected.name} v${confirmedVersion}...`);
902
917
  const api = new PostProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
@@ -1029,3 +1044,394 @@ async function deployVersionAfterPush(apiKey, agentId, selectedSkill, pushedVers
1029
1044
  console.log('šŸ’” You can deploy later using: lua deploy\n');
1030
1045
  }
1031
1046
  }
1047
+ /**
1048
+ * Push all command - Pushes all components (skills, webhooks, jobs, processors) without prompts
1049
+ *
1050
+ * This command:
1051
+ * 1. Compiles the project
1052
+ * 2. Reads lua.skill.yaml to get all components
1053
+ * 3. Auto-bumps patch versions
1054
+ * 4. Pushes all components
1055
+ * 5. Optionally auto-deploys to production
1056
+ *
1057
+ * @param options - Command options (force is required, autoDeploy is optional)
1058
+ */
1059
+ async function pushAllCommand(options) {
1060
+ writeProgress("šŸš€ Push All - Pushing all components to server...\n");
1061
+ // Step 1: Compile first
1062
+ writeProgress("šŸ“¦ Compiling project...");
1063
+ await compileCommand();
1064
+ // Step 2: Load configuration and API key
1065
+ const config = readSkillConfig();
1066
+ if (!config?.agent?.agentId) {
1067
+ console.error('āŒ No agent ID found in lua.skill.yaml. Run "lua init" first.');
1068
+ process.exit(1);
1069
+ }
1070
+ const apiKey = await loadApiKey();
1071
+ if (!apiKey) {
1072
+ console.error('āŒ No API key found. Run "lua auth configure" first.');
1073
+ process.exit(1);
1074
+ }
1075
+ const agentId = config.agent.agentId; // Validated above, safe to assert
1076
+ // Step 3: Read deploy.json for component data
1077
+ const deployJsonPath = path.join(process.cwd(), '.lua', 'deploy.json');
1078
+ if (!fs.existsSync(deployJsonPath)) {
1079
+ console.error('āŒ No deploy.json found. Compilation may have failed.');
1080
+ process.exit(1);
1081
+ }
1082
+ const deployData = JSON.parse(fs.readFileSync(deployJsonPath, 'utf8'));
1083
+ // Track results
1084
+ const results = {
1085
+ skills: [],
1086
+ webhooks: [],
1087
+ jobs: [],
1088
+ preprocessors: [],
1089
+ postprocessors: []
1090
+ };
1091
+ // Step 4: Push all skills
1092
+ if (config.skills && config.skills.length > 0) {
1093
+ writeProgress(`\nšŸ“¦ Pushing ${config.skills.length} skill(s)...`);
1094
+ for (const skillConfig of config.skills) {
1095
+ try {
1096
+ const skillData = deployData.skills.find((s) => s.name === skillConfig.name);
1097
+ if (!skillData) {
1098
+ console.warn(`āš ļø Skill "${skillConfig.name}" not found in deploy.json, skipping`);
1099
+ continue;
1100
+ }
1101
+ // Validate skillId and version exist
1102
+ const skillId = skillConfig.skillId;
1103
+ const currentVersion = skillConfig.version;
1104
+ if (!skillId) {
1105
+ console.warn(`āš ļø Skill "${skillConfig.name}" has no skillId, skipping`);
1106
+ continue;
1107
+ }
1108
+ if (!currentVersion) {
1109
+ console.warn(`āš ļø Skill "${skillConfig.name}" has no version, skipping`);
1110
+ continue;
1111
+ }
1112
+ // Auto-bump patch version
1113
+ const newVersion = bumpPatchVersion(currentVersion);
1114
+ writeInfo(` šŸ“ ${skillConfig.name}: ${currentVersion} → ${newVersion}`);
1115
+ // Push version
1116
+ const pushResult = await pushVersion(apiKey, agentId, skillId, {
1117
+ version: newVersion,
1118
+ description: skillConfig.description || '',
1119
+ context: skillConfig.context || '',
1120
+ code: skillData.code,
1121
+ executeFunction: skillData.executeFunction,
1122
+ inputSchema: skillData.inputSchema,
1123
+ outputSchema: skillData.outputSchema,
1124
+ });
1125
+ // Update YAML with new version
1126
+ updateSkillVersionInYaml(skillConfig.name, newVersion);
1127
+ results.skills.push({ name: skillConfig.name, version: newVersion, skillId });
1128
+ writeSuccess(` āœ… ${skillConfig.name} v${newVersion} pushed`);
1129
+ // Auto-deploy if requested
1130
+ if (options.autoDeploy) {
1131
+ await publishVersion(apiKey, agentId, skillId, newVersion);
1132
+ writeSuccess(` šŸš€ ${skillConfig.name} v${newVersion} deployed to production`);
1133
+ }
1134
+ }
1135
+ catch (error) {
1136
+ console.error(` āŒ Failed to push ${skillConfig.name}:`, error.message);
1137
+ }
1138
+ }
1139
+ }
1140
+ // Step 5: Push all webhooks
1141
+ if (config.webhooks && config.webhooks.length > 0) {
1142
+ writeProgress(`\nšŸŖ Pushing ${config.webhooks.length} webhook(s)...`);
1143
+ for (const webhookConfig of config.webhooks) {
1144
+ try {
1145
+ const webhookData = deployData.webhooks?.find((w) => w.name === webhookConfig.name);
1146
+ if (!webhookData) {
1147
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" not found in deploy.json, skipping`);
1148
+ continue;
1149
+ }
1150
+ // Validate webhookId and version exist
1151
+ if (!webhookConfig.webhookId) {
1152
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" has no webhookId, skipping`);
1153
+ continue;
1154
+ }
1155
+ if (!webhookConfig.version) {
1156
+ console.warn(`āš ļø Webhook "${webhookConfig.name}" has no version, skipping`);
1157
+ continue;
1158
+ }
1159
+ // Auto-bump patch version
1160
+ const newVersion = bumpPatchVersion(webhookConfig.version);
1161
+ writeInfo(` šŸ“ ${webhookConfig.name}: ${webhookConfig.version} → ${newVersion}`);
1162
+ // Prepare webhook data for push
1163
+ const pushData = {
1164
+ name: webhookConfig.name,
1165
+ version: newVersion,
1166
+ description: webhookData.description || webhookConfig.description || '',
1167
+ context: webhookData.context || webhookConfig.context || '',
1168
+ webhookId: webhookConfig.webhookId,
1169
+ querySchema: webhookData.querySchema,
1170
+ headerSchema: webhookData.headerSchema,
1171
+ bodySchema: webhookData.bodySchema,
1172
+ code: webhookData.code,
1173
+ executeFunction: webhookData.executeFunction
1174
+ };
1175
+ // Push version using fetch (like existing webhook push)
1176
+ const response = await fetch(`${BASE_URLS.API}/developer/webhooks/${agentId}/${webhookConfig.webhookId}/version`, {
1177
+ method: 'POST',
1178
+ headers: {
1179
+ 'Authorization': `Bearer ${apiKey}`,
1180
+ 'Content-Type': 'application/json'
1181
+ },
1182
+ body: JSON.stringify(pushData)
1183
+ });
1184
+ if (!response.ok) {
1185
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
1186
+ }
1187
+ // Update YAML
1188
+ updateWebhookVersionInYaml(webhookConfig.name, newVersion);
1189
+ results.webhooks.push({ name: webhookConfig.name, version: newVersion });
1190
+ writeSuccess(` āœ… ${webhookConfig.name} v${newVersion} pushed`);
1191
+ // Auto-deploy if requested
1192
+ if (options.autoDeploy) {
1193
+ const deployResponse = await fetch(`${BASE_URLS.API}/developer/webhooks/${agentId}/${webhookConfig.webhookId}/${newVersion}/publish`, {
1194
+ method: 'PUT',
1195
+ headers: {
1196
+ 'Authorization': `Bearer ${apiKey}`,
1197
+ 'Content-Type': 'application/json'
1198
+ }
1199
+ });
1200
+ if (deployResponse.ok) {
1201
+ writeSuccess(` šŸš€ ${webhookConfig.name} v${newVersion} deployed to production`);
1202
+ }
1203
+ }
1204
+ }
1205
+ catch (error) {
1206
+ console.error(` āŒ Failed to push ${webhookConfig.name}:`, error.message);
1207
+ }
1208
+ }
1209
+ }
1210
+ // Step 6: Push all jobs
1211
+ if (config.jobs && config.jobs.length > 0) {
1212
+ writeProgress(`\nā° Pushing ${config.jobs.length} job(s)...`);
1213
+ for (const jobConfig of config.jobs) {
1214
+ try {
1215
+ const jobData = deployData.jobs?.find((j) => j.name === jobConfig.name);
1216
+ if (!jobData) {
1217
+ console.warn(`āš ļø Job "${jobConfig.name}" not found in deploy.json, skipping`);
1218
+ continue;
1219
+ }
1220
+ // Validate jobId and version exist
1221
+ if (!jobConfig.jobId) {
1222
+ console.warn(`āš ļø Job "${jobConfig.name}" has no jobId, skipping`);
1223
+ continue;
1224
+ }
1225
+ if (!jobConfig.version) {
1226
+ console.warn(`āš ļø Job "${jobConfig.name}" has no version, skipping`);
1227
+ continue;
1228
+ }
1229
+ // Auto-bump patch version
1230
+ const newVersion = bumpPatchVersion(jobConfig.version);
1231
+ writeInfo(` šŸ“ ${jobConfig.name}: ${jobConfig.version} → ${newVersion}`);
1232
+ // Prepare job data for push
1233
+ const pushData = {
1234
+ name: jobConfig.name,
1235
+ version: newVersion,
1236
+ description: jobData.description || jobConfig.description || '',
1237
+ context: jobData.context || jobConfig.context || '',
1238
+ jobId: jobConfig.jobId,
1239
+ schedule: jobData.schedule || jobConfig.schedule,
1240
+ timeout: jobData.timeout,
1241
+ retry: jobData.retry,
1242
+ code: jobData.code,
1243
+ executeFunction: jobData.executeFunction,
1244
+ metadata: jobData.metadata || jobConfig.metadata
1245
+ };
1246
+ // Push version using fetch
1247
+ const response = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${jobConfig.jobId}/version`, {
1248
+ method: 'POST',
1249
+ headers: {
1250
+ 'Authorization': `Bearer ${apiKey}`,
1251
+ 'Content-Type': 'application/json'
1252
+ },
1253
+ body: JSON.stringify(pushData)
1254
+ });
1255
+ if (!response.ok) {
1256
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
1257
+ }
1258
+ // Update YAML
1259
+ updateJobVersionInYaml(jobConfig.name, newVersion);
1260
+ results.jobs.push({ name: jobConfig.name, version: newVersion });
1261
+ writeSuccess(` āœ… ${jobConfig.name} v${newVersion} pushed`);
1262
+ // Auto-deploy if requested
1263
+ if (options.autoDeploy) {
1264
+ const deployResponse = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${jobConfig.jobId}/${newVersion}/publish`, {
1265
+ method: 'PUT',
1266
+ headers: {
1267
+ 'Authorization': `Bearer ${apiKey}`,
1268
+ 'Content-Type': 'application/json'
1269
+ }
1270
+ });
1271
+ if (deployResponse.ok) {
1272
+ writeSuccess(` šŸš€ ${jobConfig.name} v${newVersion} deployed to production`);
1273
+ }
1274
+ }
1275
+ }
1276
+ catch (error) {
1277
+ console.error(` āŒ Failed to push ${jobConfig.name}:`, error.message);
1278
+ }
1279
+ }
1280
+ }
1281
+ // Step 7: Push all preprocessors
1282
+ if (config.preprocessors && config.preprocessors.length > 0) {
1283
+ writeProgress(`\nšŸ“„ Pushing ${config.preprocessors.length} preprocessor(s)...`);
1284
+ const preprocessorService = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
1285
+ for (const processorConfig of config.preprocessors) {
1286
+ try {
1287
+ const processorData = deployData.preprocessors?.find((p) => p.name === processorConfig.name);
1288
+ if (!processorData) {
1289
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" not found in deploy.json, skipping`);
1290
+ continue;
1291
+ }
1292
+ // Validate preprocessorId and version exist
1293
+ const preprocessorId = processorConfig.preprocessorId;
1294
+ const currentVersion = processorConfig.version;
1295
+ if (!preprocessorId) {
1296
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" has no preprocessorId, skipping`);
1297
+ continue;
1298
+ }
1299
+ if (!currentVersion) {
1300
+ console.warn(`āš ļø Preprocessor "${processorConfig.name}" has no version, skipping`);
1301
+ continue;
1302
+ }
1303
+ // Auto-bump patch version
1304
+ const newVersion = bumpPatchVersion(currentVersion);
1305
+ writeInfo(` šŸ“ ${processorConfig.name}: ${currentVersion} → ${newVersion}`);
1306
+ // Prepare version data
1307
+ const versionData = {
1308
+ name: processorConfig.name,
1309
+ version: newVersion,
1310
+ description: processorData.description || processorConfig.description || '',
1311
+ context: processorData.context || processorConfig.context || '',
1312
+ preprocessorId: preprocessorId,
1313
+ code: processorData.code,
1314
+ executeFunction: processorData.executeFunction,
1315
+ async: Boolean(processorData.async ?? false)
1316
+ };
1317
+ // Push version
1318
+ const result = await preprocessorService.pushPreProcessor(preprocessorId, versionData);
1319
+ if (!result.success) {
1320
+ throw new Error(result.error?.message || 'Failed to push preprocessor');
1321
+ }
1322
+ // Update YAML
1323
+ updateProcessorVersionInYaml('preprocessors', processorConfig.name, newVersion);
1324
+ results.preprocessors.push({ name: processorConfig.name, version: newVersion });
1325
+ writeSuccess(` āœ… ${processorConfig.name} v${newVersion} pushed`);
1326
+ // Auto-deploy if requested
1327
+ if (options.autoDeploy) {
1328
+ const deployResult = await preprocessorService.publishPreProcessorVersion(preprocessorId, newVersion);
1329
+ if (deployResult.success) {
1330
+ writeSuccess(` šŸš€ ${processorConfig.name} v${newVersion} deployed to production`);
1331
+ }
1332
+ }
1333
+ }
1334
+ catch (error) {
1335
+ console.error(` āŒ Failed to push ${processorConfig.name}:`, error.message);
1336
+ }
1337
+ }
1338
+ }
1339
+ // Step 8: Push all postprocessors
1340
+ if (config.postprocessors && config.postprocessors.length > 0) {
1341
+ writeProgress(`\nšŸ“¤ Pushing ${config.postprocessors.length} postprocessor(s)...`);
1342
+ const postprocessorService = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
1343
+ for (const processorConfig of config.postprocessors) {
1344
+ try {
1345
+ const processorData = deployData.postprocessors?.find((p) => p.name === processorConfig.name);
1346
+ if (!processorData) {
1347
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" not found in deploy.json, skipping`);
1348
+ continue;
1349
+ }
1350
+ // Validate postprocessorId and version exist
1351
+ const postprocessorId = processorConfig.postprocessorId;
1352
+ const currentVersion = processorConfig.version;
1353
+ if (!postprocessorId) {
1354
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" has no postprocessorId, skipping`);
1355
+ continue;
1356
+ }
1357
+ if (!currentVersion) {
1358
+ console.warn(`āš ļø Postprocessor "${processorConfig.name}" has no version, skipping`);
1359
+ continue;
1360
+ }
1361
+ // Auto-bump patch version
1362
+ const newVersion = bumpPatchVersion(currentVersion);
1363
+ writeInfo(` šŸ“ ${processorConfig.name}: ${currentVersion} → ${newVersion}`);
1364
+ // Prepare version data
1365
+ const versionData = {
1366
+ name: processorConfig.name,
1367
+ version: newVersion,
1368
+ description: processorData.description || processorConfig.description || '',
1369
+ context: processorData.context || processorConfig.context || '',
1370
+ postprocessorId: postprocessorId,
1371
+ code: processorData.code,
1372
+ executeFunction: processorData.executeFunction,
1373
+ async: Boolean(processorData.async ?? false)
1374
+ };
1375
+ // Push version
1376
+ const result = await postprocessorService.pushPostProcessor(postprocessorId, versionData);
1377
+ if (!result.success) {
1378
+ throw new Error(result.error?.message || 'Failed to push postprocessor');
1379
+ }
1380
+ // Update YAML
1381
+ updateProcessorVersionInYaml('postprocessors', processorConfig.name, newVersion);
1382
+ results.postprocessors.push({ name: processorConfig.name, version: newVersion });
1383
+ writeSuccess(` āœ… ${processorConfig.name} v${newVersion} pushed`);
1384
+ // Auto-deploy if requested
1385
+ if (options.autoDeploy) {
1386
+ const deployResult = await postprocessorService.publishPostProcessorVersion(postprocessorId, newVersion);
1387
+ if (deployResult.success) {
1388
+ writeSuccess(` šŸš€ ${processorConfig.name} v${newVersion} deployed to production`);
1389
+ }
1390
+ }
1391
+ }
1392
+ catch (error) {
1393
+ console.error(` āŒ Failed to push ${processorConfig.name}:`, error.message);
1394
+ }
1395
+ }
1396
+ }
1397
+ // Step 9: Print summary
1398
+ writeSuccess('\nāœ… Push All Complete!\n');
1399
+ if (results.skills.length > 0) {
1400
+ console.log(`šŸ› ļø Skills (${results.skills.length}):`);
1401
+ results.skills.forEach(s => console.log(` • ${s.name} v${s.version}`));
1402
+ }
1403
+ if (results.webhooks.length > 0) {
1404
+ console.log(`šŸŖ Webhooks (${results.webhooks.length}):`);
1405
+ results.webhooks.forEach(w => console.log(` • ${w.name} v${w.version}`));
1406
+ }
1407
+ if (results.jobs.length > 0) {
1408
+ console.log(`ā° Jobs (${results.jobs.length}):`);
1409
+ results.jobs.forEach(j => console.log(` • ${j.name} v${j.version}`));
1410
+ }
1411
+ if (results.preprocessors.length > 0) {
1412
+ console.log(`šŸ“„ PreProcessors (${results.preprocessors.length}):`);
1413
+ results.preprocessors.forEach(p => console.log(` • ${p.name} v${p.version}`));
1414
+ }
1415
+ if (results.postprocessors.length > 0) {
1416
+ console.log(`šŸ“¤ PostProcessors (${results.postprocessors.length}):`);
1417
+ results.postprocessors.forEach(p => console.log(` • ${p.name} v${p.version}`));
1418
+ }
1419
+ if (options.autoDeploy) {
1420
+ writeSuccess('\nšŸš€ All components deployed to production!');
1421
+ }
1422
+ console.log('');
1423
+ }
1424
+ /**
1425
+ * Bumps the patch version of a semantic version string
1426
+ * e.g., "1.2.3" -> "1.2.4"
1427
+ */
1428
+ function bumpPatchVersion(version) {
1429
+ const parts = version.split('.');
1430
+ if (parts.length !== 3) {
1431
+ // If not a valid semver, just return incremented version
1432
+ return version + '.1';
1433
+ }
1434
+ const [major, minor, patch] = parts;
1435
+ const newPatch = parseInt(patch, 10) + 1;
1436
+ return `${major}.${minor}.${newPatch}`;
1437
+ }
@@ -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
  */
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Base URLs for the API, Auth, and Chat - Production
3
3
  */
4
- export declare const BASE_URLS: {
5
- readonly API: "http://localhost:3022";
6
- readonly AUTH: "https://auth.heylua.ai";
7
- readonly CHAT: "http://localhost:3001";
8
- };
9
4
  /**
10
5
  * Base URLs for the API, Auth, and Chat - Development
11
6
  */
7
+ export declare const BASE_URLS: {
8
+ readonly API: "https://api.heylua.ai";
9
+ readonly AUTH: "https://auth.heylua.ai";
10
+ readonly CHAT: "https://api.heylua.ai";
11
+ readonly WEBHOOK: "https://webhook.heylua.ai";
12
+ };