lua-cli 1.1.4-beta.2 โ†’ 1.2.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.
@@ -0,0 +1,170 @@
1
+ # Quick Start Guide
2
+
3
+ Get up and running with Lua CLI in 5 minutes!
4
+
5
+ ## ๐Ÿš€ Installation
6
+
7
+ ```bash
8
+ npm install -g lua-cli
9
+ ```
10
+
11
+ ## ๐Ÿ“ฆ Create Your First Skill
12
+
13
+ 1. **Initialize a new project:**
14
+ ```bash
15
+ mkdir my-first-skill
16
+ cd my-first-skill
17
+ lua init
18
+ ```
19
+
20
+ 2. **Create a simple tool:**
21
+ ```typescript
22
+ // tools/HelloTool.ts
23
+ import { LuaTool } from "lua-cli/skill";
24
+ import { z } from "zod";
25
+
26
+ export default class HelloTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
27
+ name = "hello";
28
+ description = "Say hello to someone";
29
+
30
+ inputSchema = z.object({
31
+ name: z.string().describe("Name to greet")
32
+ });
33
+
34
+ outputSchema = z.object({
35
+ message: z.string(),
36
+ timestamp: z.string()
37
+ });
38
+
39
+ async execute(input) {
40
+ return {
41
+ message: `Hello, ${input.name}!`,
42
+ timestamp: new Date().toISOString()
43
+ };
44
+ }
45
+ }
46
+ ```
47
+
48
+ 3. **Register the tool:**
49
+ ```typescript
50
+ // index.ts
51
+ import { LuaSkill } from "lua-cli/skill";
52
+ import HelloTool from "./tools/HelloTool";
53
+
54
+ const skill = new LuaSkill();
55
+ skill.addTool(new HelloTool());
56
+
57
+ // Test the tool
58
+ async function test() {
59
+ const result = await skill.run({
60
+ tool: "hello",
61
+ name: "World"
62
+ });
63
+ console.log(result);
64
+ }
65
+
66
+ test().catch(console.error);
67
+ ```
68
+
69
+ 4. **Compile and test:**
70
+ ```bash
71
+ lua compile
72
+ lua test
73
+ ```
74
+
75
+ ## ๐ŸŽฏ Common Patterns
76
+
77
+ ### API Call Tool
78
+ ```typescript
79
+ import axios from "axios";
80
+
81
+ export default class WeatherTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
82
+ name = "weather";
83
+ description = "Get weather for a city";
84
+
85
+ inputSchema = z.object({
86
+ city: z.string().describe("City name")
87
+ });
88
+
89
+ outputSchema = z.object({
90
+ temperature: z.number(),
91
+ condition: z.string(),
92
+ city: z.string()
93
+ });
94
+
95
+ async execute(input) {
96
+ const response = await axios.get(`https://api.weather.com/v1/current`, {
97
+ params: { q: input.city }
98
+ });
99
+
100
+ return {
101
+ temperature: response.data.temp_c,
102
+ condition: response.data.condition.text,
103
+ city: input.city
104
+ };
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Data Processing Tool
110
+ ```typescript
111
+ export default class ProcessDataTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
112
+ name = "process_data";
113
+ description = "Process and transform data";
114
+
115
+ inputSchema = z.object({
116
+ data: z.array(z.any()).describe("Array of data to process"),
117
+ operation: z.enum(["sort", "filter", "map"]).describe("Operation to perform")
118
+ });
119
+
120
+ outputSchema = z.object({
121
+ result: z.array(z.any()),
122
+ count: z.number()
123
+ });
124
+
125
+ async execute(input) {
126
+ let result;
127
+
128
+ switch (input.operation) {
129
+ case "sort":
130
+ result = input.data.sort();
131
+ break;
132
+ case "filter":
133
+ result = input.data.filter(item => item > 0);
134
+ break;
135
+ case "map":
136
+ result = input.data.map(item => item * 2);
137
+ break;
138
+ }
139
+
140
+ return {
141
+ result,
142
+ count: result.length
143
+ };
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## ๐Ÿ”ง Next Steps
149
+
150
+ 1. **Read the full documentation:**
151
+ - [README.md](./README.md) - Complete guide
152
+ - [DEVELOPER.md](./DEVELOPER.md) - Technical details
153
+ - [API.md](./API.md) - API reference
154
+
155
+ 2. **Explore examples:**
156
+ - Check the `tools/` directory for working examples
157
+ - Look at `services/` for reusable components
158
+
159
+ 3. **Build something awesome:**
160
+ - Create tools for your specific use case
161
+ - Integrate with your favorite APIs
162
+ - Share your skills with the community
163
+
164
+ ## ๐Ÿ†˜ Need Help?
165
+
166
+ - Check the [troubleshooting section](./README.md#troubleshooting)
167
+ - Look at the [API reference](./API.md)
168
+ - Review the [developer documentation](./DEVELOPER.md)
169
+
170
+ Happy coding! ๐ŸŽ‰
@@ -0,0 +1,477 @@
1
+ # LuaSkill Template
2
+
3
+ This template provides a skeleton implementation demonstrating how to build LuaSkills with custom tools using the Lua CLI framework.
4
+
5
+ ## ๐Ÿš€ Quick Start
6
+
7
+ 1. **Install the Lua CLI globally:**
8
+ ```bash
9
+ npm install -g lua-cli
10
+ ```
11
+
12
+ 2. **Initialize a new LuaSkill project:**
13
+ ```bash
14
+ mkdir my-lua-skill
15
+ cd my-lua-skill
16
+ lua init
17
+ ```
18
+
19
+ 3. **Compile your skill:**
20
+ ```bash
21
+ lua compile
22
+ ```
23
+
24
+ 4. **Test your tools:**
25
+ ```bash
26
+ lua test
27
+ ```
28
+
29
+ ## ๐Ÿ“ Project Structure
30
+
31
+ ```
32
+ my-lua-skill/
33
+ โ”œโ”€โ”€ tools/ # Your custom tools
34
+ โ”‚ โ”œโ”€โ”€ GetWeatherTool.ts
35
+ โ”‚ โ”œโ”€โ”€ GetUserDataTool.ts
36
+ โ”‚ โ””โ”€โ”€ CreatePostTool.ts
37
+ โ”œโ”€โ”€ services/ # Shared services
38
+ โ”‚ โ”œโ”€โ”€ ApiService.ts
39
+ โ”‚ โ””โ”€โ”€ GetWeather.ts
40
+ โ”œโ”€โ”€ index.ts # Main skill definition
41
+ โ”œโ”€โ”€ package.json # Dependencies
42
+ โ””โ”€โ”€ .lua/ # Generated files (auto-created)
43
+ โ”œโ”€โ”€ deploy.json # Compiled skill data
44
+ โ””โ”€โ”€ *.js # Bundled tool files
45
+ ```
46
+
47
+ ## ๐Ÿ› ๏ธ Creating Tools
48
+
49
+ ### Basic Tool Structure
50
+
51
+ Every tool must implement the `LuaTool` interface:
52
+
53
+ ```typescript
54
+ import { LuaTool } from "lua-cli/skill";
55
+ import { z } from "zod";
56
+
57
+ export default class MyTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
58
+ name = "my_tool";
59
+ description = "Description of what this tool does";
60
+
61
+ inputSchema = z.object({
62
+ // Define your input parameters
63
+ param1: z.string().describe("Description of param1"),
64
+ param2: z.number().describe("Description of param2")
65
+ });
66
+
67
+ outputSchema = z.object({
68
+ // Define your output structure
69
+ result: z.string(),
70
+ success: z.boolean()
71
+ });
72
+
73
+ async execute(input: z.infer<typeof this.inputSchema>) {
74
+ // Your tool logic here
75
+ return {
76
+ result: "Tool executed successfully",
77
+ success: true
78
+ };
79
+ }
80
+ }
81
+ ```
82
+
83
+ ### Tool Examples
84
+
85
+ #### 1. Simple Data Processing Tool
86
+
87
+ ```typescript
88
+ import { LuaTool } from "lua-cli/skill";
89
+ import { z } from "zod";
90
+
91
+ export default class ProcessDataTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
92
+ name = "process_data";
93
+ description = "Process and transform input data";
94
+
95
+ inputSchema = z.object({
96
+ data: z.string().describe("Raw data to process"),
97
+ format: z.enum(["json", "xml", "csv"]).describe("Output format")
98
+ });
99
+
100
+ outputSchema = z.object({
101
+ processedData: z.string(),
102
+ format: z.string(),
103
+ timestamp: z.string()
104
+ });
105
+
106
+ async execute(input) {
107
+ // Process the data based on format
108
+ let processedData;
109
+ switch (input.format) {
110
+ case "json":
111
+ processedData = JSON.stringify({ data: input.data });
112
+ break;
113
+ case "xml":
114
+ processedData = `<data>${input.data}</data>`;
115
+ break;
116
+ case "csv":
117
+ processedData = `data\n"${input.data}"`;
118
+ break;
119
+ }
120
+
121
+ return {
122
+ processedData,
123
+ format: input.format,
124
+ timestamp: new Date().toISOString()
125
+ };
126
+ }
127
+ }
128
+ ```
129
+
130
+ #### 2. HTTP API Tool
131
+
132
+ ```typescript
133
+ import { LuaTool } from "lua-cli/skill";
134
+ import { z } from "zod";
135
+ import axios from "axios";
136
+
137
+ export default class ApiCallTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
138
+ name = "api_call";
139
+ description = "Make HTTP API calls";
140
+
141
+ inputSchema = z.object({
142
+ url: z.string().url().describe("API endpoint URL"),
143
+ method: z.enum(["GET", "POST", "PUT", "DELETE"]).describe("HTTP method"),
144
+ data: z.any().optional().describe("Request body data"),
145
+ headers: z.record(z.string()).optional().describe("Custom headers")
146
+ });
147
+
148
+ outputSchema = z.object({
149
+ status: z.number(),
150
+ data: z.any(),
151
+ success: z.boolean(),
152
+ error: z.string().optional()
153
+ });
154
+
155
+ async execute(input) {
156
+ try {
157
+ const response = await axios({
158
+ url: input.url,
159
+ method: input.method,
160
+ data: input.data,
161
+ headers: input.headers || {}
162
+ });
163
+
164
+ return {
165
+ status: response.status,
166
+ data: response.data,
167
+ success: true
168
+ };
169
+ } catch (error: any) {
170
+ return {
171
+ status: error.response?.status || 0,
172
+ data: null,
173
+ success: false,
174
+ error: error.message
175
+ };
176
+ }
177
+ }
178
+ }
179
+ ```
180
+
181
+ #### 3. File Operations Tool
182
+
183
+ ```typescript
184
+ import { LuaTool } from "lua-cli/skill";
185
+ import { z } from "zod";
186
+ import fs from "fs/promises";
187
+ import path from "path";
188
+
189
+ export default class FileTool implements LuaTool<z.ZodObject<any>, z.ZodObject<any>> {
190
+ name = "file_operations";
191
+ description = "Perform file system operations";
192
+
193
+ inputSchema = z.object({
194
+ operation: z.enum(["read", "write", "list", "delete"]).describe("File operation to perform"),
195
+ path: z.string().describe("File or directory path"),
196
+ content: z.string().optional().describe("Content to write (for write operations)")
197
+ });
198
+
199
+ outputSchema = z.object({
200
+ success: z.boolean(),
201
+ data: z.any().optional(),
202
+ error: z.string().optional()
203
+ });
204
+
205
+ async execute(input) {
206
+ try {
207
+ switch (input.operation) {
208
+ case "read":
209
+ const content = await fs.readFile(input.path, "utf8");
210
+ return { success: true, data: content };
211
+
212
+ case "write":
213
+ await fs.writeFile(input.path, input.content || "");
214
+ return { success: true, data: "File written successfully" };
215
+
216
+ case "list":
217
+ const files = await fs.readdir(input.path);
218
+ return { success: true, data: files };
219
+
220
+ case "delete":
221
+ await fs.unlink(input.path);
222
+ return { success: true, data: "File deleted successfully" };
223
+
224
+ default:
225
+ return { success: false, error: "Invalid operation" };
226
+ }
227
+ } catch (error: any) {
228
+ return { success: false, error: error.message };
229
+ }
230
+ }
231
+ }
232
+ ```
233
+
234
+ ## ๐Ÿ”ง Creating Services
235
+
236
+ Services provide reusable functionality across multiple tools:
237
+
238
+ ```typescript
239
+ // services/DatabaseService.ts
240
+ import axios from "axios";
241
+
242
+ export default class DatabaseService {
243
+ private baseUrl: string;
244
+
245
+ constructor(baseUrl: string) {
246
+ this.baseUrl = baseUrl;
247
+ }
248
+
249
+ async query(sql: string) {
250
+ const response = await axios.post(`${this.baseUrl}/query`, { sql });
251
+ return response.data;
252
+ }
253
+
254
+ async insert(table: string, data: any) {
255
+ const response = await axios.post(`${this.baseUrl}/insert`, { table, data });
256
+ return response.data;
257
+ }
258
+ }
259
+ ```
260
+
261
+ ## ๐Ÿ“ Main Skill Definition
262
+
263
+ Your `index.ts` file defines the skill and registers tools:
264
+
265
+ ```typescript
266
+ import { LuaSkill } from "lua-cli/skill";
267
+ import ProcessDataTool from "./tools/ProcessDataTool";
268
+ import ApiCallTool from "./tools/ApiCallTool";
269
+ import FileTool from "./tools/FileTool";
270
+
271
+ // Initialize skill
272
+ const skill = new LuaSkill();
273
+
274
+ // Add tools
275
+ skill.addTool(new ProcessDataTool());
276
+ skill.addTool(new ApiCallTool());
277
+ skill.addTool(new FileTool());
278
+
279
+ // Test cases (optional)
280
+ const testCases = [
281
+ { tool: "process_data", data: "Hello World", format: "json" },
282
+ { tool: "api_call", url: "https://httpbin.org/get", method: "GET" },
283
+ { tool: "file_operations", operation: "list", path: "./" }
284
+ ];
285
+
286
+ async function runTests() {
287
+ console.log("๐Ÿงช Running tool tests...\n");
288
+
289
+ for (const [index, testCase] of testCases.entries()) {
290
+ try {
291
+ console.log(`Test ${index + 1}: ${testCase.tool}`);
292
+ const result = await skill.run(testCase);
293
+ console.log("โœ… Success:", result);
294
+ } catch (error: any) {
295
+ console.log("โŒ Error:", error.message);
296
+ }
297
+ console.log("");
298
+ }
299
+ }
300
+
301
+ // Run tests if this file is executed directly
302
+ if (import.meta.url === `file://${process.argv[1]}`) {
303
+ runTests().catch(console.error);
304
+ }
305
+ ```
306
+
307
+ ## ๐ŸŽฏ Best Practices
308
+
309
+ ### 1. Input Validation
310
+ Always use Zod schemas for robust input validation:
311
+
312
+ ```typescript
313
+ inputSchema = z.object({
314
+ email: z.string().email().describe("Valid email address"),
315
+ age: z.number().min(0).max(120).describe("Age between 0 and 120"),
316
+ tags: z.array(z.string()).optional().describe("Optional array of tags")
317
+ });
318
+ ```
319
+
320
+ ### 2. Error Handling
321
+ Provide meaningful error messages:
322
+
323
+ ```typescript
324
+ async execute(input) {
325
+ try {
326
+ // Your logic here
327
+ return { success: true, data: result };
328
+ } catch (error: any) {
329
+ return {
330
+ success: false,
331
+ error: error.message,
332
+ timestamp: new Date().toISOString()
333
+ };
334
+ }
335
+ }
336
+ ```
337
+
338
+ ### 3. Async Operations
339
+ Use async/await for better error handling:
340
+
341
+ ```typescript
342
+ async execute(input) {
343
+ const result = await someAsyncOperation(input);
344
+ return result;
345
+ }
346
+ ```
347
+
348
+ ### 4. Service Reuse
349
+ Extract common functionality into services:
350
+
351
+ ```typescript
352
+ // In your tool
353
+ import DatabaseService from "../services/DatabaseService";
354
+
355
+ export default class UserTool {
356
+ private dbService = new DatabaseService("http://localhost:3000");
357
+
358
+ async execute(input) {
359
+ const users = await this.dbService.query("SELECT * FROM users");
360
+ return { users };
361
+ }
362
+ }
363
+ ```
364
+
365
+ ## ๐Ÿ“ฆ Dependencies
366
+
367
+ Add external dependencies to your `package.json`:
368
+
369
+ ```json
370
+ {
371
+ "dependencies": {
372
+ "axios": "^1.6.0",
373
+ "zod": "^3.22.0"
374
+ }
375
+ }
376
+ ```
377
+
378
+ The Lua CLI will automatically bundle these dependencies when you run `lua compile`.
379
+
380
+ ## ๐Ÿงช Testing
381
+
382
+ ### Interactive Testing
383
+ ```bash
384
+ lua test
385
+ ```
386
+
387
+ ### Programmatic Testing
388
+ ```typescript
389
+ const result = await skill.run({
390
+ tool: "my_tool",
391
+ param1: "value1",
392
+ param2: 42
393
+ });
394
+ console.log(result);
395
+ ```
396
+
397
+ ## ๐Ÿš€ Deployment
398
+
399
+ Once your skill is ready:
400
+
401
+ 1. **Compile:**
402
+ ```bash
403
+ lua compile
404
+ ```
405
+
406
+ 2. **Deploy:**
407
+ ```bash
408
+ lua deploy
409
+ ```
410
+
411
+ The compiled skill data will be in `.lua/deploy.json` and can be used with the Lua platform.
412
+
413
+ ## ๐Ÿ“š API Reference
414
+
415
+ ### LuaSkill Class
416
+
417
+ ```typescript
418
+ class LuaSkill {
419
+ constructor()
420
+ addTool<TInput, TOutput>(tool: LuaTool<TInput, TOutput>): void
421
+ async run(input: Record<string, any>): Promise<any>
422
+ }
423
+ ```
424
+
425
+ ### LuaTool Interface
426
+
427
+ ```typescript
428
+ interface LuaTool<TInput extends ZodType, TOutput extends ZodType> {
429
+ name: string;
430
+ description: string;
431
+ inputSchema: TInput;
432
+ outputSchema: TOutput;
433
+ execute(input: z.infer<TInput>): Promise<z.infer<TOutput>>;
434
+ }
435
+ ```
436
+
437
+ ## ๐Ÿ” Troubleshooting
438
+
439
+ ### Common Issues
440
+
441
+ 1. **"Tool not found" error:**
442
+ - Ensure the tool name matches exactly
443
+ - Check that the tool is added to the skill
444
+
445
+ 2. **Input validation errors:**
446
+ - Verify your Zod schema matches the input structure
447
+ - Check required vs optional fields
448
+
449
+ 3. **Bundling errors:**
450
+ - Ensure all dependencies are in `package.json`
451
+ - Check import paths are correct
452
+
453
+ 4. **Runtime errors:**
454
+ - Use try/catch blocks in your execute methods
455
+ - Check that all required globals are available
456
+
457
+ ### Debug Tips
458
+
459
+ - Use `console.log` for debugging (output appears in test mode)
460
+ - Test individual tools before adding to the skill
461
+ - Validate schemas with Zod's `.parse()` method
462
+ - Check the generated `.lua/deploy.json` for compilation issues
463
+
464
+ ## ๐Ÿ“– Examples
465
+
466
+ See the `tools/` directory for complete working examples:
467
+ - `GetWeatherTool.ts` - Simple API call
468
+ - `GetUserDataTool.ts` - Complex service integration
469
+ - `CreatePostTool.ts` - POST request with data
470
+
471
+ ## ๐Ÿค Contributing
472
+
473
+ Found a bug or want to add a feature? Check out our [contributing guidelines](../../CONTRIBUTING.md).
474
+
475
+ ## ๐Ÿ“„ License
476
+
477
+ This template is part of the Lua CLI framework. See the main [LICENSE](../../LICENSE) file for details.
package/template/index.ts CHANGED
@@ -1,29 +1,53 @@
1
- import z from "zod";
2
- import { LuaSkill, LuaTool } from "lua-cli/skill";
1
+ import { LuaSkill } from "lua-cli/skill";
3
2
  import GetWeatherTool from "./tools/GetWeatherTool";
4
3
  import GetUserDataTool from "./tools/GetUserDataTool";
5
4
  import CreatePostTool from "./tools/CreatePostTool";
5
+ import CalculatorTool from "./tools/CalculatorTool";
6
+ import AdvancedMathTool from "./tools/AdvancedMathTool";
6
7
 
7
- const skill = new LuaSkill("123");
8
+ // Initialize skill with tools
9
+ const skill = new LuaSkill();
8
10
  skill.addTool(new GetWeatherTool());
9
11
  skill.addTool(new GetUserDataTool());
10
12
  skill.addTool(new CreatePostTool());
13
+ skill.addTool(new CalculatorTool());
14
+ skill.addTool(new AdvancedMathTool());
15
+
16
+ // Test cases
17
+ const testCases = [
18
+ { tool: "get_weather", city: "London" },
19
+ { tool: "get_user_data", userId: "user123" },
20
+ { tool: "create_post", title: "Test Post", content: "This is a test post content" },
21
+ { tool: "calculator", operation: "add", a: 5, b: 3 },
22
+ { tool: "advanced_math", operation: "factorial", numbers: [5] },
23
+ { tool: "advanced_math", operation: "is_prime", numbers: [17] },
24
+ { tool: "advanced_math", operation: "fibonacci", numbers: [10] },
25
+ { tool: "advanced_math", operation: "gcd", numbers: [48, 18] },
26
+ // This should fail - wrong property name
27
+ { tool: "get_weather", cityLong: "London", apiKey: "123" }
28
+ ];
29
+
30
+ async function runTests() {
31
+ console.log("๐Ÿงช Running tool tests...\n");
32
+
33
+ for (const [index, testCase] of testCases.entries()) {
34
+ try {
35
+ console.log(`Test ${index + 1}: ${testCase.tool}`);
36
+ const result = await skill.run(testCase);
37
+ console.log("โœ… Success:", result);
38
+ } catch (error: any) {
39
+ console.log("โŒ Error:", error.message);
40
+ }
41
+ console.log(""); // Empty line for readability
42
+ }
43
+ }
11
44
 
12
45
  async function main() {
13
46
  try {
14
- // Test weather tool
15
- console.log("Weather tool:", await skill.run({ tool: "get_weather", city: "London" }));
16
-
17
- // Test user data tool with axios
18
- console.log("User data tool:", await skill.run({ tool: "get_user_data", userId: "user123" }));
19
-
20
- // Test post creation tool with axios
21
- console.log("Post creation tool:", await skill.run({ tool: "create_post", title: "Test Post", content: "This is a test post content" }));
22
-
23
- // This should fail - wrong property name
24
- console.log("Invalid input:", await skill.run({ tool: "get_weather", cityLong: "London", apiKey: "123" }));
25
- } catch (error: any) {
26
- console.error("Validation error:", error.message);
47
+ await runTests();
48
+ } catch (error) {
49
+ console.error("๐Ÿ’ฅ Unexpected error:", error);
50
+ process.exit(1);
27
51
  }
28
52
  }
29
53