lua-cli 2.5.7 → 2.5.8

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 (37) hide show
  1. package/dist/api/agent.api.service.d.ts +45 -0
  2. package/dist/api/agent.api.service.js +54 -0
  3. package/dist/api/user.data.api.service.d.ts +15 -0
  4. package/dist/api/user.data.api.service.js +31 -0
  5. package/dist/cli/command-definitions.js +77 -5
  6. package/dist/commands/completion.d.ts +11 -0
  7. package/dist/commands/completion.js +209 -0
  8. package/dist/commands/env.d.ts +3 -2
  9. package/dist/commands/env.js +42 -17
  10. package/dist/commands/features.d.ts +16 -0
  11. package/dist/commands/features.js +352 -0
  12. package/dist/commands/index.d.ts +3 -0
  13. package/dist/commands/index.js +3 -0
  14. package/dist/commands/persona.d.ts +3 -2
  15. package/dist/commands/persona.js +43 -18
  16. package/dist/commands/push.d.ts +9 -13
  17. package/dist/commands/push.js +271 -82
  18. package/dist/commands/skills.d.ts +16 -0
  19. package/dist/commands/skills.js +438 -0
  20. package/dist/common/data.entry.instance.d.ts +7 -0
  21. package/dist/common/data.entry.instance.js +15 -0
  22. package/dist/common/order.instance.d.ts +6 -0
  23. package/dist/common/order.instance.js +14 -0
  24. package/dist/common/product.instance.d.ts +6 -0
  25. package/dist/common/product.instance.js +14 -0
  26. package/dist/common/user.instance.d.ts +14 -0
  27. package/dist/common/user.instance.js +29 -0
  28. package/dist/index.js +14 -3
  29. package/dist/interfaces/agent.d.ts +31 -0
  30. package/dist/interfaces/message.d.ts +18 -0
  31. package/dist/interfaces/message.js +1 -0
  32. package/dist/types/api-contracts.d.ts +9 -0
  33. package/dist/types/api-contracts.js +0 -7
  34. package/dist/web/app.css +152 -736
  35. package/dist/web/app.js +45 -45
  36. package/package.json +2 -2
  37. package/template/package.json +1 -1
