lua-cli 1.2.1 → 1.3.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 +50 -0
- package/README.md +244 -63
- package/dist/commands/agents.js +17 -17
- package/dist/commands/apiKey.js +24 -19
- package/dist/commands/compile.d.ts +1 -0
- package/dist/commands/compile.js +1004 -0
- package/dist/commands/configure.js +93 -68
- package/dist/commands/deploy-new.d.ts +0 -0
- package/dist/commands/deploy-new.js +130 -0
- package/dist/commands/deploy.d.ts +19 -0
- package/dist/commands/deploy.js +81 -763
- package/dist/commands/destroy.js +26 -21
- package/dist/commands/dev.d.ts +63 -0
- package/dist/commands/dev.js +656 -0
- package/dist/commands/index.d.ts +4 -2
- package/dist/commands/index.js +4 -2
- package/dist/commands/init.js +297 -62
- package/dist/commands/push.d.ts +22 -0
- package/dist/commands/push.js +127 -0
- package/dist/commands/test.js +14 -15
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -19
- package/dist/services/api.d.ts +195 -0
- package/dist/services/api.js +209 -0
- package/dist/services/auth.d.ts +102 -0
- package/dist/services/auth.js +129 -40
- package/dist/skill.d.ts +22 -1
- package/dist/skill.js +21 -1
- package/dist/types/index.d.ts +16 -2
- package/dist/types/index.js +16 -1
- package/dist/user-data-api.d.ts +52 -0
- package/dist/user-data-api.js +151 -0
- package/dist/utils/cli.d.ts +34 -0
- package/dist/utils/cli.js +58 -0
- package/dist/utils/files.d.ts +4 -1
- package/dist/utils/files.js +61 -14
- package/dist/web/app.css +1050 -0
- package/dist/web/app.js +79 -0
- package/dist/web/tools-page.css +377 -0
- package/package.json +18 -5
- package/template/package-lock.json +32 -3
- package/template/package.json +3 -1
- package/template/{index.ts → src/index.ts} +13 -4
- package/template/src/tools/UserPreferencesTool.ts +73 -0
- package/template/tools/UserPreferencesTool.ts +73 -0
- package/template/tsconfig.json +1 -1
- package/template/.lua/deploy.json +0 -145
- /package/template/{services → src/services}/ApiService.ts +0 -0
- /package/template/{services → src/services}/GetWeather.ts +0 -0
- /package/template/{services → src/services}/MathService.ts +0 -0
- /package/template/{tools → src/tools}/AdvancedMathTool.ts +0 -0
- /package/template/{tools → src/tools}/CalculatorTool.ts +0 -0
- /package/template/{tools → src/tools}/CreatePostTool.ts +0 -0
- /package/template/{tools → src/tools}/GetUserDataTool.ts +0 -0
- /package/template/{tools → src/tools}/GetWeatherTool.ts +0 -0
package/dist/commands/init.js
CHANGED
|
@@ -1,70 +1,305 @@
|
|
|
1
1
|
import inquirer from "inquirer";
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { loadApiKey, checkApiKey } from "../services/auth.js";
|
|
5
|
-
import { copyTemplateFiles,
|
|
4
|
+
import { loadApiKey, checkApiKey, createSkill, getAgentTypes, createAgent, getAgentDetails } from "../services/auth.js";
|
|
5
|
+
import { copyTemplateFiles, createSkillYaml } from "../utils/files.js";
|
|
6
|
+
import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from "../utils/cli.js";
|
|
7
|
+
function getTemplateDir() {
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
return path.join(__dirname, "..", "..", "template");
|
|
11
|
+
}
|
|
6
12
|
export async function initCommand() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Get user data from API
|
|
13
|
-
const userData = await checkApiKey(apiKey);
|
|
14
|
-
// Extract organizations and create choices for selection
|
|
15
|
-
const orgs = userData.admin.orgs;
|
|
16
|
-
const orgChoices = orgs.map((org) => ({
|
|
17
|
-
name: org.registeredName,
|
|
18
|
-
value: org
|
|
19
|
-
}));
|
|
20
|
-
// Select organization
|
|
21
|
-
const { selectedOrg } = await inquirer.prompt([
|
|
22
|
-
{
|
|
23
|
-
type: "list",
|
|
24
|
-
name: "selectedOrg",
|
|
25
|
-
message: "Select an organization:",
|
|
26
|
-
choices: orgChoices
|
|
13
|
+
return withErrorHandling(async () => {
|
|
14
|
+
const apiKey = await loadApiKey();
|
|
15
|
+
if (!apiKey) {
|
|
16
|
+
console.error("❌ No API key found. Run `lua configure` first.");
|
|
17
|
+
process.exit(1);
|
|
27
18
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
// Ask user if they want to create a new agent or select existing one
|
|
20
|
+
const { agentChoice } = await inquirer.prompt([
|
|
21
|
+
{
|
|
22
|
+
type: "list",
|
|
23
|
+
name: "agentChoice",
|
|
24
|
+
message: "What would you like to do?",
|
|
25
|
+
choices: [
|
|
26
|
+
{ name: "Select existing agent", value: "existing" },
|
|
27
|
+
{ name: "Create new agent", value: "create" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
]);
|
|
31
|
+
// Clear the agent choice prompt lines
|
|
32
|
+
clearPromptLines(2);
|
|
33
|
+
let selectedAgent;
|
|
34
|
+
let selectedOrg;
|
|
35
|
+
let persona;
|
|
36
|
+
let welcomeMessage;
|
|
37
|
+
if (agentChoice === "existing") {
|
|
38
|
+
// Get user data from API only when selecting existing agent
|
|
39
|
+
const userData = await checkApiKey(apiKey);
|
|
40
|
+
writeProgress("✅ Authenticated");
|
|
41
|
+
// Extract organizations and create choices for selection
|
|
42
|
+
const orgs = userData.admin.orgs;
|
|
43
|
+
if (!orgs || orgs.length === 0) {
|
|
44
|
+
console.error("❌ No organizations found.");
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const orgChoices = orgs.map((org) => ({
|
|
48
|
+
name: org.registeredName || org.name || 'Unknown Organization',
|
|
49
|
+
value: org
|
|
50
|
+
}));
|
|
51
|
+
// Select organization
|
|
52
|
+
const { selectedOrg: existingOrg } = await inquirer.prompt([
|
|
53
|
+
{
|
|
54
|
+
type: "list",
|
|
55
|
+
name: "selectedOrg",
|
|
56
|
+
message: "Select an organization:",
|
|
57
|
+
choices: orgChoices
|
|
58
|
+
}
|
|
59
|
+
]);
|
|
60
|
+
selectedOrg = existingOrg;
|
|
61
|
+
// Clear the organization selection prompt lines
|
|
62
|
+
clearPromptLines(2);
|
|
63
|
+
// Extract agents from selected organization
|
|
64
|
+
if (!selectedOrg.agents || selectedOrg.agents.length === 0) {
|
|
65
|
+
console.error("❌ No agents found in the selected organization.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const agentChoices = selectedOrg.agents.map((agent) => ({
|
|
69
|
+
name: agent.name,
|
|
70
|
+
value: agent
|
|
71
|
+
}));
|
|
72
|
+
// Select agent
|
|
73
|
+
const { selectedAgent: existingAgent } = await inquirer.prompt([
|
|
74
|
+
{
|
|
75
|
+
type: "list",
|
|
76
|
+
name: "selectedAgent",
|
|
77
|
+
message: "Select an agent:",
|
|
78
|
+
choices: agentChoices
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
selectedAgent = existingAgent;
|
|
82
|
+
// Clear the agent selection prompt lines
|
|
83
|
+
clearPromptLines(2);
|
|
41
84
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
85
|
+
else {
|
|
86
|
+
// Create new agent flow
|
|
87
|
+
writeProgress("🔄 Fetching agent types...");
|
|
88
|
+
const agentTypes = await getAgentTypes(apiKey);
|
|
89
|
+
writeProgress("✅ Agent types loaded");
|
|
90
|
+
// Select agent type
|
|
91
|
+
const agentTypeChoices = agentTypes.map((type) => ({
|
|
92
|
+
name: type.name,
|
|
93
|
+
value: type
|
|
94
|
+
}));
|
|
95
|
+
const { selectedAgentType } = await inquirer.prompt([
|
|
96
|
+
{
|
|
97
|
+
type: "list",
|
|
98
|
+
name: "selectedAgentType",
|
|
99
|
+
message: "Select an agent type:",
|
|
100
|
+
choices: agentTypeChoices
|
|
101
|
+
}
|
|
102
|
+
]);
|
|
103
|
+
// Clear the agent type selection prompt lines
|
|
104
|
+
clearPromptLines(2);
|
|
105
|
+
// Collect required metadata
|
|
106
|
+
const metadata = {};
|
|
107
|
+
if (selectedAgentType.requiredSubAgentMetadata && selectedAgentType.requiredSubAgentMetadata.length > 0) {
|
|
108
|
+
for (const field of selectedAgentType.requiredSubAgentMetadata) {
|
|
109
|
+
const { [field]: value } = await inquirer.prompt([
|
|
110
|
+
{
|
|
111
|
+
type: "input",
|
|
112
|
+
name: field,
|
|
113
|
+
message: `Enter ${field}:`,
|
|
114
|
+
validate: (input) => input.trim().length > 0 || `${field} is required`
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
metadata[field] = value;
|
|
118
|
+
// Clear the metadata prompt lines
|
|
119
|
+
clearPromptLines(2);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Configure features
|
|
123
|
+
const features = {};
|
|
124
|
+
const availableFeatures = Object.keys(selectedAgentType.features);
|
|
125
|
+
if (availableFeatures.length > 0) {
|
|
126
|
+
for (const feature of availableFeatures) {
|
|
127
|
+
const { [feature]: enabled } = await inquirer.prompt([
|
|
128
|
+
{
|
|
129
|
+
type: "confirm",
|
|
130
|
+
name: feature,
|
|
131
|
+
message: `Enable ${feature} feature?`,
|
|
132
|
+
default: selectedAgentType.features[feature]?.active || false
|
|
133
|
+
}
|
|
134
|
+
]);
|
|
135
|
+
features[feature] = enabled;
|
|
136
|
+
// Clear the feature prompt lines
|
|
137
|
+
clearPromptLines(2);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Collect persona information
|
|
141
|
+
const businessTypes = [
|
|
142
|
+
"Retail & Consumer Goods (e.g. clothing store, bookstore)",
|
|
143
|
+
"Food & Beverage (e.g. restaurant, bakery)",
|
|
144
|
+
"Hospitality (e.g. hotel, resort)",
|
|
145
|
+
"Personal services (e.g. hair salon, spa)",
|
|
146
|
+
"Education (e.g. language school, online courses)",
|
|
147
|
+
"Health (e.g. gym, yoga studio, clinic)"
|
|
148
|
+
];
|
|
149
|
+
const brandPersonalities = [
|
|
150
|
+
"Energetic & fun",
|
|
151
|
+
"Refined & elegant",
|
|
152
|
+
"Chatty",
|
|
153
|
+
"Casual",
|
|
154
|
+
"Funny",
|
|
155
|
+
"Friendly"
|
|
156
|
+
];
|
|
157
|
+
const { businessName } = await inquirer.prompt([
|
|
158
|
+
{
|
|
159
|
+
type: "input",
|
|
160
|
+
name: "businessName",
|
|
161
|
+
message: "Enter business name:",
|
|
162
|
+
default: "Private"
|
|
163
|
+
}
|
|
164
|
+
]);
|
|
165
|
+
clearPromptLines(2);
|
|
166
|
+
const { agentName } = await inquirer.prompt([
|
|
167
|
+
{
|
|
168
|
+
type: "input",
|
|
169
|
+
name: "agentName",
|
|
170
|
+
message: "Enter agent name:",
|
|
171
|
+
validate: (input) => input.trim().length > 0 || "Agent name is required"
|
|
172
|
+
}
|
|
173
|
+
]);
|
|
174
|
+
clearPromptLines(2);
|
|
175
|
+
const { businessType } = await inquirer.prompt([
|
|
176
|
+
{
|
|
177
|
+
type: "list",
|
|
178
|
+
name: "businessType",
|
|
179
|
+
message: "Select business type:",
|
|
180
|
+
choices: businessTypes
|
|
181
|
+
}
|
|
182
|
+
]);
|
|
183
|
+
clearPromptLines(2);
|
|
184
|
+
const { brandPersonality } = await inquirer.prompt([
|
|
185
|
+
{
|
|
186
|
+
type: "list",
|
|
187
|
+
name: "brandPersonality",
|
|
188
|
+
message: "Select brand personality:",
|
|
189
|
+
choices: brandPersonalities
|
|
190
|
+
}
|
|
191
|
+
]);
|
|
192
|
+
clearPromptLines(2);
|
|
193
|
+
const { brandTraits } = await inquirer.prompt([
|
|
194
|
+
{
|
|
195
|
+
type: "input",
|
|
196
|
+
name: "brandTraits",
|
|
197
|
+
message: "Enter brand traits (any traits the agent might have):",
|
|
198
|
+
default: ""
|
|
199
|
+
}
|
|
200
|
+
]);
|
|
201
|
+
clearPromptLines(2);
|
|
202
|
+
// For new agents, we need to handle organization selection
|
|
203
|
+
// For now, we'll create a new organization with the business name
|
|
204
|
+
// In the future, we could add organization selection here too
|
|
205
|
+
// Create agent
|
|
206
|
+
writeProgress("🔄 Creating agent...");
|
|
207
|
+
const agentData = {
|
|
208
|
+
id: `agent_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
209
|
+
type: selectedAgentType.id,
|
|
210
|
+
metadata,
|
|
211
|
+
persona: {
|
|
212
|
+
agentName,
|
|
213
|
+
businessType,
|
|
214
|
+
brandPersonality,
|
|
215
|
+
brandTraits
|
|
216
|
+
},
|
|
217
|
+
features,
|
|
218
|
+
channels: [],
|
|
219
|
+
org: {
|
|
220
|
+
registeredName: businessName
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
const createAgentResult = await createAgent(apiKey, agentData);
|
|
224
|
+
if (!createAgentResult.success || !createAgentResult.data) {
|
|
225
|
+
console.error("❌ Failed to create agent:", createAgentResult.error?.message || "Unknown error");
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
writeProgress("✅ Agent created successfully!");
|
|
229
|
+
// Wait 30 seconds and get agent details
|
|
230
|
+
writeProgress("⏳ Waiting for agent to be ready...");
|
|
231
|
+
await new Promise(resolve => setTimeout(resolve, 30000));
|
|
232
|
+
writeProgress("🔄 Fetching agent details...");
|
|
233
|
+
const agentDetailsResult = await getAgentDetails(apiKey, createAgentResult.data.agentId);
|
|
234
|
+
if (!agentDetailsResult.success || !agentDetailsResult.data) {
|
|
235
|
+
console.error("❌ Failed to fetch agent details:", agentDetailsResult.error?.message || "Unknown error");
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
selectedAgent = {
|
|
239
|
+
agentId: createAgentResult.data.agentId,
|
|
240
|
+
name: createAgentResult.data.name
|
|
241
|
+
};
|
|
242
|
+
persona = agentDetailsResult.data.persona;
|
|
243
|
+
welcomeMessage = agentDetailsResult.data.welcomeMessage;
|
|
244
|
+
// For new agents, get the organization ID from the created agent response
|
|
245
|
+
selectedOrg = {
|
|
246
|
+
id: createAgentResult.data.org.id
|
|
247
|
+
};
|
|
248
|
+
writeProgress("✅ Agent details loaded");
|
|
56
249
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
250
|
+
// Get skill name and handle retries
|
|
251
|
+
let skillName = "";
|
|
252
|
+
let skillData = null;
|
|
253
|
+
let retry = true;
|
|
254
|
+
while (retry) {
|
|
255
|
+
const { skillName: inputSkillName } = await inquirer.prompt([
|
|
256
|
+
{
|
|
257
|
+
type: "input",
|
|
258
|
+
name: "skillName",
|
|
259
|
+
message: "Enter a name for your skill:",
|
|
260
|
+
default: "My Lua Skill"
|
|
261
|
+
}
|
|
262
|
+
]);
|
|
263
|
+
skillName = inputSkillName;
|
|
264
|
+
// Create skill via API
|
|
265
|
+
writeProgress("🔄 Creating skill...");
|
|
266
|
+
const result = await createSkill(apiKey, selectedAgent.agentId, skillName);
|
|
267
|
+
if (result.success && result.data) {
|
|
268
|
+
skillData = result.data;
|
|
269
|
+
writeProgress("✅ Skill created successfully!");
|
|
270
|
+
retry = false;
|
|
271
|
+
}
|
|
272
|
+
else if (result.error) {
|
|
273
|
+
console.error(`❌ ${result.error.message}`);
|
|
274
|
+
const { shouldRetry } = await inquirer.prompt([
|
|
275
|
+
{
|
|
276
|
+
type: "confirm",
|
|
277
|
+
name: "shouldRetry",
|
|
278
|
+
message: "Would you like to try with a different name?",
|
|
279
|
+
default: true
|
|
280
|
+
}
|
|
281
|
+
]);
|
|
282
|
+
// Clear the retry prompt lines
|
|
283
|
+
clearPromptLines(2);
|
|
284
|
+
if (!shouldRetry) {
|
|
285
|
+
writeProgress("❌ Skill creation cancelled.");
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.error("❌ Failed to create skill. Please try again.");
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Create lua.skill.yaml file with skill ID, actual skill name, persona and welcome message from backend
|
|
295
|
+
const actualSkillName = skillData?.name || skillName;
|
|
296
|
+
// Copy template files
|
|
297
|
+
const templateDir = getTemplateDir();
|
|
298
|
+
const currentDir = process.cwd();
|
|
299
|
+
copyTemplateFiles(templateDir, currentDir);
|
|
300
|
+
createSkillYaml(selectedAgent.agentId, selectedOrg.id, actualSkillName, skillData?.id, persona, welcomeMessage);
|
|
301
|
+
writeProgress("✅ Created lua.skill.yaml");
|
|
302
|
+
writeProgress("✅ Copied template files");
|
|
303
|
+
writeSuccess("✅ Lua skill project initialized successfully!");
|
|
304
|
+
}, "initialization");
|
|
70
305
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface PushVersionResponse {
|
|
2
|
+
success: boolean;
|
|
3
|
+
data?: {
|
|
4
|
+
skillsId: string;
|
|
5
|
+
version: string;
|
|
6
|
+
context: string;
|
|
7
|
+
description: string;
|
|
8
|
+
tools: any[];
|
|
9
|
+
_id: string;
|
|
10
|
+
id: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
__v: number;
|
|
14
|
+
};
|
|
15
|
+
error?: {
|
|
16
|
+
message: string;
|
|
17
|
+
error: string;
|
|
18
|
+
statusCode: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export declare function pushVersion(apiKey: string, agentId: string, skillId: string, versionData: any): Promise<PushVersionResponse>;
|
|
22
|
+
export declare function pushCommand(): Promise<void>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { compileCommand } from './compile.js';
|
|
5
|
+
import { checkApiKey, loadApiKey } from '../services/auth.js';
|
|
6
|
+
import { ApiService } from '../services/api.js';
|
|
7
|
+
import { readSkillConfig } from '../utils/files.js';
|
|
8
|
+
import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from '../utils/cli.js';
|
|
9
|
+
export async function pushVersion(apiKey, agentId, skillId, versionData) {
|
|
10
|
+
try {
|
|
11
|
+
const response = await ApiService.Skill.pushSkill(apiKey, agentId, skillId, versionData);
|
|
12
|
+
if (response.success) {
|
|
13
|
+
return {
|
|
14
|
+
success: true,
|
|
15
|
+
data: response.data
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
error: {
|
|
22
|
+
message: response.error?.message || 'Unknown error',
|
|
23
|
+
error: response.error?.message || 'Unknown error',
|
|
24
|
+
statusCode: response.error?.statusCode || 500
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error("❌ Error pushing version:", error);
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
error: {
|
|
34
|
+
message: "Network error",
|
|
35
|
+
error: "Failed to connect to server",
|
|
36
|
+
statusCode: 500
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function readConfigVersion() {
|
|
42
|
+
const config = readSkillConfig();
|
|
43
|
+
return config?.skill?.version || null;
|
|
44
|
+
}
|
|
45
|
+
function readDeployJson() {
|
|
46
|
+
const deployPath = path.join(process.cwd(), '.lua', 'deploy.json');
|
|
47
|
+
if (!fs.existsSync(deployPath)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const deployContent = fs.readFileSync(deployPath, 'utf8');
|
|
51
|
+
return JSON.parse(deployContent);
|
|
52
|
+
}
|
|
53
|
+
export async function pushCommand() {
|
|
54
|
+
return withErrorHandling(async () => {
|
|
55
|
+
// Check if we're in a skill directory
|
|
56
|
+
const config = readSkillConfig();
|
|
57
|
+
if (!config) {
|
|
58
|
+
console.error("❌ No lua.skill.yaml found. Please run this command from a skill directory.");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Read version from config
|
|
62
|
+
const version = config.skill?.version;
|
|
63
|
+
if (!version) {
|
|
64
|
+
console.error("❌ No version found in skill configuration");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
// Confirm with user
|
|
68
|
+
const { confirmed } = await inquirer.prompt([
|
|
69
|
+
{
|
|
70
|
+
type: "confirm",
|
|
71
|
+
name: "confirmed",
|
|
72
|
+
message: `Are you sure you want to push version ${version}?`,
|
|
73
|
+
default: false
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
// Clear the confirmation prompt lines
|
|
77
|
+
clearPromptLines(2);
|
|
78
|
+
if (!confirmed) {
|
|
79
|
+
console.log("❌ Push cancelled.");
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
// Load API key
|
|
83
|
+
const apiKey = await loadApiKey();
|
|
84
|
+
if (!apiKey) {
|
|
85
|
+
console.error("❌ No API key found. Please run 'lua configure' to set up your API key.");
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
// Validate API key
|
|
89
|
+
const userData = await checkApiKey(apiKey);
|
|
90
|
+
writeProgress("✅ Authenticated");
|
|
91
|
+
// Compile the skill first
|
|
92
|
+
writeProgress("🔄 Compiling skill...");
|
|
93
|
+
await compileCommand();
|
|
94
|
+
// Read deploy.json
|
|
95
|
+
const deployData = readDeployJson();
|
|
96
|
+
if (!deployData) {
|
|
97
|
+
console.error("❌ No deploy.json found. Compilation may have failed.");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
// Verify version matches
|
|
101
|
+
if (deployData.version !== version) {
|
|
102
|
+
console.error(`❌ Version mismatch: config has ${version}, deploy.json has ${deployData.version}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
// Extract agentId and skillId from config
|
|
106
|
+
const agentId = config.agent?.agentId;
|
|
107
|
+
const skillId = config.skill?.skillId;
|
|
108
|
+
if (!agentId || !skillId) {
|
|
109
|
+
console.error("❌ Missing agentId or skillId in skill configuration");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
// Push version
|
|
113
|
+
writeProgress("🔄 Pushing version to server...");
|
|
114
|
+
const result = await pushVersion(apiKey, agentId, skillId, deployData);
|
|
115
|
+
if (result.success && result.data) {
|
|
116
|
+
writeSuccess(`✅ Version ${result.data.version} pushed successfully`);
|
|
117
|
+
}
|
|
118
|
+
else if (result.error) {
|
|
119
|
+
console.error(`❌ ${result.error.message}`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.error("❌ Failed to push version. Please try again.");
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}, "push");
|
|
127
|
+
}
|
package/dist/commands/test.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import inquirer from "inquirer";
|
|
4
|
-
import {
|
|
4
|
+
import { compileCommand } from "./compile.js";
|
|
5
5
|
import { gunzipSync } from "zlib";
|
|
6
6
|
import { Buffer } from "buffer";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
import vm from "vm";
|
|
9
|
+
import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from "../utils/cli.js";
|
|
9
10
|
// Decompression utility
|
|
10
11
|
function decompressCode(compressedCode) {
|
|
11
12
|
const buffer = Buffer.from(compressedCode, 'base64');
|
|
12
13
|
return gunzipSync(buffer).toString('utf8');
|
|
13
14
|
}
|
|
14
15
|
export async function testCommand() {
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
return withErrorHandling(async () => {
|
|
17
|
+
writeProgress("🧪 Testing Lua skill...");
|
|
17
18
|
// First, compile the code
|
|
18
|
-
|
|
19
|
-
await
|
|
19
|
+
writeProgress("📦 Compiling code first...");
|
|
20
|
+
await compileCommand();
|
|
20
21
|
// Check if .lua directory exists
|
|
21
22
|
const luaDir = path.join(process.cwd(), ".lua");
|
|
22
23
|
if (!fs.existsSync(luaDir)) {
|
|
@@ -45,12 +46,14 @@ export async function testCommand() {
|
|
|
45
46
|
pageSize: 10
|
|
46
47
|
}
|
|
47
48
|
]);
|
|
48
|
-
|
|
49
|
+
// Clear the tool selection prompt lines
|
|
50
|
+
clearPromptLines(2);
|
|
51
|
+
writeProgress(`✅ Selected tool: ${selectedTool.name}`);
|
|
49
52
|
// Get input values for each required parameter using inquirer
|
|
50
53
|
const inputValues = {};
|
|
51
54
|
const inputSchema = selectedTool.inputSchema;
|
|
52
55
|
if (inputSchema.properties) {
|
|
53
|
-
|
|
56
|
+
writeProgress("\n📝 Enter input values:");
|
|
54
57
|
const inputPrompts = [];
|
|
55
58
|
for (const [key, value] of Object.entries(inputSchema.properties)) {
|
|
56
59
|
const property = value;
|
|
@@ -108,8 +111,8 @@ export async function testCommand() {
|
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
writeProgress("\n🚀 Executing tool...");
|
|
115
|
+
writeProgress(`Input: ${JSON.stringify(inputValues, null, 2)}`);
|
|
113
116
|
// Get the execute function string directly from the selected tool and decompress it
|
|
114
117
|
const toolCode = decompressCode(selectedTool.execute);
|
|
115
118
|
// Execute the tool
|
|
@@ -174,7 +177,7 @@ module.exports = async (input) => {
|
|
|
174
177
|
// Get the exported function
|
|
175
178
|
const executeFunction = context.module.exports;
|
|
176
179
|
const result = await executeFunction(inputValues);
|
|
177
|
-
|
|
180
|
+
writeSuccess("✅ Tool execution successful!");
|
|
178
181
|
console.log(`Output: ${JSON.stringify(result, null, 2)}`);
|
|
179
182
|
}
|
|
180
183
|
catch (executionError) {
|
|
@@ -184,9 +187,5 @@ module.exports = async (input) => {
|
|
|
184
187
|
console.error(executionError.stack);
|
|
185
188
|
}
|
|
186
189
|
}
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
console.error("❌ Test failed:", error.message);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
190
|
+
}, "testing");
|
|
192
191
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {};
|
|
2
|
+
export { user, createUserDataAPI, UserDataAPI } from './user-data-api.js';
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import { configureCommand, initCommand, destroyCommand, apiKeyCommand,
|
|
3
|
+
import { configureCommand, initCommand, destroyCommand, apiKeyCommand, compileCommand, testCommand, pushCommand, deployCommand, devCommand } from "./commands/index.js";
|
|
4
4
|
const program = new Command();
|
|
5
|
-
program
|
|
6
|
-
.command("
|
|
7
|
-
.description("
|
|
8
|
-
|
|
9
|
-
program
|
|
10
|
-
.command("destroy")
|
|
11
|
-
.description("Delete your stored API key")
|
|
12
|
-
.action(destroyCommand);
|
|
13
|
-
program
|
|
5
|
+
const authCommand = program
|
|
6
|
+
.command("auth")
|
|
7
|
+
.description("Authentication management commands");
|
|
8
|
+
authCommand
|
|
14
9
|
.command("configure")
|
|
15
10
|
.description("Set up your API key")
|
|
16
11
|
.action(configureCommand);
|
|
17
|
-
|
|
18
|
-
.command("
|
|
12
|
+
authCommand
|
|
13
|
+
.command("logout")
|
|
14
|
+
.description("Delete your stored API key")
|
|
15
|
+
.action(destroyCommand);
|
|
16
|
+
authCommand
|
|
17
|
+
.command("key")
|
|
19
18
|
.description("Display your stored API key")
|
|
20
19
|
.action(apiKeyCommand);
|
|
21
|
-
program
|
|
22
|
-
.command("
|
|
23
|
-
.description("
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
const skillCommand = program
|
|
21
|
+
.command("skill")
|
|
22
|
+
.description("Lua skill management commands");
|
|
23
|
+
skillCommand
|
|
24
|
+
.command("init")
|
|
25
|
+
.description("Initialize a new Lua skill project")
|
|
26
|
+
.action(initCommand);
|
|
27
|
+
skillCommand
|
|
26
28
|
.command("compile")
|
|
27
29
|
.description("Compile Lua skill to generate deployable format")
|
|
28
|
-
.action(
|
|
29
|
-
|
|
30
|
+
.action(compileCommand);
|
|
31
|
+
skillCommand
|
|
30
32
|
.command("test")
|
|
31
33
|
.description("Test Lua skill tools interactively")
|
|
32
34
|
.action(testCommand);
|
|
35
|
+
skillCommand
|
|
36
|
+
.command("push")
|
|
37
|
+
.description("Push compiled skill version to server")
|
|
38
|
+
.action(pushCommand);
|
|
39
|
+
skillCommand
|
|
40
|
+
.command("deploy")
|
|
41
|
+
.description("Deploy a version to production")
|
|
42
|
+
.action(deployCommand);
|
|
43
|
+
skillCommand
|
|
44
|
+
.command("dev")
|
|
45
|
+
.description("Push compiled skill version to sandbox for development")
|
|
46
|
+
.action(devCommand);
|
|
33
47
|
program.parse(process.argv);
|
|
48
|
+
// Export user data API for use in projects
|
|
49
|
+
export { user, createUserDataAPI, UserDataAPI } from './user-data-api.js';
|