lua-cli 1.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/LICENSE +21 -0
- package/README.md +176 -0
- package/dist/index.js +348 -0
- package/package.json +57 -0
- package/template/package.json +12 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Lua AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Lua CLI
|
|
2
|
+
|
|
3
|
+
A command-line interface for the Lua AI platform that helps you manage agents, organizations, and skills with ease.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- đ **Secure Authentication**: Support for both API key and email-based OTP authentication
|
|
8
|
+
- đĸ **Organization Management**: Select and manage multiple organizations
|
|
9
|
+
- đ¤ **Agent Management**: Choose from available agents within your organizations
|
|
10
|
+
- đ ī¸ **Skill Development**: Initialize new Lua skills with proper configuration
|
|
11
|
+
- đ **API Key Management**: Securely store, view, and manage your API keys
|
|
12
|
+
- đĻ **Template System**: Quick project setup with pre-configured templates
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Install the Lua CLI globally using npm:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g lua-cli
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
1. **Configure your authentication:**
|
|
25
|
+
```bash
|
|
26
|
+
lua configure
|
|
27
|
+
```
|
|
28
|
+
Choose between API key or email authentication methods.
|
|
29
|
+
|
|
30
|
+
2. **Initialize a new skill project:**
|
|
31
|
+
```bash
|
|
32
|
+
lua init
|
|
33
|
+
```
|
|
34
|
+
Select your organization and agent, then provide skill details.
|
|
35
|
+
|
|
36
|
+
3. **View your API key:**
|
|
37
|
+
```bash
|
|
38
|
+
lua apiKey
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. **List your agents:**
|
|
42
|
+
```bash
|
|
43
|
+
lua agents
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
5. **Delete your stored credentials:**
|
|
47
|
+
```bash
|
|
48
|
+
lua destroy
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
### `lua configure`
|
|
54
|
+
|
|
55
|
+
Set up your authentication credentials. You can choose between:
|
|
56
|
+
|
|
57
|
+
- **API Key**: Direct API key input
|
|
58
|
+
- **Email**: Email-based OTP authentication
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
lua configure
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `lua init`
|
|
65
|
+
|
|
66
|
+
Initialize a new Lua skill project in the current directory.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
lua init
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This command will:
|
|
73
|
+
- Fetch your organizations and agents from the API
|
|
74
|
+
- Let you select an organization by name
|
|
75
|
+
- Let you choose an agent from the selected organization
|
|
76
|
+
- Prompt for skill name and description
|
|
77
|
+
- Create a `lua.skill.toml` configuration file
|
|
78
|
+
- Copy template files to the current directory
|
|
79
|
+
|
|
80
|
+
### `lua apiKey`
|
|
81
|
+
|
|
82
|
+
Display your stored API key (with confirmation prompt).
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
lua apiKey
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `lua agents`
|
|
89
|
+
|
|
90
|
+
Fetch and display your agents from the HeyLua API.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
lua agents
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `lua destroy`
|
|
97
|
+
|
|
98
|
+
Delete your stored API key and credentials.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
lua destroy
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Configuration File
|
|
105
|
+
|
|
106
|
+
The `lua.skill.toml` file is created when you run `lua init`:
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[agent]
|
|
110
|
+
agentId = "your-agent-id"
|
|
111
|
+
orgId = "your-organization-id"
|
|
112
|
+
|
|
113
|
+
[skill]
|
|
114
|
+
name = "Your Skill Name"
|
|
115
|
+
description = "Description of your skill"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Authentication Methods
|
|
119
|
+
|
|
120
|
+
### API Key Authentication
|
|
121
|
+
|
|
122
|
+
1. Run `lua configure`
|
|
123
|
+
2. Select "API Key"
|
|
124
|
+
3. Enter your API key when prompted
|
|
125
|
+
4. The key is validated and stored securely
|
|
126
|
+
|
|
127
|
+
### Email Authentication
|
|
128
|
+
|
|
129
|
+
1. Run `lua configure`
|
|
130
|
+
2. Select "Email"
|
|
131
|
+
3. Enter your email address
|
|
132
|
+
4. Check your email for the OTP code
|
|
133
|
+
5. Enter the 6-digit OTP code
|
|
134
|
+
6. An API key is automatically generated and stored
|
|
135
|
+
|
|
136
|
+
## Security
|
|
137
|
+
|
|
138
|
+
- All API keys are stored securely using your system's credential manager
|
|
139
|
+
- Email authentication uses OTP (One-Time Password) for secure verification
|
|
140
|
+
- Confirmation prompts prevent accidental exposure of sensitive information
|
|
141
|
+
- No credentials are stored in plain text
|
|
142
|
+
|
|
143
|
+
## Requirements
|
|
144
|
+
|
|
145
|
+
- Node.js 16.0.0 or higher
|
|
146
|
+
- Valid Lua AI platform account
|
|
147
|
+
|
|
148
|
+
## Development
|
|
149
|
+
|
|
150
|
+
To contribute to this project:
|
|
151
|
+
|
|
152
|
+
1. Clone the repository
|
|
153
|
+
2. Install dependencies: `npm install`
|
|
154
|
+
3. Build the project: `npm run build`
|
|
155
|
+
4. Make your changes
|
|
156
|
+
5. Test your changes
|
|
157
|
+
6. Submit a pull request
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
162
|
+
|
|
163
|
+
## Support
|
|
164
|
+
|
|
165
|
+
For support and questions:
|
|
166
|
+
- Create an issue on [GitHub](https://github.com/heylua/lua-cli/issues)
|
|
167
|
+
- Contact: stefan@heylua.ai
|
|
168
|
+
|
|
169
|
+
## Changelog
|
|
170
|
+
|
|
171
|
+
### 1.0.0
|
|
172
|
+
- Initial release
|
|
173
|
+
- API key and email authentication
|
|
174
|
+
- Organization and agent management
|
|
175
|
+
- Skill project initialization
|
|
176
|
+
- Secure credential storage
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import keytar from "keytar";
|
|
5
|
+
import fetch from "node-fetch";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
const program = new Command();
|
|
10
|
+
const SERVICE = "lua-cli";
|
|
11
|
+
const ACCOUNT = "api-key";
|
|
12
|
+
async function saveApiKey(apiKey) {
|
|
13
|
+
await keytar.setPassword(SERVICE, ACCOUNT, apiKey);
|
|
14
|
+
}
|
|
15
|
+
async function loadApiKey() {
|
|
16
|
+
return keytar.getPassword(SERVICE, ACCOUNT);
|
|
17
|
+
}
|
|
18
|
+
async function deleteApiKey() {
|
|
19
|
+
return keytar.deletePassword(SERVICE, ACCOUNT);
|
|
20
|
+
}
|
|
21
|
+
async function requestEmailOTP(email) {
|
|
22
|
+
try {
|
|
23
|
+
const response = await fetch("https://auth.heylua.ai/otp", {
|
|
24
|
+
method: "POST",
|
|
25
|
+
headers: {
|
|
26
|
+
"accept": "application/json",
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
},
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
type: "email",
|
|
31
|
+
email: email
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
return response.ok;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error("â Error requesting OTP:", error);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function verifyOTPAndGetToken(email, pin) {
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch("https://auth.heylua.ai/otp/verify", {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: {
|
|
46
|
+
"accept": "application/json",
|
|
47
|
+
"Content-Type": "application/json"
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
pin: pin,
|
|
51
|
+
type: "email",
|
|
52
|
+
email: email
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
return data.signInToken;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error("â Error verifying OTP:", error);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function generateApiKey(signInToken) {
|
|
67
|
+
try {
|
|
68
|
+
const response = await fetch("https://auth.heylua.ai/profile/apiKey", {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: {
|
|
71
|
+
"Authorization": `Bearer ${signInToken}`,
|
|
72
|
+
"Content-Type": "application/json"
|
|
73
|
+
},
|
|
74
|
+
body: ""
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const data = await response.json();
|
|
80
|
+
return data.apiKey;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error("â Error generating API key:", error);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function checkApiKey(apiKey) {
|
|
88
|
+
const response = await fetch("https://api.heylua.ai/admin", {
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Bearer ${apiKey}`,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
console.error(`â Invalid API key`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
return await response.json();
|
|
98
|
+
}
|
|
99
|
+
function copyTemplateFiles(templateDir, targetDir) {
|
|
100
|
+
const files = fs.readdirSync(templateDir);
|
|
101
|
+
for (const file of files) {
|
|
102
|
+
const srcPath = path.join(templateDir, file);
|
|
103
|
+
const destPath = path.join(targetDir, file);
|
|
104
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
105
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
106
|
+
copyTemplateFiles(srcPath, destPath);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
fs.copyFileSync(srcPath, destPath);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function createSkillToml(agentId, orgId, skillName, skillDescription) {
|
|
114
|
+
const tomlContent = `[agent]
|
|
115
|
+
agentId = "${agentId}"
|
|
116
|
+
orgId = "${orgId}"
|
|
117
|
+
|
|
118
|
+
[skill]
|
|
119
|
+
name = "${skillName}"
|
|
120
|
+
description = "${skillDescription}"
|
|
121
|
+
`;
|
|
122
|
+
fs.writeFileSync("lua.skill.toml", tomlContent);
|
|
123
|
+
}
|
|
124
|
+
program
|
|
125
|
+
.command("init")
|
|
126
|
+
.description("Initialize a new Lua skill project")
|
|
127
|
+
.action(async () => {
|
|
128
|
+
const apiKey = await loadApiKey();
|
|
129
|
+
if (!apiKey) {
|
|
130
|
+
console.error("â No API key found. Run `lua configure` first.");
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
// Get user data from API
|
|
134
|
+
const userData = await checkApiKey(apiKey);
|
|
135
|
+
// Extract organizations and create choices for selection
|
|
136
|
+
const orgs = userData.admin.orgs;
|
|
137
|
+
const orgChoices = orgs.map((org) => ({
|
|
138
|
+
name: org.registeredName,
|
|
139
|
+
value: org
|
|
140
|
+
}));
|
|
141
|
+
// Select organization
|
|
142
|
+
const { selectedOrg } = await inquirer.prompt([
|
|
143
|
+
{
|
|
144
|
+
type: "list",
|
|
145
|
+
name: "selectedOrg",
|
|
146
|
+
message: "Select an organization:",
|
|
147
|
+
choices: orgChoices
|
|
148
|
+
}
|
|
149
|
+
]);
|
|
150
|
+
// Extract agents from selected organization
|
|
151
|
+
const agentChoices = selectedOrg.agents.map((agent) => ({
|
|
152
|
+
name: agent.name,
|
|
153
|
+
value: agent
|
|
154
|
+
}));
|
|
155
|
+
// Select agent
|
|
156
|
+
const { selectedAgent } = await inquirer.prompt([
|
|
157
|
+
{
|
|
158
|
+
type: "list",
|
|
159
|
+
name: "selectedAgent",
|
|
160
|
+
message: "Select an agent:",
|
|
161
|
+
choices: agentChoices
|
|
162
|
+
}
|
|
163
|
+
]);
|
|
164
|
+
// Get skill details
|
|
165
|
+
const { skillName, skillDescription } = await inquirer.prompt([
|
|
166
|
+
{
|
|
167
|
+
type: "input",
|
|
168
|
+
name: "skillName",
|
|
169
|
+
message: "Enter a name for your skill:",
|
|
170
|
+
default: "My Lua Skill"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
type: "input",
|
|
174
|
+
name: "skillDescription",
|
|
175
|
+
message: "Describe your skill:",
|
|
176
|
+
default: "A Lua skill for automation"
|
|
177
|
+
}
|
|
178
|
+
]);
|
|
179
|
+
// Create lua.skill.toml file
|
|
180
|
+
createSkillToml(selectedAgent.agentId, selectedOrg.id, skillName, skillDescription);
|
|
181
|
+
console.log("â
Created lua.skill.toml");
|
|
182
|
+
// Copy template files
|
|
183
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
184
|
+
const __dirname = path.dirname(__filename);
|
|
185
|
+
const templateDir = path.join(__dirname, "..", "template");
|
|
186
|
+
const currentDir = process.cwd();
|
|
187
|
+
copyTemplateFiles(templateDir, currentDir);
|
|
188
|
+
console.log("â
Copied template files");
|
|
189
|
+
console.log("đ Lua skill project initialized successfully!");
|
|
190
|
+
});
|
|
191
|
+
program
|
|
192
|
+
.command("destroy")
|
|
193
|
+
.description("Delete your stored API key")
|
|
194
|
+
.action(async () => {
|
|
195
|
+
const apiKey = await loadApiKey();
|
|
196
|
+
if (!apiKey) {
|
|
197
|
+
console.log("âšī¸ No API key found to delete.");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const { confirm } = await inquirer.prompt([
|
|
201
|
+
{
|
|
202
|
+
type: "confirm",
|
|
203
|
+
name: "confirm",
|
|
204
|
+
message: "Are you sure you want to delete your API key? This action cannot be undone.",
|
|
205
|
+
default: false
|
|
206
|
+
}
|
|
207
|
+
]);
|
|
208
|
+
if (confirm) {
|
|
209
|
+
const deleted = await deleteApiKey();
|
|
210
|
+
if (deleted) {
|
|
211
|
+
console.log("â
API key deleted successfully.");
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
console.log("â Failed to delete API key.");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.log("âšī¸ API key deletion cancelled.");
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
program
|
|
222
|
+
.command("configure")
|
|
223
|
+
.description("Set up your API key")
|
|
224
|
+
.action(async () => {
|
|
225
|
+
// Choose authentication method
|
|
226
|
+
const { authMethod } = await inquirer.prompt([
|
|
227
|
+
{
|
|
228
|
+
type: "list",
|
|
229
|
+
name: "authMethod",
|
|
230
|
+
message: "Choose authentication method:",
|
|
231
|
+
choices: [
|
|
232
|
+
{ name: "API Key", value: "api-key" },
|
|
233
|
+
{ name: "Email", value: "email" }
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
]);
|
|
237
|
+
if (authMethod === "api-key") {
|
|
238
|
+
// Existing API key flow
|
|
239
|
+
const answers = await inquirer.prompt([
|
|
240
|
+
{
|
|
241
|
+
type: "password",
|
|
242
|
+
name: "apiKey",
|
|
243
|
+
message: "Enter your API key",
|
|
244
|
+
mask: "*",
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
247
|
+
const data = await checkApiKey(answers.apiKey);
|
|
248
|
+
if (!data) {
|
|
249
|
+
console.error("â Invalid API key");
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
await saveApiKey(answers.apiKey);
|
|
253
|
+
console.log("â
API key saved securely.");
|
|
254
|
+
}
|
|
255
|
+
else if (authMethod === "email") {
|
|
256
|
+
// Email authentication flow
|
|
257
|
+
const { email } = await inquirer.prompt([
|
|
258
|
+
{
|
|
259
|
+
type: "input",
|
|
260
|
+
name: "email",
|
|
261
|
+
message: "Enter your email address:",
|
|
262
|
+
validate: (input) => {
|
|
263
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
264
|
+
return emailRegex.test(input) || "Please enter a valid email address";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
]);
|
|
268
|
+
console.log("đ§ Sending OTP to your email...");
|
|
269
|
+
const otpSent = await requestEmailOTP(email);
|
|
270
|
+
if (!otpSent) {
|
|
271
|
+
console.error("â Failed to send OTP. Please try again.");
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
console.log("â
OTP sent successfully!");
|
|
275
|
+
const { pin } = await inquirer.prompt([
|
|
276
|
+
{
|
|
277
|
+
type: "input",
|
|
278
|
+
name: "pin",
|
|
279
|
+
message: "Enter the OTP code:",
|
|
280
|
+
validate: (input) => {
|
|
281
|
+
return input.length === 6 || "OTP must be 6 digits";
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
]);
|
|
285
|
+
console.log("đ Verifying OTP...");
|
|
286
|
+
const signInToken = await verifyOTPAndGetToken(email, pin);
|
|
287
|
+
if (!signInToken) {
|
|
288
|
+
console.error("â Invalid OTP. Please try again.");
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
console.log("â
OTP verified successfully!");
|
|
292
|
+
console.log("đ Generating API key...");
|
|
293
|
+
const apiKey = await generateApiKey(signInToken);
|
|
294
|
+
if (!apiKey) {
|
|
295
|
+
console.error("â Failed to generate API key. Please try again.");
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
await saveApiKey(apiKey);
|
|
299
|
+
console.log("â
API key generated and saved securely.");
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
program
|
|
303
|
+
.command("apiKey")
|
|
304
|
+
.description("Display your stored API key")
|
|
305
|
+
.action(async () => {
|
|
306
|
+
const apiKey = await loadApiKey();
|
|
307
|
+
if (!apiKey) {
|
|
308
|
+
console.log("âšī¸ No API key found. Run `lua configure` first.");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const { confirm } = await inquirer.prompt([
|
|
312
|
+
{
|
|
313
|
+
type: "confirm",
|
|
314
|
+
name: "confirm",
|
|
315
|
+
message: "This will display your API key. Are you sure you want to continue?",
|
|
316
|
+
default: false
|
|
317
|
+
}
|
|
318
|
+
]);
|
|
319
|
+
if (confirm) {
|
|
320
|
+
console.log("đ Your API key:");
|
|
321
|
+
console.log(apiKey);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
console.log("âšī¸ API key display cancelled.");
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
program
|
|
328
|
+
.command("agents")
|
|
329
|
+
.description("Fetch agents from HeyLua API")
|
|
330
|
+
.action(async () => {
|
|
331
|
+
const apiKey = await loadApiKey();
|
|
332
|
+
if (!apiKey) {
|
|
333
|
+
console.error("â No API key found. Run `lua configure` first.");
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
|
336
|
+
const response = await fetch("https://api.heylua.ai/admin", {
|
|
337
|
+
headers: {
|
|
338
|
+
Authorization: `Bearer ${apiKey}`,
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
if (!response.ok) {
|
|
342
|
+
console.error(`â Error ${response.status}: ${await response.text()}`);
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
const data = await response.json();
|
|
346
|
+
console.log("â
Agents:", JSON.stringify(data, null, 2));
|
|
347
|
+
});
|
|
348
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lua-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Command-line interface for Lua AI platform - manage agents, organizations, and skills",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"prepublishOnly": "npm run build",
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"lua",
|
|
13
|
+
"ai",
|
|
14
|
+
"cli",
|
|
15
|
+
"command-line",
|
|
16
|
+
"automation",
|
|
17
|
+
"agents",
|
|
18
|
+
"api",
|
|
19
|
+
"typescript"
|
|
20
|
+
],
|
|
21
|
+
"author": "Stefan Kruger <stefan@heylua.ai>",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/heylua/lua-cli.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/heylua/lua-cli#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/heylua/lua-cli/issues"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=16.0.0"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist/**/*",
|
|
37
|
+
"template/**/*",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"commander": "^14.0.1",
|
|
43
|
+
"inquirer": "^12.9.6",
|
|
44
|
+
"keytar": "^7.9.0",
|
|
45
|
+
"node-fetch": "^3.3.2"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/inquirer": "^9.0.9",
|
|
49
|
+
"@types/node": "^24.5.1",
|
|
50
|
+
"@types/node-fetch": "^2.6.13",
|
|
51
|
+
"ts-node": "^10.9.2",
|
|
52
|
+
"typescript": "^5.9.2"
|
|
53
|
+
},
|
|
54
|
+
"bin": {
|
|
55
|
+
"lua": "dist/index.js"
|
|
56
|
+
}
|
|
57
|
+
}
|