@@ -0,0 +1,438 @@
1
+ /**
2
+ * Skills Command
3
+ * Manages agent skills for sandbox and production environments
4
+ */
5
+ import { loadApiKey, checkApiKey } from '../services/auth.js';
6
+ import { readSkillConfig } from '../utils/files.js';
7
+ import { withErrorHandling, writeProgress, writeSuccess, writeInfo } from '../utils/cli.js';
8
+ import { BASE_URLS } from '../config/constants.js';
9
+ import { safePrompt } from '../utils/prompt-handler.js';
10
+ import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
11
+ /**
12
+ * Main skills command - manages agent skills
13
+ *
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
21
+ */
22
+ export async function skillsCommand(env) {
23
+ return withErrorHandling(async () => {
24
+ // Step 1: Load configuration first (to get agentId)
25
+ const config = readSkillConfig();
26
+ validateConfig(config);
27
+ validateAgentConfig(config);
28
+ const agentId = config.agent.agentId;
29
+ // Step 2: Authenticate
30
+ const apiKey = await loadApiKey();
31
+ if (!apiKey) {
32
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
33
+ process.exit(1);
34
+ }
35
+ await checkApiKey(apiKey);
36
+ 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);
56
+ }
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
+ ]
69
+ }
70
+ ]);
71
+ if (!envAnswer)
72
+ return;
73
+ selectedEnvironment = envAnswer.environment;
74
+ }
75
+ const context = {
76
+ environment: selectedEnvironment,
77
+ agentId,
78
+ apiKey,
79
+ };
80
+ // Step 5: Start management based on environment
81
+ if (selectedEnvironment === 'sandbox') {
82
+ await manageSandboxSkills(context, config);
83
+ }
84
+ else {
85
+ await manageProductionSkills(context, config);
86
+ }
87
+ }, "skills");
88
+ }
89
+ /**
90
+ * Manage sandbox skills - view local configuration
91
+ */
92
+ async function manageSandboxSkills(context, config) {
93
+ let continueManaging = true;
94
+ while (continueManaging) {
95
+ console.log("\n" + "=".repeat(60));
96
+ console.log("🔧 Sandbox Skills");
97
+ console.log("=".repeat(60) + "\n");
98
+ const skills = config.skills || [];
99
+ if (skills.length === 0) {
100
+ console.log("ℹ️ No skills found in configuration.");
101
+ console.log("💡 Run 'lua compile' to add skills to your configuration.\n");
102
+ }
103
+ else {
104
+ console.log("Local skills in lua.skill.yaml:\n");
105
+ skills.forEach((skill, index) => {
106
+ console.log(`${index + 1}. 📦 ${skill.name}`);
107
+ console.log(` Version: ${skill.version}`);
108
+ console.log(` Skill ID: ${skill.skillId}`);
109
+ console.log();
110
+ });
111
+ }
112
+ const actionAnswer = await safePrompt([
113
+ {
114
+ type: 'list',
115
+ name: 'action',
116
+ message: 'What would you like to do?',
117
+ choices: [
118
+ { name: '🔄 Refresh list', value: 'refresh' },
119
+ { name: '📦 Compile skills', value: 'compile' },
120
+ { name: '☁️ Push a skill', value: 'push' },
121
+ { name: '❌ Exit', value: 'exit' }
122
+ ]
123
+ }
124
+ ]);
125
+ if (!actionAnswer)
126
+ return;
127
+ const { action } = actionAnswer;
128
+ switch (action) {
129
+ case 'refresh':
130
+ // Reload config
131
+ const newConfig = readSkillConfig();
132
+ config.skills = newConfig.skills;
133
+ break;
134
+ case 'compile':
135
+ console.log("\n💡 Run 'lua compile' in your terminal to compile your skills.\n");
136
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
137
+ break;
138
+ case 'push':
139
+ console.log("\n💡 Run 'lua push skill' in your terminal to push a skill.\n");
140
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
141
+ break;
142
+ case 'exit':
143
+ continueManaging = false;
144
+ console.log("\n👋 Goodbye!\n");
145
+ break;
146
+ }
147
+ }
148
+ }
149
+ /**
150
+ * Manage production skills - view and deploy versions
151
+ */
152
+ async function manageProductionSkills(context, config) {
153
+ let continueManaging = true;
154
+ while (continueManaging) {
155
+ console.log("\n" + "=".repeat(60));
156
+ console.log("🚀 Production Skills");
157
+ console.log("=".repeat(60) + "\n");
158
+ const actionAnswer = await safePrompt([
159
+ {
160
+ type: 'list',
161
+ name: 'action',
162
+ message: 'What would you like to do?',
163
+ choices: [
164
+ { name: '👁️ View deployed skills', value: 'view' },
165
+ { name: '📜 View skill versions', value: 'versions' },
166
+ { name: '🚀 Deploy a version', value: 'deploy' },
167
+ { name: '❌ Exit', value: 'exit' }
168
+ ]
169
+ }
170
+ ]);
171
+ if (!actionAnswer)
172
+ return;
173
+ const { action } = actionAnswer;
174
+ switch (action) {
175
+ case 'view':
176
+ await viewDeployedSkills(context, config);
177
+ break;
178
+ case 'versions':
179
+ await viewSkillVersions(context, config);
180
+ break;
181
+ case 'deploy':
182
+ await deploySkillVersion(context, config);
183
+ break;
184
+ case 'exit':
185
+ continueManaging = false;
186
+ console.log("\n👋 Goodbye!\n");
187
+ break;
188
+ }
189
+ }
190
+ }
191
+ /**
192
+ * View deployed skills in production
193
+ */
194
+ async function viewDeployedSkills(context, config) {
195
+ 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");
250
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
251
+ }
252
+ catch (error) {
253
+ console.error('❌ Error loading skill information:', error);
254
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
255
+ }
256
+ }
257
+ /**
258
+ * View versions for a specific skill
259
+ */
260
+ async function viewSkillVersions(context, config) {
261
+ const skills = config.skills || [];
262
+ if (skills.length === 0) {
263
+ console.log("\nℹ️ No skills found in configuration.\n");
264
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
265
+ return;
266
+ }
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)
280
+ return;
281
+ const selectedSkill = skillAnswer.selectedSkill;
282
+ 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");
321
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
322
+ }
323
+ catch (error) {
324
+ console.error('❌ Error loading versions:', error);
325
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
326
+ }
327
+ }
328
+ /**
329
+ * Deploy a skill version to production
330
+ */
331
+ async function deploySkillVersion(context, config) {
332
+ const skills = config.skills || [];
333
+ if (skills.length === 0) {
334
+ console.log("\nℹ️ No skills found in configuration.\n");
335
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
336
+ return;
337
+ }
338
+ // Prompt to select a skill
339
+ const skillAnswer = await safePrompt([
340
+ {
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
+ }))
348
+ }
349
+ ]);
350
+ if (!skillAnswer)
351
+ 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: 'POST',
419
+ headers: {
420
+ 'Authorization': `Bearer ${context.apiKey}`,
421
+ 'Content-Type': 'application/json'
422
+ },
423
+ body: JSON.stringify({})
424
+ });
425
+ if (!deployResponse.ok) {
426
+ const errorText = await deployResponse.text();
427
+ console.error(`\n❌ Deploy Error: ${deployResponse.status} - ${errorText}\n`);
428
+ throw new Error(`HTTP error! status: ${deployResponse.status}`);
429
+ }
430
+ writeSuccess(`\n✅ Version ${selectedVersion.version} of "${selectedSkill.name}" deployed successfully to production\n`);
431
+ writeInfo("💡 The new version is now active for all users.");
432
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
433
+ }
434
+ catch (error) {
435
+ console.error('\n❌ Error deploying version:', error);
436
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
437
+ }
438
+ }
@@ -39,4 +39,11 @@ export default class DataEntryInstance {
39
39
  * @throws Error if the deletion fails
40
40
  */
41
41
  delete(): Promise<boolean>;
42
+ /**
43
+ * Saves the data entry
44
+ * @param searchText - Optional search text for vector search indexing
45
+ * @returns Promise resolving to true if saving was successful
46
+ * @throws Error if the save operation fails
47
+ */
48
+ save(searchText?: string): Promise<boolean>;
42
49
  }
