lua-cli 3.2.0 → 3.4.0

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 (121) hide show
  1. package/dist/api/logs.api.service.d.ts +1 -1
  2. package/dist/api/logs.api.service.js.map +1 -1
  3. package/dist/api/products.api.service.d.ts +17 -5
  4. package/dist/api/products.api.service.js +21 -9
  5. package/dist/api/products.api.service.js.map +1 -1
  6. package/dist/api/webhook.api.service.d.ts +4 -0
  7. package/dist/api/webhook.api.service.js.map +1 -1
  8. package/dist/api-exports.d.ts +19 -7
  9. package/dist/api-exports.js +20 -5
  10. package/dist/api-exports.js.map +1 -1
  11. package/dist/cli/command-definitions.js +323 -88
  12. package/dist/cli/command-definitions.js.map +1 -1
  13. package/dist/commands/apiKey.d.ts +5 -2
  14. package/dist/commands/apiKey.js +8 -2
  15. package/dist/commands/apiKey.js.map +1 -1
  16. package/dist/commands/channels.d.ts +4 -9
  17. package/dist/commands/channels.js +140 -84
  18. package/dist/commands/channels.js.map +1 -1
  19. package/dist/commands/chat.d.ts +4 -2
  20. package/dist/commands/chat.js +126 -32
  21. package/dist/commands/chat.js.map +1 -1
  22. package/dist/commands/chatClear.d.ts +3 -2
  23. package/dist/commands/chatClear.js +16 -15
  24. package/dist/commands/chatClear.js.map +1 -1
  25. package/dist/commands/compile.d.ts +5 -4
  26. package/dist/commands/compile.js +73 -9
  27. package/dist/commands/compile.js.map +1 -1
  28. package/dist/commands/deploy.d.ts +5 -24
  29. package/dist/commands/deploy.js +75 -48
  30. package/dist/commands/deploy.js.map +1 -1
  31. package/dist/commands/destroy.d.ts +5 -2
  32. package/dist/commands/destroy.js +14 -2
  33. package/dist/commands/destroy.js.map +1 -1
  34. package/dist/commands/env.d.ts +3 -1
  35. package/dist/commands/env.js +322 -122
  36. package/dist/commands/env.js.map +1 -1
  37. package/dist/commands/features.d.ts +5 -9
  38. package/dist/commands/features.js +249 -129
  39. package/dist/commands/features.js.map +1 -1
  40. package/dist/commands/init.d.ts +7 -1
  41. package/dist/commands/init.js +242 -59
  42. package/dist/commands/init.js.map +1 -1
  43. package/dist/commands/jobs.d.ts +5 -13
  44. package/dist/commands/jobs.js +523 -360
  45. package/dist/commands/jobs.js.map +1 -1
  46. package/dist/commands/logs.d.ts +5 -10
  47. package/dist/commands/logs.js +259 -103
  48. package/dist/commands/logs.js.map +1 -1
  49. package/dist/commands/marketplace.d.ts +23 -2
  50. package/dist/commands/marketplace.js +530 -7
  51. package/dist/commands/marketplace.js.map +1 -1
  52. package/dist/commands/mcp.d.ts +5 -11
  53. package/dist/commands/mcp.js +304 -294
  54. package/dist/commands/mcp.js.map +1 -1
  55. package/dist/commands/persona.d.ts +5 -9
  56. package/dist/commands/persona.js +349 -232
  57. package/dist/commands/persona.js.map +1 -1
  58. package/dist/commands/postprocessors.d.ts +6 -2
  59. package/dist/commands/postprocessors.js +387 -280
  60. package/dist/commands/postprocessors.js.map +1 -1
  61. package/dist/commands/preprocessors.d.ts +6 -2
  62. package/dist/commands/preprocessors.js +387 -280
  63. package/dist/commands/preprocessors.js.map +1 -1
  64. package/dist/commands/production.d.ts +5 -8
  65. package/dist/commands/production.js +317 -228
  66. package/dist/commands/production.js.map +1 -1
  67. package/dist/commands/push.js +385 -427
  68. package/dist/commands/push.js.map +1 -1
  69. package/dist/commands/resources.d.ts +5 -10
  70. package/dist/commands/resources.js +219 -154
  71. package/dist/commands/resources.js.map +1 -1
  72. package/dist/commands/skills.d.ts +5 -9
  73. package/dist/commands/skills.js +435 -275
  74. package/dist/commands/skills.js.map +1 -1
  75. package/dist/commands/sync.d.ts +10 -8
  76. package/dist/commands/sync.js +110 -19
  77. package/dist/commands/sync.js.map +1 -1
  78. package/dist/commands/test.d.ts +1 -11
  79. package/dist/commands/test.js +395 -438
  80. package/dist/commands/test.js.map +1 -1
  81. package/dist/commands/webhooks.d.ts +5 -11
  82. package/dist/commands/webhooks.js +431 -287
  83. package/dist/commands/webhooks.js.map +1 -1
  84. package/dist/interfaces/index.d.ts +1 -1
  85. package/dist/interfaces/mcp.d.ts +39 -19
  86. package/dist/interfaces/mcp.js +3 -0
  87. package/dist/interfaces/mcp.js.map +1 -1
  88. package/dist/interfaces/product.d.ts +26 -0
  89. package/dist/interfaces/skills.d.ts +5 -0
  90. package/dist/types/api-contracts.d.ts +8 -4
  91. package/dist/types/index.d.ts +1 -1
  92. package/dist/types/index.js.map +1 -1
  93. package/dist/types/skill.d.ts +146 -35
  94. package/dist/types/skill.js +31 -37
  95. package/dist/types/skill.js.map +1 -1
  96. package/dist/utils/bundling.d.ts +17 -0
  97. package/dist/utils/bundling.js +96 -0
  98. package/dist/utils/bundling.js.map +1 -1
  99. package/dist/utils/compile.d.ts +4 -0
  100. package/dist/utils/compile.js +5 -0
  101. package/dist/utils/compile.js.map +1 -1
  102. package/dist/utils/dev-helpers.d.ts +3 -2
  103. package/dist/utils/dev-helpers.js +3 -5
  104. package/dist/utils/dev-helpers.js.map +1 -1
  105. package/dist/utils/job-management.d.ts +4 -1
  106. package/dist/utils/job-management.js +15 -29
  107. package/dist/utils/job-management.js.map +1 -1
  108. package/dist/utils/mcp-server-management.d.ts +5 -2
  109. package/dist/utils/mcp-server-management.js +27 -43
  110. package/dist/utils/mcp-server-management.js.map +1 -1
  111. package/dist/utils/push-helpers.d.ts +1 -1
  112. package/dist/utils/push-helpers.js +5 -1
  113. package/dist/utils/push-helpers.js.map +1 -1
  114. package/dist/utils/skill-management.d.ts +7 -2
  115. package/dist/utils/skill-management.js +21 -30
  116. package/dist/utils/skill-management.js.map +1 -1
  117. package/dist/utils/webhook-management.d.ts +4 -1
  118. package/dist/utils/webhook-management.js +15 -29
  119. package/dist/utils/webhook-management.js.map +1 -1
  120. package/package.json +1 -1
  121. package/template/package.json +1 -1
