lua-cli 2.5.6 → 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.
- package/dist/api/agent.api.service.d.ts +45 -0
- package/dist/api/agent.api.service.js +54 -0
- package/dist/api/user.data.api.service.d.ts +15 -0
- package/dist/api/user.data.api.service.js +31 -0
- package/dist/cli/command-definitions.js +77 -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 +3 -0
- package/dist/commands/index.js +3 -0
- package/dist/commands/persona.d.ts +3 -2
- package/dist/commands/persona.js +43 -18
- package/dist/commands/push.d.ts +9 -13
- package/dist/commands/push.js +271 -82
- package/dist/commands/skills.d.ts +16 -0
- package/dist/commands/skills.js +438 -0
- package/dist/common/basket.instance.js +38 -19
- package/dist/common/data.entry.instance.d.ts +7 -0
- package/dist/common/data.entry.instance.js +35 -9
- package/dist/common/order.instance.d.ts +6 -0
- package/dist/common/order.instance.js +48 -15
- package/dist/common/product.instance.d.ts +6 -0
- package/dist/common/product.instance.js +34 -9
- package/dist/common/product.pagination.instance.js +6 -2
- package/dist/common/product.search.instance.js +4 -1
- package/dist/common/user.instance.d.ts +14 -0
- package/dist/common/user.instance.js +49 -9
- package/dist/index.js +14 -3
- package/dist/interfaces/agent.d.ts +31 -0
- package/dist/interfaces/message.d.ts +18 -0
- package/dist/interfaces/message.js +1 -0
- package/dist/types/api-contracts.d.ts +9 -0
- package/dist/types/api-contracts.js +0 -7
- package/dist/web/app.css +152 -736
- package/dist/web/app.js +45 -45
- package/package.json +2 -2
- 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
|
+
}
|
|
@@ -12,15 +12,16 @@ export default class BasketInstance {
|
|
|
12
12
|
* @returns Proxied instance that allows direct access to data and common properties
|
|
13
13
|
*/
|
|
14
14
|
constructor(api, basket) {
|
|
15
|
-
|
|
16
|
-
this.
|
|
15
|
+
// Ensure data and common are always objects, never null or undefined
|
|
16
|
+
this.data = basket.data && typeof basket.data === 'object' ? basket.data : {};
|
|
17
|
+
this.common = basket.common && typeof basket.common === 'object' ? basket.common : {};
|
|
17
18
|
this.id = basket.id;
|
|
18
19
|
this.userId = basket.userId;
|
|
19
20
|
this.agentId = basket.agentId;
|
|
20
|
-
this.metadata = basket.data
|
|
21
|
-
this.totalAmount = basket.common
|
|
22
|
-
this.itemCount = basket.common
|
|
23
|
-
this.status = basket.common.
|
|
21
|
+
this.metadata = basket.data?.metadata || {};
|
|
22
|
+
this.totalAmount = basket.common?.totalAmount || 0;
|
|
23
|
+
this.itemCount = basket.common?.itemCount || 0;
|
|
24
|
+
this.status = basket.common?.status || BasketStatus.ACTIVE;
|
|
24
25
|
// Make basketAPI non-enumerable so it doesn't show up in console.log
|
|
25
26
|
Object.defineProperty(this, 'basketAPI', {
|
|
26
27
|
value: api,
|
|
@@ -35,12 +36,12 @@ export default class BasketInstance {
|
|
|
35
36
|
if (prop in target) {
|
|
36
37
|
return Reflect.get(target, prop, receiver);
|
|
37
38
|
}
|
|
38
|
-
// Check data object
|
|
39
|
-
if (typeof prop === 'string' && prop in target.data) {
|
|
39
|
+
// Check data object (with null check)
|
|
40
|
+
if (typeof prop === 'string' && target.data && typeof target.data === 'object' && prop in target.data) {
|
|
40
41
|
return target.data[prop];
|
|
41
42
|
}
|
|
42
|
-
// Check common object
|
|
43
|
-
if (typeof prop === 'string' && prop in target.common) {
|
|
43
|
+
// Check common object (with null check)
|
|
44
|
+
if (typeof prop === 'string' && target.common && typeof target.common === 'object' && prop in target.common) {
|
|
44
45
|
return target.common[prop];
|
|
45
46
|
}
|
|
46
47
|
return undefined;
|
|
@@ -53,6 +54,13 @@ export default class BasketInstance {
|
|
|
53
54
|
}
|
|
54
55
|
// Check if property exists in data or common, otherwise default to data
|
|
55
56
|
if (typeof prop === 'string') {
|
|
57
|
+
// Initialize objects if they don't exist
|
|
58
|
+
if (!target.data || typeof target.data !== 'object') {
|
|
59
|
+
target.data = {};
|
|
60
|
+
}
|
|
61
|
+
if (!target.common || typeof target.common !== 'object') {
|
|
62
|
+
target.common = {};
|
|
63
|
+
}
|
|
56
64
|
if (prop in target.common) {
|
|
57
65
|
target.common[prop] = value;
|
|
58
66
|
}
|
|
@@ -64,14 +72,25 @@ export default class BasketInstance {
|
|
|
64
72
|
return false;
|
|
65
73
|
},
|
|
66
74
|
has(target, prop) {
|
|
67
|
-
// Check if property exists on instance, in data, or in common
|
|
68
|
-
|
|
75
|
+
// Check if property exists on instance, in data, or in common (with null checks)
|
|
76
|
+
if (prop in target) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
if (typeof prop === 'string') {
|
|
80
|
+
if (target.data && typeof target.data === 'object' && prop in target.data) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (target.common && typeof target.common === 'object' && prop in target.common) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
69
88
|
},
|
|
70
89
|
ownKeys(target) {
|
|
71
|
-
// Return instance keys, data keys, and common keys
|
|
90
|
+
// Return instance keys, data keys, and common keys (with null checks)
|
|
72
91
|
const instanceKeys = Reflect.ownKeys(target);
|
|
73
|
-
const dataKeys = Object.keys(target.data);
|
|
74
|
-
const commonKeys = Object.keys(target.common);
|
|
92
|
+
const dataKeys = target.data && typeof target.data === 'object' ? Object.keys(target.data) : [];
|
|
93
|
+
const commonKeys = target.common && typeof target.common === 'object' ? Object.keys(target.common) : [];
|
|
75
94
|
return [...new Set([...instanceKeys, ...dataKeys, ...commonKeys])];
|
|
76
95
|
},
|
|
77
96
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -80,8 +99,8 @@ export default class BasketInstance {
|
|
|
80
99
|
if (instanceDesc) {
|
|
81
100
|
return instanceDesc;
|
|
82
101
|
}
|
|
83
|
-
// Then check data properties
|
|
84
|
-
if (typeof prop === 'string' && prop in target.data) {
|
|
102
|
+
// Then check data properties (with null check)
|
|
103
|
+
if (typeof prop === 'string' && target.data && typeof target.data === 'object' && prop in target.data) {
|
|
85
104
|
return {
|
|
86
105
|
configurable: true,
|
|
87
106
|
enumerable: true,
|
|
@@ -89,8 +108,8 @@ export default class BasketInstance {
|
|
|
89
108
|
value: target.data[prop]
|
|
90
109
|
};
|
|
91
110
|
}
|
|
92
|
-
// Then check common properties
|
|
93
|
-
if (typeof prop === 'string' && prop in target.common) {
|
|
111
|
+
// Then check common properties (with null check)
|
|
112
|
+
if (typeof prop === 'string' && target.common && typeof target.common === 'object' && prop in target.common) {
|
|
94
113
|
return {
|
|
95
114
|
configurable: true,
|
|
96
115
|
enumerable: true,
|
|
@@ -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
|
}
|
|
@@ -12,7 +12,8 @@ export default class DataEntryInstance {
|
|
|
12
12
|
* @returns Proxied instance that allows direct access to data properties
|
|
13
13
|
*/
|
|
14
14
|
constructor(api, entry, collectionName) {
|
|
15
|
-
|
|
15
|
+
// Ensure data is always an object, never null or undefined
|
|
16
|
+
this.data = entry.data && typeof entry.data === 'object' ? entry.data : {};
|
|
16
17
|
this.id = entry.id;
|
|
17
18
|
this.collectionName = collectionName;
|
|
18
19
|
this.score = entry.score;
|
|
@@ -30,8 +31,8 @@ export default class DataEntryInstance {
|
|
|
30
31
|
if (prop in target) {
|
|
31
32
|
return Reflect.get(target, prop, receiver);
|
|
32
33
|
}
|
|
33
|
-
// Otherwise, try to get it from the data object
|
|
34
|
-
if (typeof prop === 'string' && prop in target.data) {
|
|
34
|
+
// Otherwise, try to get it from the data object (with null check)
|
|
35
|
+
if (typeof prop === 'string' && target.data && typeof target.data === 'object' && prop in target.data) {
|
|
35
36
|
return target.data[prop];
|
|
36
37
|
}
|
|
37
38
|
return undefined;
|
|
@@ -44,19 +45,29 @@ export default class DataEntryInstance {
|
|
|
44
45
|
}
|
|
45
46
|
// All other properties get set on the data object
|
|
46
47
|
if (typeof prop === 'string') {
|
|
48
|
+
// Initialize data object if it doesn't exist
|
|
49
|
+
if (!target.data || typeof target.data !== 'object') {
|
|
50
|
+
target.data = {};
|
|
51
|
+
}
|
|
47
52
|
target.data[prop] = value;
|
|
48
53
|
return true;
|
|
49
54
|
}
|
|
50
55
|
return false;
|
|
51
56
|
},
|
|
52
57
|
has(target, prop) {
|
|
53
|
-
// Check if property exists on instance or in data
|
|
54
|
-
|
|
58
|
+
// Check if property exists on instance or in data (with null check)
|
|
59
|
+
if (prop in target) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (typeof prop === 'string' && target.data && typeof target.data === 'object') {
|
|
63
|
+
return prop in target.data;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
55
66
|
},
|
|
56
67
|
ownKeys(target) {
|
|
57
|
-
// Return both instance keys and data keys
|
|
68
|
+
// Return both instance keys and data keys (with null check)
|
|
58
69
|
const instanceKeys = Reflect.ownKeys(target);
|
|
59
|
-
const dataKeys = Object.keys(target.data);
|
|
70
|
+
const dataKeys = target.data && typeof target.data === 'object' ? Object.keys(target.data) : [];
|
|
60
71
|
return [...new Set([...instanceKeys, ...dataKeys])];
|
|
61
72
|
},
|
|
62
73
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -65,8 +76,8 @@ export default class DataEntryInstance {
|
|
|
65
76
|
if (instanceDesc) {
|
|
66
77
|
return instanceDesc;
|
|
67
78
|
}
|
|
68
|
-
// Then check if it's a data property
|
|
69
|
-
if (typeof prop === 'string' && prop in target.data) {
|
|
79
|
+
// Then check if it's a data property (with null check)
|
|
80
|
+
if (typeof prop === 'string' && target.data && typeof target.data === 'object' && prop in target.data) {
|
|
70
81
|
return {
|
|
71
82
|
configurable: true,
|
|
72
83
|
enumerable: true,
|
|
@@ -133,4 +144,19 @@ export default class DataEntryInstance {
|
|
|
133
144
|
throw new Error('Failed to clear user data');
|
|
134
145
|
}
|
|
135
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
|
+
}
|
|
136
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
|
}
|