@@ -144,4 +144,19 @@ export default class DataEntryInstance {
144
144
  throw new Error('Failed to clear user data');
145
145
  }
146
146
  }
147
+ /**
148
+ * Saves the data entry
149
+ * @param searchText - Optional search text for vector search indexing
150
+ * @returns Promise resolving to true if saving was successful
151
+ * @throws Error if the save operation fails
152
+ */
153
+ async save(searchText) {
154
+ try {
155
+ await this.customDataAPI.update(this.collectionName, this.id, { data: this.data, searchText: searchText });
156
+ return true;
157
+ }
158
+ catch (error) {
159
+ throw new Error('Failed to save data entry');
160
+ }
161
+ }
147
162
  }
@@ -40,4 +40,10 @@ export default class OrderInstance {
40
40
  * @throws Error if the data update fails
41
41
  */
42
42
  update(data: Record<string, any>): Promise<any>;
43
+ /**
44
+ * Saves the order's data
45
+ * @returns Promise resolving to true if saving was successful
46
+ * @throws Error if the save operation fails
47
+ */
48
+ save(): Promise<boolean>;
43
49
  }
@@ -170,4 +170,18 @@ export default class OrderInstance {
170
170
  id: this.id
171
171
  };
172
172
  }
173
+ /**
174
+ * Saves the order's data
175
+ * @returns Promise resolving to true if saving was successful
176
+ * @throws Error if the save operation fails
177
+ */
178
+ async save() {
179
+ try {
180
+ await this.orderAPI.updateData(this.data, this.id);
181
+ return true;
182
+ }
183
+ catch (error) {
184
+ throw new Error('Failed to save order data');
185
+ }
186
+ }
173
187
  }
@@ -33,4 +33,10 @@ export default class ProductInstance {
33
33
  * @throws Error if the deletion fails or the product is not found
34
34
  */
35
35
  delete(): Promise<Product>;
36
+ /**
37
+ * Saves the product's data
38
+ * @returns Promise resolving to true if saving was successful
39
+ * @throws Error if the save operation fails
40
+ */
41
+ save(): Promise<boolean>;
36
42
  }
@@ -127,4 +127,18 @@ export default class ProductInstance {
127
127
  }
128
128
  return this.data;
129
129
  }
130
+ /**
131
+ * Saves the product's data
132
+ * @returns Promise resolving to true if saving was successful
133
+ * @throws Error if the save operation fails
134
+ */
135
+ async save() {
136
+ try {
137
+ await this.productAPI.update(this.data, this.data.id);
138
+ return true;
139
+ }
140
+ catch (error) {
141
+ throw new Error('Failed to save product data');
142
+ }
143
+ }
130
144
  }
@@ -1,3 +1,4 @@
1
+ import { Message } from "../interfaces/message.js";
1
2
  import { UserDataAPI } from "../types/index.js";
2
3
  /**
3
4
  * User data instance class providing a fluent API for managing user data
@@ -33,4 +34,17 @@ export default class UserDataInstance {
33
34
  * @throws Error if the clear operation fails
34
35
  */
35
36
  clear(): Promise<boolean>;
37
+ /**
38
+ * Saves the user's data
39
+ * @returns Promise resolving to true if saving was successful
40
+ * @throws Error if the save operation fails
41
+ */
42
+ save(): Promise<boolean>;
43
+ /**
44
+ * Sends a message to a specific user conversation for the agent
45
+ * @param messages - An array of messages to send (can be text, image, or file types)
46
+ * @returns Promise resolving to the response data from the server
47
+ * @throws Error if the message sending fails or the request is unsuccessful
48
+ */
49
+ send(messages: Message[]): Promise<any>;
36
50
  }
