lua-cli 1.3.2-alpha.2 → 2.0.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.
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/dist/commands/agents.js +1 -1
- package/dist/commands/apiKey.js +2 -4
- package/dist/commands/compile.js +632 -973
- package/dist/commands/deploy.js +1 -1
- package/dist/commands/dev.js +352 -81
- package/dist/commands/init.js +52 -78
- package/dist/commands/push.js +1 -1
- package/dist/commands/test.js +49 -11
- package/dist/index.js +7 -9
- package/dist/services/api.d.ts +4 -1
- package/dist/services/api.js +7 -6
- package/dist/services/auth.d.ts +0 -4
- package/dist/services/auth.js +2 -129
- package/dist/skill.d.ts +5 -0
- package/dist/skill.js +6 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/utils/files.d.ts +1 -1
- package/dist/utils/files.js +13 -28
- package/dist/utils/sandbox.d.ts +8 -70
- package/dist/utils/sandbox.js +153 -7
- package/dist/web/app.css +4709 -796
- package/dist/web/app.js +22 -20
- package/dist/web/tools-page.css +0 -13
- package/package.json +4 -2
- package/template/env.example +17 -0
- package/template/lua.skill.yaml +14 -15
- package/template/package.json +3 -1
- package/template/src/index.ts +46 -6
- package/template/src/seed.ts +46 -0
- package/template/src/tools/GetWeatherTool.ts +32 -15
- package/template/src/tools/PaymentTool.ts +51 -0
- package/template/src/tools/SearchProducts.ts +43 -0
- package/dist/commands/deploy-new.d.ts +0 -0
- package/dist/commands/deploy-new.js +0 -130
- package/template/package-lock.json +0 -1523
package/dist/commands/deploy.js
CHANGED
|
@@ -45,7 +45,7 @@ export async function deployCommand() {
|
|
|
45
45
|
// Load API key
|
|
46
46
|
const apiKey = await loadApiKey();
|
|
47
47
|
if (!apiKey) {
|
|
48
|
-
console.error("❌ No API key found. Please run 'lua configure' to set up your API key.");
|
|
48
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
49
49
|
process.exit(1);
|
|
50
50
|
}
|
|
51
51
|
// Validate API key
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import inquirer from 'inquirer';
|
|
5
4
|
import { compileCommand } from './compile.js';
|
|
6
5
|
import { checkApiKey, loadApiKey } from '../services/auth.js';
|
|
7
6
|
import { ApiService } from '../services/api.js';
|
|
8
|
-
import { executeTool, createBroadcastConsole } from '../utils/sandbox.js';
|
|
7
|
+
import { executeTool, createBroadcastConsole, loadEnvironmentVariables } from '../utils/sandbox.js';
|
|
9
8
|
import { readSkillConfig, updateSkillYamlPersona } from '../utils/files.js';
|
|
10
|
-
import { withErrorHandling,
|
|
9
|
+
import { withErrorHandling, writeProgress, writeSuccess } from '../utils/cli.js';
|
|
11
10
|
import keytar from 'keytar';
|
|
12
11
|
import { watch } from 'fs';
|
|
13
12
|
import { createServer } from 'http';
|
|
@@ -19,26 +18,64 @@ const __dirname = path.dirname(__filename);
|
|
|
19
18
|
const SANDBOX_SERVICE = "lua-cli-sandbox";
|
|
20
19
|
const SANDBOX_ACCOUNT = "sandbox-skill-id";
|
|
21
20
|
// Function to get sandbox skill ID from secure storage
|
|
22
|
-
async function getSandboxSkillId() {
|
|
21
|
+
async function getSandboxSkillId(skillName) {
|
|
23
22
|
try {
|
|
24
|
-
|
|
23
|
+
const account = skillName ? `${SANDBOX_ACCOUNT}_${skillName}` : SANDBOX_ACCOUNT;
|
|
24
|
+
return await keytar.getPassword(SANDBOX_SERVICE, account);
|
|
25
25
|
}
|
|
26
26
|
catch (error) {
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
// Function to store sandbox skill ID in secure storage
|
|
31
|
-
async function setSandboxSkillId(
|
|
31
|
+
async function setSandboxSkillId(sandboxId, skillName) {
|
|
32
32
|
try {
|
|
33
|
-
|
|
33
|
+
const account = skillName ? `${SANDBOX_ACCOUNT}_${skillName}` : SANDBOX_ACCOUNT;
|
|
34
|
+
await keytar.setPassword(SANDBOX_SERVICE, account, sandboxId);
|
|
34
35
|
}
|
|
35
36
|
catch (error) {
|
|
36
37
|
// Ignore storage errors
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
// Function to get all sandbox skill IDs for all skills
|
|
41
|
+
async function getAllSandboxSkillIds() {
|
|
42
|
+
const skillOverrides = [];
|
|
43
|
+
try {
|
|
44
|
+
// Read deploy.json to get all skills
|
|
45
|
+
const deployData = readDeployJson();
|
|
46
|
+
if (!deployData || !deployData.skills || !Array.isArray(deployData.skills)) {
|
|
47
|
+
return skillOverrides;
|
|
48
|
+
}
|
|
49
|
+
// For each skill, get its sandbox ID
|
|
50
|
+
for (const skill of deployData.skills) {
|
|
51
|
+
if (skill.skillId && skill.name) {
|
|
52
|
+
const sandboxId = await getSandboxSkillId(skill.name);
|
|
53
|
+
if (sandboxId) {
|
|
54
|
+
skillOverrides.push({
|
|
55
|
+
skillId: skill.skillId,
|
|
56
|
+
sandboxId: sandboxId
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Error getting sandbox skill IDs:', error);
|
|
64
|
+
}
|
|
65
|
+
return skillOverrides;
|
|
66
|
+
}
|
|
39
67
|
// Function to send chat message to API
|
|
40
68
|
export async function sendChatMessage(apiKey, agentId, skillId, sandboxId, message, persona) {
|
|
41
69
|
try {
|
|
70
|
+
// Get all sandbox skill IDs for skill override
|
|
71
|
+
const allSkillOverrides = await getAllSandboxSkillIds();
|
|
72
|
+
// If no skills found, fallback to the provided skillId and sandboxId
|
|
73
|
+
const skillOverride = allSkillOverrides.length > 0 ? allSkillOverrides : [
|
|
74
|
+
{
|
|
75
|
+
skillId: skillId,
|
|
76
|
+
sandboxId: sandboxId
|
|
77
|
+
}
|
|
78
|
+
];
|
|
42
79
|
const chatRequest = {
|
|
43
80
|
messages: [
|
|
44
81
|
{
|
|
@@ -47,12 +84,7 @@ export async function sendChatMessage(apiKey, agentId, skillId, sandboxId, messa
|
|
|
47
84
|
}
|
|
48
85
|
],
|
|
49
86
|
navigate: true,
|
|
50
|
-
skillOverride:
|
|
51
|
-
{
|
|
52
|
-
skillId: skillId,
|
|
53
|
-
sandboxId: sandboxId
|
|
54
|
-
}
|
|
55
|
-
]
|
|
87
|
+
skillOverride: skillOverride
|
|
56
88
|
};
|
|
57
89
|
// Add persona override if provided
|
|
58
90
|
if (persona) {
|
|
@@ -122,6 +154,120 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
122
154
|
}
|
|
123
155
|
return;
|
|
124
156
|
}
|
|
157
|
+
if (req.method === 'GET' && req.url === '/api/config') {
|
|
158
|
+
try {
|
|
159
|
+
const config = readSkillConfig();
|
|
160
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
161
|
+
res.end(JSON.stringify({
|
|
162
|
+
agent: {
|
|
163
|
+
agentId: config?.agent?.agentId || '',
|
|
164
|
+
orgId: config?.agent?.orgId || ''
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error('Error reading config:', error);
|
|
170
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
171
|
+
res.end(JSON.stringify({ error: 'Failed to read configuration' }));
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (req.method === 'GET' && req.url === '/api/skills') {
|
|
176
|
+
(async () => {
|
|
177
|
+
try {
|
|
178
|
+
const skillsData = [];
|
|
179
|
+
// First try to read from deploy.json in the .lua directory
|
|
180
|
+
const deployPath = path.join(process.cwd(), '.lua', 'deploy.json');
|
|
181
|
+
if (fs.existsSync(deployPath)) {
|
|
182
|
+
// Read from compiled deploy.json
|
|
183
|
+
const deployData = JSON.parse(fs.readFileSync(deployPath, 'utf8'));
|
|
184
|
+
if (deployData.skills && Array.isArray(deployData.skills)) {
|
|
185
|
+
// New format with skills array
|
|
186
|
+
for (const skill of deployData.skills) {
|
|
187
|
+
const sandboxId = await getSandboxSkillId(skill.name);
|
|
188
|
+
skillsData.push({
|
|
189
|
+
name: skill.name || 'Unnamed Skill',
|
|
190
|
+
description: skill.description || 'A Lua skill for AI automation',
|
|
191
|
+
context: skill.context || '',
|
|
192
|
+
version: skill.version || '1.0.0',
|
|
193
|
+
skillId: skill.skillId || '',
|
|
194
|
+
sandboxId: sandboxId || '',
|
|
195
|
+
tools: skill.tools ? skill.tools.map((tool) => tool.name) : []
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Legacy format fallback
|
|
201
|
+
const toolNames = Object.keys(deployData.tools || {});
|
|
202
|
+
const sandboxId = await getSandboxSkillId(); // Legacy uses no skill name
|
|
203
|
+
skillsData.push({
|
|
204
|
+
name: deployData.name || 'Current Skill',
|
|
205
|
+
description: deployData.description || 'A Lua skill for AI automation',
|
|
206
|
+
context: deployData.context || '',
|
|
207
|
+
version: deployData.version || '1.0.0',
|
|
208
|
+
skillId: deployData.skillId || '',
|
|
209
|
+
sandboxId: sandboxId || '',
|
|
210
|
+
tools: toolNames
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Fallback: Read from YAML and scan tools directory
|
|
216
|
+
const config = readSkillConfig();
|
|
217
|
+
const toolsDir = path.join(process.cwd(), 'src', 'tools');
|
|
218
|
+
let toolNames = [];
|
|
219
|
+
if (fs.existsSync(toolsDir)) {
|
|
220
|
+
const toolFiles = fs.readdirSync(toolsDir)
|
|
221
|
+
.filter((file) => file.endsWith('.ts'))
|
|
222
|
+
.map((file) => file.replace('.ts', ''));
|
|
223
|
+
toolNames = toolFiles;
|
|
224
|
+
}
|
|
225
|
+
if (config?.skills && Array.isArray(config.skills)) {
|
|
226
|
+
// New format: multiple skills
|
|
227
|
+
for (const skill of config.skills) {
|
|
228
|
+
const sandboxId = await getSandboxSkillId(skill.name);
|
|
229
|
+
skillsData.push({
|
|
230
|
+
name: skill.name || 'Unnamed Skill',
|
|
231
|
+
description: 'A Lua skill for AI automation (not compiled)',
|
|
232
|
+
context: 'This skill has not been compiled yet. Run "lua compile" to see full context information.',
|
|
233
|
+
version: skill.version || '1.0.0',
|
|
234
|
+
skillId: skill.skillId || '',
|
|
235
|
+
sandboxId: sandboxId || '',
|
|
236
|
+
tools: toolNames // All tools for now since not compiled
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else if (config?.skill) {
|
|
241
|
+
// Legacy format: single skill
|
|
242
|
+
const sandboxId = await getSandboxSkillId(); // Legacy uses no skill name
|
|
243
|
+
skillsData.push({
|
|
244
|
+
name: config.skill.name || 'Current Skill',
|
|
245
|
+
description: 'A Lua skill for AI automation (not compiled)',
|
|
246
|
+
context: 'This skill has not been compiled yet. Run "lua compile" to see full context information.',
|
|
247
|
+
version: config.skill.version || '1.0.0',
|
|
248
|
+
skillId: config.skill.skillId || '',
|
|
249
|
+
sandboxId: sandboxId || '',
|
|
250
|
+
tools: toolNames
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
255
|
+
res.end(JSON.stringify({
|
|
256
|
+
success: true,
|
|
257
|
+
skills: skillsData
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
console.error('Error reading skills:', error);
|
|
262
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
263
|
+
res.end(JSON.stringify({
|
|
264
|
+
success: false,
|
|
265
|
+
error: 'Failed to read skills configuration'
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
})();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
125
271
|
if (req.method === 'POST' && req.url === '/persona') {
|
|
126
272
|
let body = '';
|
|
127
273
|
req.on('data', chunk => {
|
|
@@ -145,6 +291,50 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
145
291
|
});
|
|
146
292
|
return;
|
|
147
293
|
}
|
|
294
|
+
// Environment variables endpoints
|
|
295
|
+
if (req.method === 'GET' && req.url === '/env') {
|
|
296
|
+
try {
|
|
297
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
298
|
+
let envContent = '';
|
|
299
|
+
if (fs.existsSync(envPath)) {
|
|
300
|
+
envContent = fs.readFileSync(envPath, 'utf8');
|
|
301
|
+
}
|
|
302
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
303
|
+
res.end(JSON.stringify({
|
|
304
|
+
success: true,
|
|
305
|
+
content: envContent
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
310
|
+
res.end(JSON.stringify({ success: false, error: 'Failed to read .env file' }));
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (req.method === 'POST' && req.url === '/env') {
|
|
315
|
+
let body = '';
|
|
316
|
+
req.on('data', chunk => {
|
|
317
|
+
body += chunk.toString();
|
|
318
|
+
});
|
|
319
|
+
req.on('end', async () => {
|
|
320
|
+
try {
|
|
321
|
+
const { content } = JSON.parse(body);
|
|
322
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
323
|
+
// Write the .env file
|
|
324
|
+
fs.writeFileSync(envPath, content || '', 'utf8');
|
|
325
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
326
|
+
res.end(JSON.stringify({
|
|
327
|
+
success: true,
|
|
328
|
+
message: 'Environment variables updated successfully'
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
333
|
+
res.end(JSON.stringify({ success: false, error: 'Failed to update .env file' }));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
148
338
|
// Tools endpoints
|
|
149
339
|
if (req.method === 'GET' && req.url === '/tools') {
|
|
150
340
|
try {
|
|
@@ -152,10 +342,23 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
152
342
|
const deployPath = path.join(process.cwd(), '.lua', 'deploy.json');
|
|
153
343
|
if (fs.existsSync(deployPath)) {
|
|
154
344
|
const deployData = JSON.parse(fs.readFileSync(deployPath, 'utf8'));
|
|
345
|
+
// Handle both new skills array format and legacy tools format
|
|
346
|
+
let tools = deployData.tools || {};
|
|
347
|
+
if (deployData.skills && Array.isArray(deployData.skills)) {
|
|
348
|
+
// New format: merge all tools from all skills
|
|
349
|
+
tools = {};
|
|
350
|
+
deployData.skills.forEach((skill) => {
|
|
351
|
+
if (skill.tools && Array.isArray(skill.tools)) {
|
|
352
|
+
skill.tools.forEach((tool) => {
|
|
353
|
+
tools[tool.name] = tool;
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
155
358
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
156
359
|
res.end(JSON.stringify({
|
|
157
360
|
success: true,
|
|
158
|
-
tools:
|
|
361
|
+
tools: tools
|
|
159
362
|
}));
|
|
160
363
|
}
|
|
161
364
|
else {
|
|
@@ -185,20 +388,33 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
185
388
|
return;
|
|
186
389
|
}
|
|
187
390
|
const deployData = JSON.parse(fs.readFileSync(deployPath, 'utf8'));
|
|
188
|
-
|
|
391
|
+
let tool = null;
|
|
392
|
+
if (deployData.skills && Array.isArray(deployData.skills)) {
|
|
393
|
+
// New format: search through skills array
|
|
394
|
+
for (const skill of deployData.skills) {
|
|
395
|
+
if (skill.tools && Array.isArray(skill.tools)) {
|
|
396
|
+
tool = skill.tools.find((t) => t.name === toolName);
|
|
397
|
+
if (tool)
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
// Legacy format: search in tools object
|
|
404
|
+
if (deployData.tools && deployData.tools[toolName]) {
|
|
405
|
+
tool = {
|
|
406
|
+
name: toolName,
|
|
407
|
+
...deployData.tools[toolName]
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
}
|
|
189
411
|
if (!tool) {
|
|
190
412
|
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
191
413
|
res.end(JSON.stringify({ success: false, error: 'Tool not found' }));
|
|
192
414
|
return;
|
|
193
415
|
}
|
|
194
|
-
//
|
|
195
|
-
const
|
|
196
|
-
const envVars = {};
|
|
197
|
-
if (config?.skill?.env) {
|
|
198
|
-
for (const [key, value] of Object.entries(config.skill.env)) {
|
|
199
|
-
envVars[key] = value;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
416
|
+
// Load environment variables from all sources (.env + yaml)
|
|
417
|
+
const envVars = loadEnvironmentVariables();
|
|
202
418
|
// Decompress and execute the tool
|
|
203
419
|
const { gunzipSync } = await import('zlib');
|
|
204
420
|
const { Buffer } = await import('buffer');
|
|
@@ -209,8 +425,21 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
209
425
|
return gunzipSync(buffer).toString('utf8');
|
|
210
426
|
}
|
|
211
427
|
const toolCode = decompressCode(tool.execute);
|
|
428
|
+
// Broadcast tool test start
|
|
429
|
+
wss.clients.forEach((client) => {
|
|
430
|
+
if (client.readyState === 1) {
|
|
431
|
+
client.send(JSON.stringify({
|
|
432
|
+
type: 'log',
|
|
433
|
+
subType: 'info',
|
|
434
|
+
message: `🧪 Testing tool: ${toolName}`,
|
|
435
|
+
timestamp: new Date().toISOString(),
|
|
436
|
+
id: Date.now().toString()
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
});
|
|
212
440
|
// Create custom console that captures output and sends via WebSocket
|
|
213
441
|
const customConsole = createBroadcastConsole((logData) => {
|
|
442
|
+
console.log('Broadcasting tool log:', logData);
|
|
214
443
|
wss.clients.forEach((client) => {
|
|
215
444
|
if (client.readyState === 1) { // WebSocket.OPEN
|
|
216
445
|
client.send(JSON.stringify(logData));
|
|
@@ -225,6 +454,18 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
225
454
|
agentId,
|
|
226
455
|
customConsole
|
|
227
456
|
});
|
|
457
|
+
// Broadcast tool test completion
|
|
458
|
+
wss.clients.forEach((client) => {
|
|
459
|
+
if (client.readyState === 1) {
|
|
460
|
+
client.send(JSON.stringify({
|
|
461
|
+
type: 'log',
|
|
462
|
+
subType: 'info',
|
|
463
|
+
message: `✅ Tool test completed: ${toolName}`,
|
|
464
|
+
timestamp: new Date().toISOString(),
|
|
465
|
+
id: (Date.now() + 1).toString()
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
});
|
|
228
469
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
229
470
|
res.end(JSON.stringify({
|
|
230
471
|
success: true,
|
|
@@ -337,8 +578,7 @@ function createChatServer(apiKey, agentId, skillId, sandboxId, port = 3000) {
|
|
|
337
578
|
// Function to update existing sandbox version
|
|
338
579
|
export async function updateDevVersion(apiKey, agentId, skillId, sandboxVersionId, versionData) {
|
|
339
580
|
try {
|
|
340
|
-
|
|
341
|
-
console.log('Calling UPDATE endpoint: ' + url);
|
|
581
|
+
// console.log('Calling UPDATE endpoint for sandbox version');
|
|
342
582
|
const response = await ApiService.Skill.updateDevSkill(apiKey, agentId, skillId, sandboxVersionId, versionData);
|
|
343
583
|
if (response.success) {
|
|
344
584
|
return {
|
|
@@ -372,8 +612,7 @@ export async function updateDevVersion(apiKey, agentId, skillId, sandboxVersionI
|
|
|
372
612
|
// Function to create new sandbox version
|
|
373
613
|
export async function pushDevVersion(apiKey, agentId, skillId, versionData) {
|
|
374
614
|
try {
|
|
375
|
-
|
|
376
|
-
console.log(`🔗 Calling CREATE endpoint: ${url}`);
|
|
615
|
+
// console.log(`🔗 Calling CREATE endpoint for sandbox version`);
|
|
377
616
|
const response = await ApiService.Skill.pushDevSkill(apiKey, agentId, skillId, versionData);
|
|
378
617
|
if (response.success) {
|
|
379
618
|
return {
|
|
@@ -416,15 +655,42 @@ function readDeployJson() {
|
|
|
416
655
|
const deployContent = fs.readFileSync(deployPath, 'utf8');
|
|
417
656
|
return JSON.parse(deployContent);
|
|
418
657
|
}
|
|
419
|
-
// Function to push to sandbox
|
|
420
|
-
async function
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const
|
|
658
|
+
// Function to push multiple skills to sandbox
|
|
659
|
+
async function pushSkillsToSandbox(apiKey, agentId, deployData, isInitial = false) {
|
|
660
|
+
const sandboxIds = {};
|
|
661
|
+
if (!deployData.skills || !Array.isArray(deployData.skills)) {
|
|
662
|
+
throw new Error("No skills found in deploy data");
|
|
663
|
+
}
|
|
664
|
+
for (const skill of deployData.skills) {
|
|
665
|
+
if (!skill.skillId) {
|
|
666
|
+
console.warn(`⚠️ Skipping skill ${skill.name} - no skillId found`);
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
try {
|
|
670
|
+
const success = await pushSingleSkillToSandbox(apiKey, agentId, skill.skillId, skill, isInitial);
|
|
671
|
+
if (success) {
|
|
672
|
+
// Get the sandbox ID for this skill (stored in .lua directory)
|
|
673
|
+
const sandboxId = await getSandboxSkillId(skill.name);
|
|
674
|
+
if (sandboxId) {
|
|
675
|
+
sandboxIds[skill.name] = sandboxId;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
console.error(`❌ Failed to push skill ${skill.name}:`, error);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return sandboxIds;
|
|
684
|
+
}
|
|
685
|
+
// Function to push a single skill to sandbox (extracted for reuse)
|
|
686
|
+
async function pushSingleSkillToSandbox(apiKey, agentId, skillId, skillData, isInitial = false) {
|
|
687
|
+
const skillName = skillData.name || 'Unknown Skill';
|
|
688
|
+
const sandboxSkillId = await getSandboxSkillId(skillName);
|
|
689
|
+
// Load environment variables
|
|
690
|
+
const envVars = loadEnvironmentVariables();
|
|
691
|
+
// console.log(skillData);
|
|
426
692
|
const payloadWithNameAndEnv = {
|
|
427
|
-
...
|
|
693
|
+
...skillData,
|
|
428
694
|
name: skillName,
|
|
429
695
|
env: envVars
|
|
430
696
|
};
|
|
@@ -436,8 +702,8 @@ async function pushToSandbox(apiKey, agentId, skillId, deployData, isInitial = f
|
|
|
436
702
|
const updateResult = await updateDevVersion(apiKey, agentId, skillId, sandboxSkillId, payloadWithNameAndEnv);
|
|
437
703
|
if (updateResult.success && updateResult.data) {
|
|
438
704
|
if (!isInitial) {
|
|
439
|
-
writeSuccess(`✅ Version ${updateResult.data.version} updated in sandbox successfully`);
|
|
440
|
-
writeSuccess(`🔑 Sandbox Skill ID: ${updateResult.data.skillId}`);
|
|
705
|
+
// writeSuccess(`✅ Version ${updateResult.data.version} updated in sandbox successfully`);
|
|
706
|
+
// writeSuccess(`🔑 Sandbox Skill ID: ${updateResult.data.skillId}`);
|
|
441
707
|
}
|
|
442
708
|
return true;
|
|
443
709
|
}
|
|
@@ -459,7 +725,7 @@ async function pushToSandbox(apiKey, agentId, skillId, deployData, isInitial = f
|
|
|
459
725
|
const result = await pushDevVersion(apiKey, agentId, skillId, payloadWithNameAndEnv);
|
|
460
726
|
if (result.success && result.data) {
|
|
461
727
|
// Store the new sandbox skill ID
|
|
462
|
-
await setSandboxSkillId(result.data.skillId);
|
|
728
|
+
await setSandboxSkillId(result.data.skillId, skillName);
|
|
463
729
|
if (!isInitial) {
|
|
464
730
|
writeSuccess(`✅ Version ${result.data.version} pushed to sandbox successfully`);
|
|
465
731
|
writeSuccess(`🔑 Sandbox Skill ID: ${result.data.skillId}`);
|
|
@@ -493,26 +759,13 @@ export async function devCommand() {
|
|
|
493
759
|
console.error("❌ No lua.skill.yaml found. Please run this command from a skill directory.");
|
|
494
760
|
process.exit(1);
|
|
495
761
|
}
|
|
496
|
-
// Read version from config
|
|
497
|
-
|
|
498
|
-
if (!version) {
|
|
499
|
-
|
|
500
|
-
process.exit(1);
|
|
762
|
+
// Read version from config (handle both old and new formats)
|
|
763
|
+
let version = config.skill?.version; // Legacy format
|
|
764
|
+
if (!version && config.skills && config.skills.length > 0) {
|
|
765
|
+
version = config.skills[0].version; // New format - use first skill's version
|
|
501
766
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
{
|
|
505
|
-
type: "confirm",
|
|
506
|
-
name: "confirmed",
|
|
507
|
-
message: `Are you sure you want to push version ${version} to sandbox?`,
|
|
508
|
-
default: false
|
|
509
|
-
}
|
|
510
|
-
]);
|
|
511
|
-
// Clear the confirmation prompt lines
|
|
512
|
-
clearPromptLines(2);
|
|
513
|
-
if (!confirmed) {
|
|
514
|
-
console.log("❌ Dev push cancelled.");
|
|
515
|
-
process.exit(0);
|
|
767
|
+
if (!version) {
|
|
768
|
+
version = "1.0.0"; // Default version
|
|
516
769
|
}
|
|
517
770
|
// Load API key
|
|
518
771
|
const apiKey = await loadApiKey();
|
|
@@ -526,33 +779,51 @@ export async function devCommand() {
|
|
|
526
779
|
// Compile the skill first
|
|
527
780
|
writeProgress("🔄 Compiling skill...");
|
|
528
781
|
await compileCommand();
|
|
782
|
+
// Re-read config after compilation to get updated skillIds
|
|
783
|
+
const updatedConfig = readSkillConfig();
|
|
784
|
+
if (!updatedConfig) {
|
|
785
|
+
console.error("❌ Failed to read updated skill configuration after compilation.");
|
|
786
|
+
process.exit(1);
|
|
787
|
+
}
|
|
529
788
|
// Read deploy.json
|
|
530
789
|
const deployData = readDeployJson();
|
|
531
790
|
if (!deployData) {
|
|
532
791
|
console.error("❌ No deploy.json found. Compilation may have failed.");
|
|
533
792
|
process.exit(1);
|
|
534
793
|
}
|
|
535
|
-
// Verify
|
|
536
|
-
if (deployData.
|
|
537
|
-
console.error(
|
|
794
|
+
// Verify deploy.json has skills
|
|
795
|
+
if (!deployData.skills || !Array.isArray(deployData.skills) || deployData.skills.length === 0) {
|
|
796
|
+
console.error("❌ No skills found in deploy.json. Compilation may have failed.");
|
|
538
797
|
process.exit(1);
|
|
539
798
|
}
|
|
540
|
-
// Extract agentId
|
|
541
|
-
const agentId =
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
799
|
+
// Extract agentId from updated config
|
|
800
|
+
const agentId = updatedConfig.agent?.agentId;
|
|
801
|
+
if (!agentId) {
|
|
802
|
+
console.error("❌ Missing agentId in skill configuration");
|
|
803
|
+
process.exit(1);
|
|
804
|
+
}
|
|
805
|
+
// For multi-skill projects, we'll use the first skill's ID for sandbox
|
|
806
|
+
let skillId = updatedConfig.skill?.skillId; // Legacy format
|
|
807
|
+
if (!skillId && updatedConfig.skills && updatedConfig.skills.length > 0) {
|
|
808
|
+
skillId = updatedConfig.skills[0].skillId; // New format - use first skill
|
|
809
|
+
}
|
|
810
|
+
if (!skillId) {
|
|
811
|
+
console.error("❌ No skillId found after compilation. Skill creation may have failed.");
|
|
812
|
+
console.error("Available skills:", updatedConfig.skills);
|
|
545
813
|
process.exit(1);
|
|
546
814
|
}
|
|
547
815
|
// Initial push to sandbox
|
|
548
|
-
writeProgress("🔄 Pushing to sandbox...");
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
816
|
+
writeProgress("🔄 Pushing skills to sandbox...");
|
|
817
|
+
const sandboxIds = await pushSkillsToSandbox(apiKey, agentId, deployData, true);
|
|
818
|
+
// console.log(sandboxIds);
|
|
819
|
+
if (Object.keys(sandboxIds).length === 0) {
|
|
820
|
+
console.error("❌ Failed to push any skills to sandbox. Cannot start development mode.");
|
|
552
821
|
process.exit(1);
|
|
553
822
|
}
|
|
554
|
-
|
|
555
|
-
|
|
823
|
+
writeSuccess(`✅ Pushed ${Object.keys(sandboxIds).length} skills to sandbox`);
|
|
824
|
+
// Use the first skill's sandbox ID for the web interface
|
|
825
|
+
const firstSkillName = Object.keys(sandboxIds)[0];
|
|
826
|
+
const sandboxSkillId = sandboxIds[firstSkillName];
|
|
556
827
|
if (!sandboxSkillId) {
|
|
557
828
|
console.error("❌ No sandbox skill ID found. Cannot start chat interface.");
|
|
558
829
|
process.exit(1);
|
|
@@ -620,20 +891,20 @@ export async function devCommand() {
|
|
|
620
891
|
writeProgress("❌ Compilation failed, skipping push");
|
|
621
892
|
return;
|
|
622
893
|
}
|
|
623
|
-
// Verify
|
|
624
|
-
if (updatedDeployData.
|
|
625
|
-
writeProgress("❌
|
|
894
|
+
// Verify updated deploy.json has skills
|
|
895
|
+
if (!updatedDeployData.skills || !Array.isArray(updatedDeployData.skills) || updatedDeployData.skills.length === 0) {
|
|
896
|
+
writeProgress("❌ No skills found in updated deploy.json, skipping push");
|
|
626
897
|
return;
|
|
627
898
|
}
|
|
628
|
-
// Push to sandbox
|
|
629
|
-
const
|
|
630
|
-
if (
|
|
631
|
-
writeProgress("❌ Failed to push to sandbox, will retry on next change");
|
|
632
|
-
broadcastLog("❌ Failed to push to sandbox, will retry on next change", 'error');
|
|
899
|
+
// Push all skills to sandbox
|
|
900
|
+
const updatedSandboxIds = await pushSkillsToSandbox(apiKey, agentId, updatedDeployData, false);
|
|
901
|
+
if (Object.keys(updatedSandboxIds).length === 0) {
|
|
902
|
+
writeProgress("❌ Failed to push any skills to sandbox, will retry on next change");
|
|
903
|
+
broadcastLog("❌ Failed to push skills to sandbox, will retry on next change", 'error');
|
|
633
904
|
}
|
|
634
905
|
else {
|
|
635
|
-
writeProgress(
|
|
636
|
-
broadcastLog(
|
|
906
|
+
// writeProgress(`✅ Successfully pushed ${Object.keys(updatedSandboxIds).length} skills to sandbox`);
|
|
907
|
+
broadcastLog(`✅ Successfully pushed ${Object.keys(updatedSandboxIds).length} skills to sandbox`, 'info');
|
|
637
908
|
}
|
|
638
909
|
}
|
|
639
910
|
catch (error) {
|