@@ -8,20 +8,24 @@ import { withErrorHandling, writeProgress, writeSuccess, writeInfo } from '../ut
8
8
  import { BASE_URLS } from '../config/constants.js';
9
9
  import { safePrompt } from '../utils/prompt-handler.js';
10
10
  import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
11
+ import SkillApi from '../api/skills.api.service.js';
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ // Main Command Entry
14
+ // ─────────────────────────────────────────────────────────────────────────────
11
15
  /**
12
- * Main skills command - manages agent skills
16
+ * Main skills command - manages agent skills.
13
17
  *
14
- * Features:
15
- * - Environment selection (sandbox/staging or production)
16
- * - Sandbox: view local skills from configuration
17
- * - Production: view deployed skills, versions, and deploy new versions
18
- *
19
- * @param env - Optional environment argument ('sandbox', 'staging', or 'production')
20
- * @returns Promise that resolves when command completes
18
+ * Supports both interactive and non-interactive modes:
19
+ * - Interactive: prompts for environment and action
20
+ * - Non-interactive: use action argument with -i and -v flags
21
21
  */
22
- export async function skillsCommand(env) {
22
+ export async function skillsCommand(actionOrEnv, cmdObj) {
23
23
  return withErrorHandling(async () => {
24
- // Step 1: Load configuration first (to get agentId)
24
+ const options = {
25
+ skillName: cmdObj?.skillName || null,
26
+ skillVersion: cmdObj?.skillVersion || null,
27
+ };
28
+ // Step 1: Load configuration
25
29
  const config = readSkillConfig();
26
30
  validateConfig(config);
27
31
  validateAgentConfig(config);
@@ -34,62 +38,352 @@ export async function skillsCommand(env) {
34
38
  }
35
39
  await checkApiKey(apiKey);
36
40
  writeProgress("✅ Authenticated");
37
- let selectedEnvironment;
38
- // Step 3: Check if environment was provided as argument
39
- if (env) {
40
- // Normalize the environment (staging is an alias for sandbox)
41
- const normalizedEnv = env.toLowerCase();
42
- if (normalizedEnv === 'sandbox' || normalizedEnv === 'staging') {
43
- selectedEnvironment = 'sandbox';
44
- }
45
- else if (normalizedEnv === 'production') {
46
- selectedEnvironment = 'production';
47
- }
48
- else {
49
- console.error(`❌ Invalid environment: "${env}". Must be "sandbox", "staging", or "production".`);
50
- console.log('\nUsage:');
51
- console.log(' lua skills - Interactive selection');
52
- console.log(' lua skills sandbox - View sandbox skills directly');
53
- console.log(' lua skills staging - View staging skills (alias for sandbox)');
54
- console.log(' lua skills production - Manage production skills directly');
55
- process.exit(1);
41
+ // Step 3: Determine mode based on argument
42
+ const validActions = ['view', 'versions', 'deploy', 'delete'];
43
+ const validEnvs = ['sandbox', 'staging', 'production'];
44
+ if (actionOrEnv) {
45
+ const normalized = actionOrEnv.toLowerCase();
46
+ // Check if it's a non-interactive action
47
+ if (validActions.includes(normalized)) {
48
+ const context = {
49
+ environment: 'production',
50
+ agentId,
51
+ apiKey,
52
+ };
53
+ await executeNonInteractive(context, config, normalized, options);
54
+ return;
56
55
  }
57
- }
58
- else {
59
- // Step 4: Prompt for environment selection
60
- const envAnswer = await safePrompt([
61
- {
62
- type: 'list',
63
- name: 'environment',
64
- message: 'Select environment:',
65
- choices: [
66
- { name: '🔧 Sandbox (local skills)', value: 'sandbox' },
67
- { name: '🚀 Production (deployed skills)', value: 'production' }
68
- ]
56
+ // Check if it's an environment selection
57
+ if (validEnvs.includes(normalized)) {
58
+ const selectedEnvironment = (normalized === 'sandbox' || normalized === 'staging') ? 'sandbox' : 'production';
59
+ const context = {
60
+ environment: selectedEnvironment,
61
+ agentId,
62
+ apiKey,
63
+ };
64
+ if (selectedEnvironment === 'sandbox') {
65
+ await manageSandboxSkillsInteractive(context, config);
66
+ }
67
+ else {
68
+ await manageProductionSkillsInteractive(context, config);
69
69
  }
70
- ]);
71
- if (!envAnswer)
72
70
  return;
73
- selectedEnvironment = envAnswer.environment;
71
+ }
72
+ // Invalid argument
73
+ console.error(`❌ Invalid argument: "${actionOrEnv}"`);
74
+ console.log('\nUsage:');
75
+ console.log(' lua skills Interactive selection');
76
+ console.log(' lua skills sandbox View sandbox skills');
77
+ console.log(' lua skills production Manage production skills');
78
+ console.log(' lua skills view List all production skills');
79
+ console.log(' lua skills versions -i mySkill View versions for a skill');
80
+ console.log(' lua skills deploy -i mySkill -v 1.0.3 Deploy specific version');
81
+ console.log(' lua skills delete -i mySkill Delete a skill from server');
82
+ process.exit(1);
74
83
  }
84
+ // Interactive mode - prompt for environment
85
+ const envAnswer = await safePrompt([
86
+ {
87
+ type: 'list',
88
+ name: 'environment',
89
+ message: 'Select environment:',
90
+ choices: [
91
+ { name: '🔧 Sandbox (local skills)', value: 'sandbox' },
92
+ { name: '🚀 Production (deployed skills)', value: 'production' }
93
+ ]
94
+ }
95
+ ]);
96
+ if (!envAnswer)
97
+ return;
75
98
  const context = {
76
- environment: selectedEnvironment,
99
+ environment: envAnswer.environment,
77
100
  agentId,
78
101
  apiKey,
79
102
  };
80
- // Step 5: Start management based on environment
81
- if (selectedEnvironment === 'sandbox') {
82
- await manageSandboxSkills(context, config);
103
+ if (context.environment === 'sandbox') {
104
+ await manageSandboxSkillsInteractive(context, config);
83
105
  }
84
106
  else {
85
- await manageProductionSkills(context, config);
107
+ await manageProductionSkillsInteractive(context, config);
86
108
  }
87
109
  }, "skills");
88
110
  }
111
+ // ─────────────────────────────────────────────────────────────────────────────
112
+ // Shared Core Functions
113
+ // ─────────────────────────────────────────────────────────────────────────────
114
+ /**
115
+ * Displays all skills with their current status.
116
+ */
117
+ async function displaySkillsCore(context, skills) {
118
+ console.log("\n" + "=".repeat(60));
119
+ console.log("⚙️ Production Skills");
120
+ console.log("=".repeat(60) + "\n");
121
+ for (const skill of skills) {
122
+ try {
123
+ const response = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${skill.skillId}/versions`, {
124
+ method: 'GET',
125
+ headers: {
126
+ 'Authorization': `Bearer ${context.apiKey}`,
127
+ 'Content-Type': 'application/json'
128
+ }
129
+ });
130
+ if (response.ok) {
131
+ const data = await response.json();
132
+ const versions = data.data?.versions || data.versions || [];
133
+ const activeVersionId = data.data?.activeVersionId || data.activeVersionId;
134
+ const activeVersion = versions.find((v) => v.skillId === activeVersionId);
135
+ console.log(`📦 ${skill.name}`);
136
+ console.log(` Skill ID: ${skill.skillId}`);
137
+ if (activeVersion) {
138
+ console.log(` Deployed Version: ${activeVersion.version} ⭐`);
139
+ console.log(` Deployed: ${new Date(activeVersion.createdAt).toLocaleString()}`);
140
+ }
141
+ else {
142
+ console.log(` Deployed Version: Not deployed`);
143
+ }
144
+ console.log(` Total Versions: ${versions.length}`);
145
+ console.log();
146
+ }
147
+ else {
148
+ displaySkillError(skill, "Unable to fetch version info");
149
+ }
150
+ }
151
+ catch {
152
+ displaySkillError(skill, "Error loading versions");
153
+ }
154
+ }
155
+ console.log("=".repeat(60));
156
+ }
157
+ function displaySkillError(skill, status) {
158
+ console.log(`📦 ${skill.name}`);
159
+ console.log(` Skill ID: ${skill.skillId}`);
160
+ console.log(` Status: ${status}`);
161
+ console.log();
162
+ }
163
+ /**
164
+ * Fetches and returns sorted skill versions.
165
+ */
166
+ async function fetchVersionsCore(context, skill) {
167
+ const response = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${skill.skillId}/versions`, {
168
+ method: 'GET',
169
+ headers: {
170
+ 'Authorization': `Bearer ${context.apiKey}`,
171
+ 'Content-Type': 'application/json'
172
+ }
173
+ });
174
+ if (!response.ok) {
175
+ console.error(`❌ Failed to fetch versions: HTTP ${response.status}`);
176
+ return null;
177
+ }
178
+ const data = await response.json();
179
+ const versions = (data.data?.versions || data.versions || []).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
180
+ return { versions, activeVersionId: data.data?.activeVersionId || data.activeVersionId };
181
+ }
182
+ /**
183
+ * Displays versions for a skill.
184
+ */
185
+ function displayVersionsCore(skill, versions, activeVersionId) {
186
+ console.log("\n" + "=".repeat(60));
187
+ console.log(`📜 Versions for ${skill.name}`);
188
+ console.log("=".repeat(60) + "\n");
189
+ versions.forEach((version, index) => {
190
+ const isActive = version.skillId === activeVersionId;
191
+ console.log(`${index + 1}. Version ${version.version}${isActive ? ' ⭐ DEPLOYED' : ''}`);
192
+ console.log(` Created: ${new Date(version.createdAt).toLocaleString()}`);
193
+ console.log(` Version ID: ${version.skillId}`);
194
+ console.log();
195
+ });
196
+ console.log("=".repeat(60));
197
+ }
198
+ /**
199
+ * Deploys a specific version of a skill.
200
+ */
201
+ async function deployVersionCore(context, skill, version) {
202
+ writeProgress(`🔄 Deploying version ${version} of "${skill.name}"...`);
203
+ const deployResponse = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${skill.skillId}/${version}/publish`, {
204
+ method: 'PUT',
205
+ headers: {
206
+ 'Authorization': `Bearer ${context.apiKey}`,
207
+ 'Content-Type': 'application/json'
208
+ }
209
+ });
210
+ if (!deployResponse.ok) {
211
+ const errorText = await deployResponse.text();
212
+ console.error(`❌ Deploy Error: ${deployResponse.status} - ${errorText}`);
213
+ return false;
214
+ }
215
+ writeSuccess(`✅ Version ${version} of "${skill.name}" deployed successfully`);
216
+ writeInfo("💡 The new version is now active for all users.");
217
+ return true;
218
+ }
219
+ /**
220
+ * Deletes a skill from the server.
221
+ * If the skill has versions, it will be deactivated instead of deleted.
222
+ */
223
+ async function deleteSkillCore(context, skill) {
224
+ writeProgress(`🗑️ Deleting skill "${skill.name}"...`);
225
+ const skillApi = new SkillApi(BASE_URLS.API, context.apiKey, context.agentId);
226
+ const response = await skillApi.deleteSkill(skill.skillId);
227
+ if (!response.success || !response.data) {
228
+ console.error(`❌ Delete Error: ${response.error?.message || 'Unknown error'}`);
229
+ return false;
230
+ }
231
+ if (response.data.deleted) {
232
+ writeSuccess(`✅ Skill "${skill.name}" deleted successfully`);
233
+ writeInfo("💡 Remove this skill from your lua.skill.yaml to keep it in sync.");
234
+ }
235
+ else if (response.data.deactivated) {
236
+ writeSuccess(`⚠️ Skill "${skill.name}" has versions and was deactivated instead of deleted`);
237
+ writeInfo("💡 The skill is now inactive and won't be available to the agent.");
238
+ }
239
+ return true;
240
+ }
89
241
  /**
90
- * Manage sandbox skills - view local configuration
242
+ * Resolves a version string to an actual version, supporting "latest".
91
243
  */
92
- async function manageSandboxSkills(context, config) {
244
+ function resolveVersion(versions, versionArg) {
245
+ if (versionArg.toLowerCase() === 'latest') {
246
+ return versions[0].version;
247
+ }
248
+ const exists = versions.some((v) => v.version === versionArg);
249
+ if (!exists) {
250
+ console.error(`❌ Version "${versionArg}" not found`);
251
+ console.log('\nAvailable versions:');
252
+ versions.slice(0, 5).forEach((v) => console.log(` - ${v.version}`));
253
+ return null;
254
+ }
255
+ return versionArg;
256
+ }
257
+ /**
258
+ * Prompts user to select a skill from a list.
259
+ */
260
+ async function promptSkillSelection(skills, message) {
261
+ const answer = await safePrompt([
262
+ {
263
+ type: 'list',
264
+ name: 'selectedSkill',
265
+ message,
266
+ choices: skills.map((skill) => ({
267
+ name: `${skill.name} (${skill.skillId})`,
268
+ value: skill
269
+ }))
270
+ }
271
+ ]);
272
+ return answer?.selectedSkill || null;
273
+ }
274
+ /**
275
+ * Prompts user to select a version from a list.
276
+ */
277
+ async function promptVersionSelection(versions, activeVersionId) {
278
+ const answer = await safePrompt([
279
+ {
280
+ type: 'list',
281
+ name: 'selectedVersion',
282
+ message: 'Select a version to deploy:',
283
+ choices: versions.map((version) => {
284
+ const isActive = version.skillId === activeVersionId;
285
+ return {
286
+ name: `Version ${version.version} (${new Date(version.createdAt).toLocaleDateString()})${isActive ? ' ⭐ CURRENT' : ''}`,
287
+ value: version
288
+ };
289
+ })
290
+ }
291
+ ]);
292
+ return answer?.selectedVersion || null;
293
+ }
294
+ // ─────────────────────────────────────────────────────────────────────────────
295
+ // Non-Interactive Mode
296
+ // ─────────────────────────────────────────────────────────────────────────────
297
+ async function executeNonInteractive(context, config, action, options) {
298
+ const skills = config.skills || [];
299
+ // View action doesn't require skill selection
300
+ if (action === 'view') {
301
+ if (skills.length === 0) {
302
+ console.log("ℹ️ No skills found in configuration.");
303
+ return;
304
+ }
305
+ await displaySkillsCore(context, skills);
306
+ return;
307
+ }
308
+ // All other actions require skill selection
309
+ if (!options.skillName) {
310
+ console.error(`❌ --skill-name is required for action "${action}"`);
311
+ console.log(`\nUsage: lua skills ${action} --skill-name <name>`);
312
+ process.exit(1);
313
+ }
314
+ let selectedSkill = skills.find((s) => s.skillId === options.skillName || s.name === options.skillName);
315
+ // For delete action, also check server skills (for orphaned skills not in local YAML)
316
+ if (!selectedSkill && action === 'delete') {
317
+ const skillApi = new SkillApi(BASE_URLS.API, context.apiKey, context.agentId);
318
+ const serverResponse = await skillApi.getSkills();
319
+ if (serverResponse.success && serverResponse.data?.skills) {
320
+ const serverSkill = serverResponse.data.skills.find((s) => s.id === options.skillName || s.name === options.skillName);
321
+ if (serverSkill) {
322
+ // Map server skill format to local format for deleteSkillCore
323
+ selectedSkill = {
324
+ name: serverSkill.name,
325
+ skillId: serverSkill.id,
326
+ };
327
+ }
328
+ }
329
+ }
330
+ if (!selectedSkill) {
331
+ console.error(`❌ Skill "${options.skillName}" not found`);
332
+ console.log('\nAvailable skills in local config:');
333
+ skills.forEach((s) => console.log(` - ${s.name} (${s.skillId})`));
334
+ if (action === 'delete') {
335
+ console.log('\n💡 Tip: The skill may have already been deleted from the server.');
336
+ }
337
+ process.exit(1);
338
+ }
339
+ switch (action) {
340
+ case 'versions': {
341
+ const data = await fetchVersionsCore(context, selectedSkill);
342
+ if (!data)
343
+ process.exit(1);
344
+ if (data.versions.length === 0) {
345
+ console.log(`ℹ️ No versions found for ${selectedSkill.name}.`);
346
+ console.log("💡 Push a version first using 'lua push skill'.");
347
+ return;
348
+ }
349
+ displayVersionsCore(selectedSkill, data.versions, data.activeVersionId);
350
+ break;
351
+ }
352
+ case 'deploy': {
353
+ if (!options.skillVersion) {
354
+ console.error('❌ --skill-version is required for deploy action');
355
+ console.log('\nUsage: lua skills deploy --skill-name mySkill --skill-version 1.0.3');
356
+ console.log(' lua skills deploy -i mySkill -v latest');
357
+ process.exit(1);
358
+ }
359
+ const data = await fetchVersionsCore(context, selectedSkill);
360
+ if (!data)
361
+ process.exit(1);
362
+ if (data.versions.length === 0) {
363
+ console.error(`❌ No versions found for ${selectedSkill.name}.`);
364
+ console.log("💡 Push a version first using 'lua push skill'.");
365
+ process.exit(1);
366
+ }
367
+ const resolvedVersion = resolveVersion(data.versions, options.skillVersion);
368
+ if (!resolvedVersion)
369
+ process.exit(1);
370
+ const success = await deployVersionCore(context, selectedSkill, resolvedVersion);
371
+ if (!success)
372
+ process.exit(1);
373
+ break;
374
+ }
375
+ case 'delete': {
376
+ const success = await deleteSkillCore(context, selectedSkill);
377
+ if (!success)
378
+ process.exit(1);
379
+ break;
380
+ }
381
+ }
382
+ }
383
+ // ─────────────────────────────────────────────────────────────────────────────
384
+ // Interactive Mode
385
+ // ─────────────────────────────────────────────────────────────────────────────
386
+ async function manageSandboxSkillsInteractive(context, config) {
93
387
  let continueManaging = true;
94
388
  while (continueManaging) {
95
389
  console.log("\n" + "=".repeat(60));
@@ -127,7 +421,6 @@ async function manageSandboxSkills(context, config) {
127
421
  const { action } = actionAnswer;
128
422
  switch (action) {
129
423
  case 'refresh':
130
- // Reload config
131
424
  const newConfig = readSkillConfig();
132
425
  config.skills = newConfig.skills;
133
426
  break;
@@ -146,10 +439,7 @@ async function manageSandboxSkills(context, config) {
146
439
  }
147
440
  }
148
441
  }
149
- /**
150
- * Manage production skills - view and deploy versions
151
- */
152
- async function manageProductionSkills(context, config) {
442
+ async function manageProductionSkillsInteractive(context, config) {
153
443
  let continueManaging = true;
154
444
  while (continueManaging) {
155
445
  console.log("\n" + "=".repeat(60));
@@ -164,6 +454,7 @@ async function manageProductionSkills(context, config) {
164
454
  { name: '👁️ View deployed skills', value: 'view' },
165
455
  { name: '📜 View skill versions', value: 'versions' },
166
456
  { name: '🚀 Deploy a version', value: 'deploy' },
457
+ { name: '🗑️ Delete a skill', value: 'delete' },
167
458
  { name: '❌ Exit', value: 'exit' }
168
459
  ]
169
460
  }
@@ -173,13 +464,16 @@ async function manageProductionSkills(context, config) {
173
464
  const { action } = actionAnswer;
174
465
  switch (action) {
175
466
  case 'view':
176
- await viewDeployedSkills(context, config);
467
+ await viewSkillsInteractive(context, config);
177
468
  break;
178
469
  case 'versions':
179
- await viewSkillVersions(context, config);
470
+ await viewVersionsInteractive(context, config);
180
471
  break;
181
472
  case 'deploy':
182
- await deploySkillVersion(context, config);
473
+ await deployVersionInteractive(context, config);
474
+ break;
475
+ case 'delete':
476
+ await deleteSkillInteractive(context, config);
183
477
  break;
184
478
  case 'exit':
185
479
  continueManaging = false;
@@ -188,251 +482,117 @@ async function manageProductionSkills(context, config) {
188
482
  }
189
483
  }
190
484
  }
191
- /**
192
- * View deployed skills in production
193
- */
194
- async function viewDeployedSkills(context, config) {
485
+ async function viewSkillsInteractive(context, config) {
195
486
  writeProgress("🔄 Loading skill information...");
196
- try {
197
- const skills = config.skills || [];
198
- if (skills.length === 0) {
199
- console.log("\nℹ️ No skills found in configuration.\n");
200
- await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
201
- return;
202
- }
203
- console.log("\n" + "=".repeat(60));
204
- console.log("⚙️ Production Skills");
205
- console.log("=".repeat(60) + "\n");
206
- // Fetch version info for each skill
207
- for (const skill of skills) {
208
- try {
209
- const response = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${skill.skillId}/versions`, {
210
- method: 'GET',
211
- headers: {
212
- 'Authorization': `Bearer ${context.apiKey}`,
213
- 'Content-Type': 'application/json'
214
- }
215
- });
216
- if (response.ok) {
217
- const data = await response.json();
218
- const versions = data.data?.versions || data.versions || [];
219
- const activeVersionId = data.data?.activeVersionId || data.activeVersionId;
220
- // Find active version
221
- const activeVersion = versions.find((v) => v.skillId === activeVersionId);
222
- console.log(`📦 ${skill.name}`);
223
- console.log(` Skill ID: ${skill.skillId}`);
224
- if (activeVersion) {
225
- console.log(` Deployed Version: ${activeVersion.version} ⭐`);
226
- const date = new Date(activeVersion.createdAt);
227
- console.log(` Deployed: ${date.toLocaleString()}`);
228
- }
229
- else {
230
- console.log(` Deployed Version: Not deployed`);
231
- }
232
- console.log(` Total Versions: ${versions.length}`);
233
- console.log();
234
- }
235
- else {
236
- console.log(`📦 ${skill.name}`);
237
- console.log(` Skill ID: ${skill.skillId}`);
238
- console.log(` Status: Unable to fetch version info`);
239
- console.log();
240
- }
241
- }
242
- catch (error) {
243
- console.log(`📦 ${skill.name}`);
244
- console.log(` Skill ID: ${skill.skillId}`);
245
- console.log(` Status: Error loading versions`);
246
- console.log();
247
- }
248
- }
249
- console.log("=".repeat(60) + "\n");
487
+ const skills = config.skills || [];
488
+ if (skills.length === 0) {
489
+ console.log("\nℹ️ No skills found in configuration.\n");
490
+ }
491
+ else {
492
+ await displaySkillsCore(context, skills);
493
+ console.log();
494
+ }
495
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
496
+ }
497
+ async function viewVersionsInteractive(context, config) {
498
+ const skills = config.skills || [];
499
+ if (skills.length === 0) {
500
+ console.log("\nℹ️ No skills found in configuration.\n");
250
501
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
502
+ return;
251
503
  }
252
- catch (error) {
253
- console.error('❌ Error loading skill information:', error);
504
+ const selectedSkill = await promptSkillSelection(skills, 'Select a skill to view versions:');
505
+ if (!selectedSkill)
506
+ return;
507
+ writeProgress(`🔄 Loading versions for ${selectedSkill.name}...`);
508
+ const data = await fetchVersionsCore(context, selectedSkill);
509
+ if (!data) {
254
510
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
511
+ return;
512
+ }
513
+ if (data.versions.length === 0) {
514
+ console.log(`\nℹ️ No versions found for ${selectedSkill.name}.\n`);
515
+ console.log("💡 Push a version first using 'lua push skill'.\n");
516
+ }
517
+ else {
518
+ displayVersionsCore(selectedSkill, data.versions, data.activeVersionId);
519
+ console.log();
255
520
  }
521
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
256
522
  }
257
- /**
258
- * View versions for a specific skill
259
- */
260
- async function viewSkillVersions(context, config) {
523
+ async function deployVersionInteractive(context, config) {
261
524
  const skills = config.skills || [];
262
525
  if (skills.length === 0) {
263
526
  console.log("\nℹ️ No skills found in configuration.\n");
264
527
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
265
528
  return;
266
529
  }
267
- // Prompt to select a skill
268
- const skillAnswer = await safePrompt([
269
- {
270
- type: 'list',
271
- name: 'selectedSkill',
272
- message: 'Select a skill to view versions:',
273
- choices: skills.map((skill) => ({
274
- name: `${skill.name} (${skill.skillId})`,
275
- value: skill
276
- }))
277
- }
278
- ]);
279
- if (!skillAnswer)
530
+ const selectedSkill = await promptSkillSelection(skills, 'Select a skill to deploy:');
531
+ if (!selectedSkill)
280
532
  return;
281
- const selectedSkill = skillAnswer.selectedSkill;
282
533
  writeProgress(`🔄 Loading versions for ${selectedSkill.name}...`);
283
- try {
284
- const response = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${selectedSkill.skillId}/versions`, {
285
- method: 'GET',
286
- headers: {
287
- 'Authorization': `Bearer ${context.apiKey}`,
288
- 'Content-Type': 'application/json'
289
- }
290
- });
291
- if (!response.ok) {
292
- throw new Error(`HTTP error! status: ${response.status}`);
293
- }
294
- const data = await response.json();
295
- const versions = data.data?.versions || data.versions || [];
296
- const activeVersionId = data.data?.activeVersionId || data.activeVersionId;
297
- if (versions.length === 0) {
298
- console.log(`\nℹ️ No versions found for ${selectedSkill.name}.\n`);
299
- console.log("💡 Push a version first using 'lua push skill'.\n");
300
- await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
301
- return;
302
- }
303
- console.log("\n" + "=".repeat(60));
304
- console.log(`📜 Versions for ${selectedSkill.name}`);
305
- console.log("=".repeat(60) + "\n");
306
- // Sort versions by date (newest first)
307
- const sortedVersions = versions.sort((a, b) => {
308
- const dateA = new Date(a.createdAt).getTime();
309
- const dateB = new Date(b.createdAt).getTime();
310
- return dateB - dateA;
311
- });
312
- sortedVersions.forEach((version, index) => {
313
- const isActive = version.skillId === activeVersionId;
314
- const date = new Date(version.createdAt);
315
- console.log(`${index + 1}. Version ${version.version}${isActive ? ' ⭐ DEPLOYED' : ''}`);
316
- console.log(` Created: ${date.toLocaleString()}`);
317
- console.log(` Version ID: ${version.skillId}`);
318
- console.log();
319
- });
320
- console.log("=".repeat(60) + "\n");
534
+ const data = await fetchVersionsCore(context, selectedSkill);
535
+ if (!data) {
321
536
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
537
+ return;
322
538
  }
323
- catch (error) {
324
- console.error('❌ Error loading versions:', error);
539
+ if (data.versions.length === 0) {
540
+ console.log(`\nℹ️ No versions found for ${selectedSkill.name}.\n`);
541
+ console.log("💡 Push a version first using 'lua push skill'.\n");
325
542
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
543
+ return;
544
+ }
545
+ const selectedVersion = await promptVersionSelection(data.versions, data.activeVersionId);
546
+ if (!selectedVersion)
547
+ return;
548
+ // Show warning and confirm
549
+ console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
550
+ console.log("⚠️ This will affect ALL users immediately.\n");
551
+ console.log(`Skill: ${selectedSkill.name}`);
552
+ console.log(`Version: ${selectedVersion.version}\n`);
553
+ const confirmAnswer = await safePrompt([
554
+ {
555
+ type: 'confirm',
556
+ name: 'confirm',
557
+ message: 'Are you absolutely sure you want to deploy this version?',
558
+ default: false
559
+ }
560
+ ]);
561
+ if (!confirmAnswer || !confirmAnswer.confirm) {
562
+ console.log("\n❌ Deployment cancelled.\n");
563
+ return;
326
564
  }
565
+ await deployVersionCore(context, selectedSkill, selectedVersion.version);
566
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
327
567
  }
328
- /**
329
- * Deploy a skill version to production
330
- */
331
- async function deploySkillVersion(context, config) {
568
+ async function deleteSkillInteractive(context, config) {
332
569
  const skills = config.skills || [];
333
570
  if (skills.length === 0) {
334
571
  console.log("\nℹ️ No skills found in configuration.\n");
335
572
  await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
336
573
  return;
337
574
  }
338
- // Prompt to select a skill
339
- const skillAnswer = await safePrompt([
575
+ const selectedSkill = await promptSkillSelection(skills, 'Select a skill to delete:');
576
+ if (!selectedSkill)
577
+ return;
578
+ // Show warning and confirm
579
+ console.log("\n⚠️ WARNING: You are about to delete a skill!");
580
+ console.log("⚠️ If the skill has versions, it will be deactivated instead.\n");
581
+ console.log(`Skill: ${selectedSkill.name}`);
582
+ console.log(`Skill ID: ${selectedSkill.skillId}\n`);
583
+ const confirmAnswer = await safePrompt([
340
584
  {
341
- type: 'list',
342
- name: 'selectedSkill',
343
- message: 'Select a skill to deploy:',
344
- choices: skills.map((skill) => ({
345
- name: `${skill.name} (${skill.skillId})`,
346
- value: skill
347
- }))
585
+ type: 'confirm',
586
+ name: 'confirm',
587
+ message: 'Are you sure you want to delete this skill?',
588
+ default: false
348
589
  }
349
590
  ]);
350
- if (!skillAnswer)
591
+ if (!confirmAnswer || !confirmAnswer.confirm) {
592
+ console.log("\n❌ Deletion cancelled.\n");
351
593
  return;
352
- const selectedSkill = skillAnswer.selectedSkill;
353
- writeProgress(`🔄 Loading versions for ${selectedSkill.name}...`);
354
- try {
355
- const response = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${selectedSkill.skillId}/versions`, {
356
- method: 'GET',
357
- headers: {
358
- 'Authorization': `Bearer ${context.apiKey}`,
359
- 'Content-Type': 'application/json'
360
- }
361
- });
362
- if (!response.ok) {
363
- throw new Error(`HTTP error! status: ${response.status}`);
364
- }
365
- const data = await response.json();
366
- const versions = data.data?.versions || data.versions || [];
367
- const activeVersionId = data.data?.activeVersionId || data.activeVersionId;
368
- if (versions.length === 0) {
369
- console.log(`\nℹ️ No versions found for ${selectedSkill.name}.\n`);
370
- console.log("💡 Push a version first using 'lua push skill'.\n");
371
- await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
372
- return;
373
- }
374
- // Sort versions by date (newest first)
375
- const sortedVersions = versions.sort((a, b) => {
376
- const dateA = new Date(a.createdAt).getTime();
377
- const dateB = new Date(b.createdAt).getTime();
378
- return dateB - dateA;
379
- });
380
- // Prompt to select a version
381
- const versionAnswer = await safePrompt([
382
- {
383
- type: 'list',
384
- name: 'selectedVersion',
385
- message: 'Select a version to deploy:',
386
- choices: sortedVersions.map((version) => {
387
- const isActive = version.skillId === activeVersionId;
388
- const date = new Date(version.createdAt);
389
- return {
390
- name: `Version ${version.version} (${date.toLocaleDateString()})${isActive ? ' ⭐ CURRENT' : ''}`,
391
- value: version
392
- };
393
- })
394
- }
395
- ]);
396
- if (!versionAnswer)
397
- return;
398
- const selectedVersion = versionAnswer.selectedVersion;
399
- // Show warning
400
- console.log("\n⚠️ WARNING: You are about to deploy to PRODUCTION!");
401
- console.log("⚠️ This will affect ALL users immediately.\n");
402
- console.log(`Skill: ${selectedSkill.name}`);
403
- console.log(`Version: ${selectedVersion.version}\n`);
404
- const confirmAnswer = await safePrompt([
405
- {
406
- type: 'confirm',
407
- name: 'confirm',
408
- message: 'Are you absolutely sure you want to deploy this version?',
409
- default: false
410
- }
411
- ]);
412
- if (!confirmAnswer || !confirmAnswer.confirm) {
413
- console.log("\n❌ Deployment cancelled.\n");
414
- return;
415
- }
416
- writeProgress("🔄 Deploying version...");
417
- const deployResponse = await fetch(`${BASE_URLS.API}/developer/skills/${context.agentId}/${selectedSkill.skillId}/${selectedVersion.version}/publish`, {
418
- method: 'PUT',
419
- headers: {
420
- 'Authorization': `Bearer ${context.apiKey}`,
421
- 'Content-Type': 'application/json'
422
- }
423
- });
424
- if (!deployResponse.ok) {
425
- const errorText = await deployResponse.text();
426
- console.error(`\n❌ Deploy Error: ${deployResponse.status} - ${errorText}\n`);
427
- throw new Error(`HTTP error! status: ${deployResponse.status}`);
428
- }
429
- writeSuccess(`\n✅ Version ${selectedVersion.version} of "${selectedSkill.name}" deployed successfully to production\n`);
430
- writeInfo("💡 The new version is now active for all users.");
431
- await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
432
- }
433
- catch (error) {
434
- console.error('\n❌ Error deploying version:', error);
435
- await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
436
594
  }
595
+ await deleteSkillCore(context, selectedSkill);
596
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
437
597
  }
438
598
  //# sourceMappingURL=skills.js.map