@@ -129,4 +129,33 @@ export default class UserDataInstance {
129
129
  throw new Error('Failed to clear user data');
130
130
  }
131
131
  }
132
+ /**
133
+ * Saves the user's data
134
+ * @returns Promise resolving to true if saving was successful
135
+ * @throws Error if the save operation fails
136
+ */
137
+ async save() {
138
+ try {
139
+ await this.userAPI.update(this.data);
140
+ return true;
141
+ }
142
+ catch (error) {
143
+ throw new Error('Failed to save user data');
144
+ }
145
+ }
146
+ /**
147
+ * Sends a message to a specific user conversation for the agent
148
+ * @param messages - An array of messages to send (can be text, image, or file types)
149
+ * @returns Promise resolving to the response data from the server
150
+ * @throws Error if the message sending fails or the request is unsuccessful
151
+ */
152
+ async send(messages) {
153
+ try {
154
+ await this.userAPI.sendMessage(messages);
155
+ return true;
156
+ }
157
+ catch (error) {
158
+ throw new Error('Failed to send message');
159
+ }
160
+ }
132
161
  }
package/dist/index.js CHANGED
@@ -37,13 +37,24 @@ Examples:
37
37
  $ lua init 🚀 Initialize a new project
38
38
  $ lua compile 📦 Compile your skills
39
39
  $ lua test 🧪 Test tools interactively
40
- $ lua push ☁️ Push to server
40
+ $ lua push ☁️ Push to server (interactive)
41
+ $ lua push skill ☁️ Push skill directly
42
+ $ lua push persona ☁️ Push persona directly
41
43
  $ lua deploy 🚀 Deploy to production
42
44
  $ lua chat 💬 Start interactive chat
43
- $ lua env ⚙️ Manage environment variables
44
- $ lua persona 🤖 Manage agent persona
45
+ $ lua env ⚙️ Manage environment variables (interactive)
46
+ $ lua env staging ⚙️ Manage staging env vars directly
47
+ $ lua env production ⚙️ Manage production env vars directly
48
+ $ lua persona 🤖 Manage agent persona (interactive)
49
+ $ lua persona staging 🤖 Manage staging persona directly
50
+ $ lua persona production 🤖 Manage production persona directly
51
+ $ lua skills ⚙️ Manage skills (interactive)
52
+ $ lua skills staging ⚙️ View staging skills directly
53
+ $ lua skills production ⚙️ Manage production skills directly
54
+ $ lua features 🎯 Manage agent features
45
55
  $ lua admin 🔧 Open admin dashboard
46
56
  $ lua docs 📖 Open documentation
57
+ $ lua completion 🎯 Enable shell autocomplete
47
58
 
48
59
  🌙 Documentation: https://docs.heylua.ai
49
60
  🌙 Support: https://heylua.ai/support
@@ -307,3 +307,34 @@ export interface CreateEmailChannelResponse {
307
307
  forwardTo: string;
308
308
  status: string;
309
309
  }
310
+ /**
311
+ * Agent feature configuration.
312
+ * Represents a feature that can be enabled/disabled for an agent.
313
+ */
314
+ export interface AgentFeature {
315
+ name: string;
316
+ title: string;
317
+ context: string;
318
+ active: boolean;
319
+ }
320
+ /**
321
+ * Response from get agent features API.
322
+ */
323
+ export interface GetAgentFeaturesResponse {
324
+ features: AgentFeature[];
325
+ }
326
+ /**
327
+ * Request payload for updating an agent feature.
328
+ * At least one of active or featureContext must be provided.
329
+ */
330
+ export interface UpdateAgentFeatureRequest {
331
+ featureName: string;
332
+ active?: boolean;
333
+ featureContext?: string;
334
+ }
335
+ /**
336
+ * Response from updating an agent feature.
337
+ */
338
+ export interface UpdateAgentFeatureResponse {
339
+ message: string;
340
+ }
@@ -0,0 +1,18 @@
1
+ export type TextMessage = {
2
+ type: "text";
3
+ text: string;
4
+ };
5
+ export type ImageMessage = {
6
+ type: "image";
7
+ image: string;
8
+ mimeType: string;
9
+ };
10
+ export type FileMessage = {
11
+ type: "file";
12
+ data: string;
13
+ mimeType: string;
14
+ };
15
+ export type Message = TextMessage | ImageMessage | FileMessage;
16
+ export interface SendMessageRequest {
17
+ messages: Message[];
18
+ }
@@ -0,0 +1 @@
1
+ export {};