lua-cli 2.5.7 → 3.0.0-alpha.1
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.
- package/dist/api/agent.api.service.d.ts +45 -0
- package/dist/api/agent.api.service.js +54 -0
- package/dist/api/job.api.service.d.ts +210 -0
- package/dist/api/job.api.service.js +200 -0
- package/dist/api/lazy-instances.d.ts +24 -0
- package/dist/api/lazy-instances.js +48 -0
- package/dist/api/postprocessor.api.service.d.ts +98 -0
- package/dist/api/postprocessor.api.service.js +76 -0
- package/dist/api/preprocessor.api.service.d.ts +98 -0
- package/dist/api/preprocessor.api.service.js +76 -0
- package/dist/api/user.data.api.service.d.ts +28 -0
- package/dist/api/user.data.api.service.js +51 -0
- package/dist/api/webhook.api.service.d.ts +151 -0
- package/dist/api/webhook.api.service.js +134 -0
- package/dist/api-exports.d.ts +156 -41
- package/dist/api-exports.js +182 -21
- package/dist/cli/command-definitions.js +149 -7
- package/dist/commands/compile.js +124 -5
- package/dist/commands/completion.d.ts +11 -0
- package/dist/commands/completion.js +209 -0
- package/dist/commands/env.d.ts +3 -2
- package/dist/commands/env.js +42 -17
- package/dist/commands/features.d.ts +16 -0
- package/dist/commands/features.js +352 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/init.js +53 -7
- package/dist/commands/jobs.d.ts +20 -0
- package/dist/commands/jobs.js +533 -0
- package/dist/commands/logs.js +2 -5
- package/dist/commands/persona.d.ts +3 -2
- package/dist/commands/persona.js +43 -18
- package/dist/commands/postprocessors.d.ts +8 -0
- package/dist/commands/postprocessors.js +431 -0
- package/dist/commands/preprocessors.d.ts +8 -0
- package/dist/commands/preprocessors.js +431 -0
- package/dist/commands/push.d.ts +9 -13
- package/dist/commands/push.js +937 -69
- package/dist/commands/skills.d.ts +16 -0
- package/dist/commands/skills.js +438 -0
- package/dist/commands/test.d.ts +9 -18
- package/dist/commands/test.js +558 -82
- package/dist/commands/webhooks.d.ts +18 -0
- package/dist/commands/webhooks.js +424 -0
- package/dist/common/data.entry.instance.d.ts +7 -0
- package/dist/common/data.entry.instance.js +15 -0
- package/dist/common/job.instance.d.ts +77 -0
- package/dist/common/job.instance.js +108 -0
- package/dist/common/order.instance.d.ts +6 -0
- package/dist/common/order.instance.js +14 -0
- package/dist/common/product.instance.d.ts +6 -0
- package/dist/common/product.instance.js +14 -0
- package/dist/common/user.instance.d.ts +15 -0
- package/dist/common/user.instance.js +38 -0
- package/dist/config/constants.d.ts +2 -2
- package/dist/config/constants.js +4 -4
- package/dist/index.js +14 -3
- package/dist/interfaces/agent.d.ts +33 -1
- package/dist/interfaces/chat.d.ts +22 -0
- package/dist/interfaces/index.d.ts +10 -0
- package/dist/interfaces/index.js +7 -0
- package/dist/interfaces/jobs.d.ts +172 -0
- package/dist/interfaces/jobs.js +5 -0
- package/dist/interfaces/message.d.ts +18 -0
- package/dist/interfaces/message.js +1 -0
- package/dist/interfaces/postprocessors.d.ts +35 -0
- package/dist/interfaces/postprocessors.js +4 -0
- package/dist/interfaces/preprocessors.d.ts +35 -0
- package/dist/interfaces/preprocessors.js +4 -0
- package/dist/interfaces/webhooks.d.ts +104 -0
- package/dist/interfaces/webhooks.js +5 -0
- package/dist/types/api-contracts.d.ts +14 -0
- package/dist/types/api-contracts.js +0 -7
- package/dist/types/compile.types.d.ts +49 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/skill.d.ts +502 -0
- package/dist/types/skill.js +477 -0
- package/dist/utils/agent-management.d.ts +25 -0
- package/dist/utils/agent-management.js +67 -0
- package/dist/utils/bundling.d.ts +31 -1
- package/dist/utils/bundling.js +653 -10
- package/dist/utils/compile.d.ts +63 -0
- package/dist/utils/compile.js +691 -36
- package/dist/utils/deployment.d.ts +2 -1
- package/dist/utils/deployment.js +16 -2
- package/dist/utils/init-agent.d.ts +3 -1
- package/dist/utils/init-agent.js +6 -4
- package/dist/utils/init-prompts.d.ts +2 -1
- package/dist/utils/init-prompts.js +14 -9
- package/dist/utils/job-management.d.ts +24 -0
- package/dist/utils/job-management.js +264 -0
- package/dist/utils/postprocessor-management.d.ts +9 -0
- package/dist/utils/postprocessor-management.js +118 -0
- package/dist/utils/preprocessor-management.d.ts +9 -0
- package/dist/utils/preprocessor-management.js +118 -0
- package/dist/utils/sandbox.d.ts +61 -1
- package/dist/utils/sandbox.js +283 -72
- package/dist/utils/tool-detection.d.ts +3 -2
- package/dist/utils/tool-detection.js +18 -4
- package/dist/utils/webhook-management.d.ts +24 -0
- package/dist/utils/webhook-management.js +256 -0
- package/dist/web/app.css +152 -736
- package/dist/web/app.js +45 -45
- package/package.json +2 -2
- package/template/AGENT_CONFIGURATION.md +251 -0
- package/template/COMPLEX_JOB_EXAMPLES.md +795 -0
- package/template/DYNAMIC_JOB_CREATION.md +371 -0
- package/template/README.md +30 -2
- package/template/WEBHOOKS_JOBS_QUICKSTART.md +318 -0
- package/template/WEBHOOK_JOB_EXAMPLES.md +817 -0
- package/template/package.json +1 -1
- package/template/src/index-agent-example.ts +201 -0
- package/template/src/index.ts +39 -0
- package/template/src/jobs/AbandonedBasketProcessorJob.ts +139 -0
- package/template/src/jobs/DailyCleanupJob.ts +100 -0
- package/template/src/jobs/DataMigrationJob.ts +133 -0
- package/template/src/jobs/HealthCheckJob.ts +87 -0
- package/template/src/postprocessors/ResponseFormatter.ts +151 -0
- package/template/src/preprocessors/MessageFilter.ts +91 -0
- package/template/src/tools/GameScoreTrackerTool.ts +356 -0
- package/template/src/tools/SmartBasketTool.ts +188 -0
- package/template/src/webhooks/PaymentWebhook.ts +113 -0
- package/template/src/webhooks/UserEventWebhook.ts +77 -0
package/dist/commands/push.js
CHANGED
|
@@ -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';
|
|
@@ -10,10 +13,95 @@ import { safePrompt } from '../utils/prompt-handler.js';
|
|
|
10
13
|
import { readDeployJson, validatePushConfig, validateDeployData, promptSkillSelection, promptVersionConfirmOrUpdate, getAvailableSkills, updateSkillVersionInYaml, getSkillDeployData, } from '../utils/push-helpers.js';
|
|
11
14
|
import { pushVersion } from '../utils/push-api.js';
|
|
12
15
|
import { fetchVersions, publishVersion, } from '../utils/deploy-api.js';
|
|
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';
|
|
13
19
|
/**
|
|
14
|
-
* Main push command - pushes a skill version to the server.
|
|
20
|
+
* Main push command - pushes a skill or persona version to the server.
|
|
15
21
|
*
|
|
16
22
|
* This command performs the following steps:
|
|
23
|
+
* 1. If type argument provided, uses it directly
|
|
24
|
+
* 2. Otherwise, prompts user to select 'skill' or 'persona'
|
|
25
|
+
* 3. Routes to appropriate push flow
|
|
26
|
+
*
|
|
27
|
+
* Use this command to:
|
|
28
|
+
* - Upload a new version of your skill or persona
|
|
29
|
+
* - Make your skill/persona available for testing in dev mode
|
|
30
|
+
* - Prepare your skill/persona for deployment
|
|
31
|
+
*
|
|
32
|
+
* Note: This does NOT deploy to production. Use `lua deploy` for that.
|
|
33
|
+
*
|
|
34
|
+
* @param type - Optional type argument ('skill' or 'persona')
|
|
35
|
+
* @returns Promise that resolves when push completes
|
|
36
|
+
*/
|
|
37
|
+
export async function pushCommand(type) {
|
|
38
|
+
return withErrorHandling(async () => {
|
|
39
|
+
let selectedType;
|
|
40
|
+
// Step 1: Check if type was provided as argument
|
|
41
|
+
if (type) {
|
|
42
|
+
// Validate the provided type
|
|
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".`);
|
|
45
|
+
console.log('\nUsage:');
|
|
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');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
selectedType = type;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Step 2: Prompt for type selection
|
|
59
|
+
const typeAnswer = await safePrompt([
|
|
60
|
+
{
|
|
61
|
+
type: 'list',
|
|
62
|
+
name: 'type',
|
|
63
|
+
message: 'What would you like to push?',
|
|
64
|
+
choices: [
|
|
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' },
|
|
70
|
+
{ name: '🌙 Persona', value: 'persona' }
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
]);
|
|
74
|
+
if (!typeAnswer) {
|
|
75
|
+
console.log("Push cancelled.");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
selectedType = typeAnswer.type;
|
|
79
|
+
}
|
|
80
|
+
// Step 3: Route to appropriate function
|
|
81
|
+
if (selectedType === 'skill') {
|
|
82
|
+
await pushSkillVersion();
|
|
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
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
await pushPersonaVersion();
|
|
98
|
+
}
|
|
99
|
+
}, "push");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Push skill version to the server.
|
|
103
|
+
*
|
|
104
|
+
* This function performs the following steps:
|
|
17
105
|
* 1. Validates configuration has required fields
|
|
18
106
|
* 2. Prompts user to select a skill (if multiple skills exist)
|
|
19
107
|
* 3. Prompts to confirm or update version
|
|
@@ -23,98 +111,878 @@ import { fetchVersions, publishVersion, } from '../utils/deploy-api.js';
|
|
|
23
111
|
* 7. Extracts the specific skill's deploy data
|
|
24
112
|
* 8. Pushes version to server
|
|
25
113
|
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
114
|
+
* @returns Promise that resolves when push completes
|
|
115
|
+
*/
|
|
116
|
+
async function pushSkillVersion() {
|
|
117
|
+
// Step 1: Validate configuration
|
|
118
|
+
const config = readSkillConfig();
|
|
119
|
+
validatePushConfig(config);
|
|
120
|
+
// Step 2: Get available skills and prompt for selection
|
|
121
|
+
const availableSkills = getAvailableSkills(config);
|
|
122
|
+
if (availableSkills.length === 0) {
|
|
123
|
+
console.error("❌ No skills found in configuration. Please compile your skill first using 'lua compile'.");
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
let selectedSkill;
|
|
127
|
+
if (availableSkills.length === 1) {
|
|
128
|
+
// Only one skill, use it automatically
|
|
129
|
+
selectedSkill = availableSkills[0];
|
|
130
|
+
writeInfo(`📦 Pushing skill: ${selectedSkill.name}`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Multiple skills, prompt for selection
|
|
134
|
+
selectedSkill = await promptSkillSelection(availableSkills);
|
|
135
|
+
writeInfo(`📦 Selected skill: ${selectedSkill.name}`);
|
|
136
|
+
}
|
|
137
|
+
// Step 3: Confirm or update version
|
|
138
|
+
const confirmedVersion = await promptVersionConfirmOrUpdate(selectedSkill.version);
|
|
139
|
+
let versionUpdated = false;
|
|
140
|
+
if (confirmedVersion !== selectedSkill.version) {
|
|
141
|
+
writeInfo(`📝 Updating version from ${selectedSkill.version} to ${confirmedVersion}`);
|
|
142
|
+
updateSkillVersionInYaml(selectedSkill.name, confirmedVersion);
|
|
143
|
+
selectedSkill.version = confirmedVersion;
|
|
144
|
+
versionUpdated = true;
|
|
145
|
+
}
|
|
146
|
+
// Step 4: Authenticate
|
|
147
|
+
const apiKey = await loadApiKey();
|
|
148
|
+
if (!apiKey) {
|
|
149
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const userData = await checkApiKey(apiKey);
|
|
153
|
+
writeProgress("✅ Authenticated");
|
|
154
|
+
// Step 5: Compile the skill (always compile to ensure up-to-date, or if version was updated)
|
|
155
|
+
writeProgress("🔄 Compiling skill...");
|
|
156
|
+
await compileCommand();
|
|
157
|
+
// Step 6: Validate deploy data for the selected skill
|
|
158
|
+
const deployData = readDeployJson();
|
|
159
|
+
validateDeployData(deployData, selectedSkill);
|
|
160
|
+
// Step 7: Extract the specific skill's deploy data
|
|
161
|
+
const skillDeployData = getSkillDeployData(deployData, selectedSkill.name);
|
|
162
|
+
// Step 8: Push version to server
|
|
163
|
+
const agentId = config.agent.agentId;
|
|
164
|
+
const skillId = selectedSkill.skillId;
|
|
165
|
+
writeProgress("🔄 Pushing version to server...");
|
|
166
|
+
const result = await pushVersion(apiKey, agentId, skillId, skillDeployData);
|
|
167
|
+
if (result.success && result.data) {
|
|
168
|
+
const pushedVersion = result.data.version;
|
|
169
|
+
writeSuccess(`✅ Version ${pushedVersion} of "${selectedSkill.name}" pushed successfully`);
|
|
170
|
+
// Update YAML with the version returned from server (in case it's different)
|
|
171
|
+
if (pushedVersion !== selectedSkill.version) {
|
|
172
|
+
writeInfo(`📝 Updating YAML with server version: ${pushedVersion}`);
|
|
173
|
+
updateSkillVersionInYaml(selectedSkill.name, pushedVersion);
|
|
174
|
+
selectedSkill.version = pushedVersion;
|
|
175
|
+
}
|
|
176
|
+
// Ask if user wants to deploy now
|
|
177
|
+
const deployAnswer = await safePrompt([
|
|
178
|
+
{
|
|
179
|
+
type: 'confirm',
|
|
180
|
+
name: 'deployNow',
|
|
181
|
+
message: 'Would you like to deploy this version to production now?',
|
|
182
|
+
default: false
|
|
183
|
+
}
|
|
184
|
+
]);
|
|
185
|
+
if (deployAnswer && deployAnswer.deployNow) {
|
|
186
|
+
await deployVersionAfterPush(apiKey, config.agent.agentId, selectedSkill, pushedVersion);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (result.error) {
|
|
190
|
+
console.error(`❌ ${result.error.message}`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.error("❌ Failed to push version. Please try again.");
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Push persona version to the server.
|
|
30
200
|
*
|
|
31
|
-
*
|
|
201
|
+
* This function performs the following steps:
|
|
202
|
+
* 1. Validates configuration has required fields
|
|
203
|
+
* 2. Loads current persona from lua.skill.yaml
|
|
204
|
+
* 3. Authenticates the user
|
|
205
|
+
* 4. Pushes persona version to server
|
|
206
|
+
* 5. Optionally deploys to production
|
|
32
207
|
*
|
|
33
208
|
* @returns Promise that resolves when push completes
|
|
34
209
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
210
|
+
async function pushPersonaVersion() {
|
|
211
|
+
// Step 1: Validate configuration
|
|
212
|
+
const config = readSkillConfig();
|
|
213
|
+
if (!config || !config.agent?.agentId) {
|
|
214
|
+
console.error("❌ No agent configuration found. Please run 'lua init' first.");
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
// Step 2: Load current persona
|
|
218
|
+
const currentPersona = config.agent?.persona || '';
|
|
219
|
+
if (!currentPersona || !currentPersona.trim()) {
|
|
220
|
+
console.error("❌ No persona found in configuration. Please edit your persona first using 'lua persona'.");
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
writeInfo(`📦 Pushing persona for agent: ${config.agent.agentId}`);
|
|
224
|
+
// Show preview of persona
|
|
225
|
+
const preview = currentPersona.length > 200
|
|
226
|
+
? currentPersona.substring(0, 200) + '...'
|
|
227
|
+
: currentPersona;
|
|
228
|
+
console.log("\nPersona preview:");
|
|
229
|
+
console.log(preview);
|
|
230
|
+
console.log();
|
|
231
|
+
// Step 3: Confirm push
|
|
232
|
+
const confirmAnswer = await safePrompt([
|
|
233
|
+
{
|
|
234
|
+
type: 'confirm',
|
|
235
|
+
name: 'confirm',
|
|
236
|
+
message: 'Create new persona version?',
|
|
237
|
+
default: true
|
|
238
|
+
}
|
|
239
|
+
]);
|
|
240
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
241
|
+
console.log("\n❌ Push cancelled.\n");
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// Step 4: Authenticate
|
|
245
|
+
const apiKey = await loadApiKey();
|
|
246
|
+
if (!apiKey) {
|
|
247
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
await checkApiKey(apiKey);
|
|
251
|
+
writeProgress("✅ Authenticated");
|
|
252
|
+
// Step 5: Push persona version to server
|
|
253
|
+
writeProgress("🔄 Creating persona version...");
|
|
254
|
+
try {
|
|
255
|
+
const response = await fetch(`${BASE_URLS.API}/developer/agents/${config.agent.agentId}/persona/version`, {
|
|
256
|
+
method: 'POST',
|
|
257
|
+
headers: {
|
|
258
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
259
|
+
'Content-Type': 'application/json'
|
|
260
|
+
},
|
|
261
|
+
body: JSON.stringify({ persona: currentPersona })
|
|
262
|
+
});
|
|
263
|
+
if (!response.ok) {
|
|
264
|
+
const errorText = await response.text();
|
|
265
|
+
throw new Error(`HTTP error! status: ${response.status}, ${errorText}`);
|
|
266
|
+
}
|
|
267
|
+
const data = await response.json();
|
|
268
|
+
const versionNum = data.version || data.data?.version || 'N/A';
|
|
269
|
+
writeSuccess(`✅ Persona version ${versionNum} created successfully`);
|
|
270
|
+
// Step 6: Ask if user wants to deploy now
|
|
271
|
+
const deployAnswer = await safePrompt([
|
|
272
|
+
{
|
|
273
|
+
type: 'confirm',
|
|
274
|
+
name: 'deployNow',
|
|
275
|
+
message: 'Would you like to deploy this persona version to production now?',
|
|
276
|
+
default: false
|
|
277
|
+
}
|
|
278
|
+
]);
|
|
279
|
+
if (deployAnswer && deployAnswer.deployNow) {
|
|
280
|
+
await deployPersonaVersionAfterPush(apiKey, config.agent.agentId, versionNum);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
writeInfo("💡 You can deploy this version later using: lua deploy");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
console.error('❌ Error creating persona version:', error);
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Deploy a persona version immediately after pushing
|
|
293
|
+
*/
|
|
294
|
+
async function deployPersonaVersionAfterPush(apiKey, agentId, versionNum) {
|
|
295
|
+
try {
|
|
296
|
+
// Show warning
|
|
297
|
+
console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
|
|
298
|
+
console.log("⚠️ This will affect ALL users immediately.\n");
|
|
299
|
+
const confirmAnswer = await safePrompt([
|
|
300
|
+
{
|
|
301
|
+
type: 'confirm',
|
|
302
|
+
name: 'confirm',
|
|
303
|
+
message: 'Are you absolutely sure you want to deploy this persona version?',
|
|
304
|
+
default: false
|
|
305
|
+
}
|
|
306
|
+
]);
|
|
307
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
308
|
+
console.log("\n❌ Deployment cancelled. Persona version created but not deployed.\n");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
writeProgress("🔄 Deploying persona version...");
|
|
312
|
+
const deployResponse = await fetch(`${BASE_URLS.API}/developer/agents/${agentId}/persona/version/${versionNum}`, {
|
|
313
|
+
method: 'POST',
|
|
314
|
+
headers: {
|
|
315
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
316
|
+
'Content-Type': 'application/json'
|
|
317
|
+
},
|
|
318
|
+
body: JSON.stringify({})
|
|
319
|
+
});
|
|
320
|
+
if (!deployResponse.ok) {
|
|
321
|
+
const errorText = await deployResponse.text();
|
|
322
|
+
console.error(`\n❌ Deploy Error: ${deployResponse.status} - ${errorText}\n`);
|
|
323
|
+
throw new Error(`HTTP error! status: ${deployResponse.status}`);
|
|
324
|
+
}
|
|
325
|
+
writeSuccess(`\n✅ Persona version ${versionNum} deployed successfully to production\n`);
|
|
326
|
+
writeInfo("💡 The new persona is now active for all users.");
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
console.error('\n❌ Error deploying persona version:', error);
|
|
330
|
+
console.log('💡 You can deploy later using: lua persona\n');
|
|
331
|
+
}
|
|
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
|
|
38
359
|
const config = readSkillConfig();
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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.");
|
|
44
404
|
process.exit(1);
|
|
45
405
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
writeInfo(
|
|
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.API}/webhooks/${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);
|
|
51
456
|
}
|
|
52
457
|
else {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
//
|
|
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");
|
|
67
556
|
const apiKey = await loadApiKey();
|
|
68
557
|
if (!apiKey) {
|
|
69
558
|
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
70
559
|
process.exit(1);
|
|
71
560
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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...");
|
|
76
711
|
await compileCommand();
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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([
|
|
98
736
|
{
|
|
99
|
-
type: '
|
|
100
|
-
name: '
|
|
101
|
-
message: '
|
|
102
|
-
|
|
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
|
+
}))
|
|
103
744
|
}
|
|
104
745
|
]);
|
|
105
|
-
if (
|
|
106
|
-
|
|
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
|
+
};
|
|
770
|
+
writeProgress(`\n🚀 Pushing ${selected.name} v${confirmedVersion}...`);
|
|
771
|
+
const api = new PreProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
|
|
772
|
+
const result = await api.pushPreProcessor(selected.preprocessorId, versionData);
|
|
773
|
+
if (result.success) {
|
|
774
|
+
writeSuccess(`\n✅ PreProcessor "${selected.name}" v${confirmedVersion} pushed successfully\n`);
|
|
775
|
+
// Ask if user wants to deploy now
|
|
776
|
+
const deployAnswer = await safePrompt([
|
|
777
|
+
{
|
|
778
|
+
type: 'confirm',
|
|
779
|
+
name: 'deployNow',
|
|
780
|
+
message: 'Would you like to deploy this preprocessor version to production now?',
|
|
781
|
+
default: false
|
|
782
|
+
}
|
|
783
|
+
]);
|
|
784
|
+
if (deployAnswer && deployAnswer.deployNow) {
|
|
785
|
+
await deployPreProcessorVersionAfterPush(apiKey, config.agent.agentId, selected, confirmedVersion);
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
writeInfo("💡 You can deploy this version later using: lua preprocessors production");
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
console.error(`❌ Failed to push: ${result.error?.message}`);
|
|
107
793
|
}
|
|
108
794
|
}
|
|
109
|
-
|
|
110
|
-
|
|
795
|
+
}
|
|
796
|
+
catch (error) {
|
|
797
|
+
console.error('❌ Error pushing preprocessor:', error);
|
|
798
|
+
process.exit(1);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Deploy a preprocessor version immediately after pushing
|
|
803
|
+
*/
|
|
804
|
+
async function deployPreProcessorVersionAfterPush(apiKey, agentId, selected, pushedVersion) {
|
|
805
|
+
try {
|
|
806
|
+
// Show warning
|
|
807
|
+
console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
|
|
808
|
+
console.log("⚠️ This will affect ALL users immediately.\n");
|
|
809
|
+
const confirmAnswer = await safePrompt([
|
|
810
|
+
{
|
|
811
|
+
type: 'confirm',
|
|
812
|
+
name: 'confirm',
|
|
813
|
+
message: 'Are you absolutely sure you want to deploy?',
|
|
814
|
+
default: false
|
|
815
|
+
}
|
|
816
|
+
]);
|
|
817
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
818
|
+
console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
writeProgress("🔄 Publishing preprocessor version...");
|
|
822
|
+
const api = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
|
|
823
|
+
const publishResponse = await api.publishPreProcessorVersion(selected.preprocessorId, pushedVersion);
|
|
824
|
+
if (!publishResponse.success) {
|
|
825
|
+
console.error(`\n❌ Deploy Error: ${publishResponse.error?.message || 'Unknown error'}\n`);
|
|
826
|
+
throw new Error(publishResponse.error?.message || 'Failed to publish preprocessor version');
|
|
827
|
+
}
|
|
828
|
+
writeSuccess(`\n✅ PreProcessor ${selected.name} v${pushedVersion} deployed successfully to production\n`);
|
|
829
|
+
writeInfo("💡 The new preprocessor version is now active for all users.");
|
|
830
|
+
}
|
|
831
|
+
catch (error) {
|
|
832
|
+
console.error('\n❌ Error deploying preprocessor version:', error);
|
|
833
|
+
console.log('💡 You can deploy later using: lua preprocessors production\n');
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Push postprocessor version to the server.
|
|
838
|
+
*/
|
|
839
|
+
async function pushPostProcessorVersion() {
|
|
840
|
+
try {
|
|
841
|
+
writeProgress("📦 Compiling project...");
|
|
842
|
+
await compileCommand();
|
|
843
|
+
writeSuccess("✅ Compilation complete");
|
|
844
|
+
const apiKey = await loadApiKey();
|
|
845
|
+
if (!apiKey) {
|
|
846
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
111
847
|
process.exit(1);
|
|
112
848
|
}
|
|
113
|
-
|
|
114
|
-
|
|
849
|
+
await checkApiKey(apiKey);
|
|
850
|
+
const config = readSkillConfig();
|
|
851
|
+
if (!config?.agent?.agentId) {
|
|
852
|
+
console.error("❌ No agent ID found in lua.skill.yaml.");
|
|
115
853
|
process.exit(1);
|
|
116
854
|
}
|
|
117
|
-
|
|
855
|
+
const postprocessors = config.postprocessors || [];
|
|
856
|
+
if (postprocessors.length === 0) {
|
|
857
|
+
console.error("❌ No postprocessors found in lua.skill.yaml.");
|
|
858
|
+
process.exit(1);
|
|
859
|
+
}
|
|
860
|
+
// Load bundled postprocessor data
|
|
861
|
+
const postprocessorsPath = path.join(process.cwd(), 'dist', 'postprocessors.json');
|
|
862
|
+
let bundledData = {};
|
|
863
|
+
if (fs.existsSync(postprocessorsPath)) {
|
|
864
|
+
const bundled = JSON.parse(fs.readFileSync(postprocessorsPath, 'utf8'));
|
|
865
|
+
// Select postprocessor
|
|
866
|
+
const answer = await safePrompt([
|
|
867
|
+
{
|
|
868
|
+
type: 'list',
|
|
869
|
+
name: 'selected',
|
|
870
|
+
message: 'Select a postprocessor to push:',
|
|
871
|
+
choices: postprocessors.map((p) => ({
|
|
872
|
+
name: `${p.name} (v${p.version})`,
|
|
873
|
+
value: p
|
|
874
|
+
}))
|
|
875
|
+
}
|
|
876
|
+
]);
|
|
877
|
+
if (!answer)
|
|
878
|
+
return;
|
|
879
|
+
const selected = answer.selected;
|
|
880
|
+
bundledData = bundled.find((p) => p.name === selected.name) || {};
|
|
881
|
+
if (!bundledData || !bundledData.code) {
|
|
882
|
+
console.error(`❌ PostProcessor "${selected.name}" not found in compiled code.`);
|
|
883
|
+
console.log("💡 Please uncomment the postprocessor or remove it from lua.skill.yaml.");
|
|
884
|
+
process.exit(1);
|
|
885
|
+
}
|
|
886
|
+
// Version confirmation
|
|
887
|
+
const confirmedVersion = await promptVersionConfirmOrUpdate(selected.version);
|
|
888
|
+
if (confirmedVersion !== selected.version) {
|
|
889
|
+
writeInfo(`📝 Updating version from ${selected.version} to ${confirmedVersion}`);
|
|
890
|
+
updateProcessorVersionInYaml('postprocessors', selected.name, confirmedVersion);
|
|
891
|
+
}
|
|
892
|
+
const versionData = {
|
|
893
|
+
name: selected.name,
|
|
894
|
+
version: confirmedVersion,
|
|
895
|
+
description: bundledData.description || selected.description,
|
|
896
|
+
context: bundledData.context || selected.context,
|
|
897
|
+
postprocessorId: selected.postprocessorId,
|
|
898
|
+
code: bundledData.code,
|
|
899
|
+
executeFunction: bundledData.executeFunction
|
|
900
|
+
};
|
|
901
|
+
writeProgress(`\n🚀 Pushing ${selected.name} v${confirmedVersion}...`);
|
|
902
|
+
const api = new PostProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
|
|
903
|
+
const result = await api.pushPostProcessor(selected.postprocessorId, versionData);
|
|
904
|
+
if (result.success) {
|
|
905
|
+
writeSuccess(`\n✅ PostProcessor "${selected.name}" v${confirmedVersion} pushed successfully\n`);
|
|
906
|
+
// Ask if user wants to deploy now
|
|
907
|
+
const deployAnswer = await safePrompt([
|
|
908
|
+
{
|
|
909
|
+
type: 'confirm',
|
|
910
|
+
name: 'deployNow',
|
|
911
|
+
message: 'Would you like to deploy this postprocessor version to production now?',
|
|
912
|
+
default: false
|
|
913
|
+
}
|
|
914
|
+
]);
|
|
915
|
+
if (deployAnswer && deployAnswer.deployNow) {
|
|
916
|
+
await deployPostProcessorVersionAfterPush(apiKey, config.agent.agentId, selected, confirmedVersion);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
writeInfo("💡 You can deploy this version later using: lua postprocessors production");
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
console.error(`❌ Failed to push: ${result.error?.message}`);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
catch (error) {
|
|
928
|
+
console.error('❌ Error pushing postprocessor:', error);
|
|
929
|
+
process.exit(1);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Deploy a postprocessor version immediately after pushing
|
|
934
|
+
*/
|
|
935
|
+
async function deployPostProcessorVersionAfterPush(apiKey, agentId, selected, pushedVersion) {
|
|
936
|
+
try {
|
|
937
|
+
// Show warning
|
|
938
|
+
console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
|
|
939
|
+
console.log("⚠️ This will affect ALL users immediately.\n");
|
|
940
|
+
const confirmAnswer = await safePrompt([
|
|
941
|
+
{
|
|
942
|
+
type: 'confirm',
|
|
943
|
+
name: 'confirm',
|
|
944
|
+
message: 'Are you absolutely sure you want to deploy?',
|
|
945
|
+
default: false
|
|
946
|
+
}
|
|
947
|
+
]);
|
|
948
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
949
|
+
console.log("\n❌ Deployment cancelled. Version pushed but not deployed.\n");
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
writeProgress("🔄 Publishing postprocessor version...");
|
|
953
|
+
const api = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
|
|
954
|
+
const publishResponse = await api.publishPostProcessorVersion(selected.postprocessorId, pushedVersion);
|
|
955
|
+
if (!publishResponse.success) {
|
|
956
|
+
console.error(`\n❌ Deploy Error: ${publishResponse.error?.message || 'Unknown error'}\n`);
|
|
957
|
+
throw new Error(publishResponse.error?.message || 'Failed to publish postprocessor version');
|
|
958
|
+
}
|
|
959
|
+
writeSuccess(`\n✅ PostProcessor ${selected.name} v${pushedVersion} deployed successfully to production\n`);
|
|
960
|
+
writeInfo("💡 The new postprocessor version is now active for all users.");
|
|
961
|
+
}
|
|
962
|
+
catch (error) {
|
|
963
|
+
console.error('\n❌ Error deploying postprocessor version:', error);
|
|
964
|
+
console.log('💡 You can deploy later using: lua postprocessors production\n');
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Updates processor version in lua.skill.yaml
|
|
969
|
+
*/
|
|
970
|
+
function updateProcessorVersionInYaml(processorType, processorName, newVersion) {
|
|
971
|
+
try {
|
|
972
|
+
const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
973
|
+
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
974
|
+
const config = yaml.load(yamlContent);
|
|
975
|
+
if (config[processorType]) {
|
|
976
|
+
const processor = config[processorType].find((p) => p.name === processorName);
|
|
977
|
+
if (processor) {
|
|
978
|
+
processor.version = newVersion;
|
|
979
|
+
fs.writeFileSync(yamlPath, yaml.dump(config, { indent: 2, lineWidth: 120, noRefs: true }));
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
catch (error) {
|
|
984
|
+
console.warn('⚠️ Could not update processor version in YAML:', error);
|
|
985
|
+
}
|
|
118
986
|
}
|
|
119
987
|
/**
|
|
120
988
|
* Deploy a version immediately after pushing
|