lua-cli 2.2.8-alpha.2 → 2.3.0-alpha.1
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/API_REFERENCE.md +1408 -0
- package/CLI_REFERENCE.md +818 -0
- package/GETTING_STARTED.md +1040 -0
- package/README.md +738 -424
- package/TEMPLATE_GUIDE.md +1398 -0
- package/dist/api/agent.api.service.d.ts +33 -6
- package/dist/api/agent.api.service.js +27 -0
- package/dist/api/auth.api.service.d.ts +31 -2
- package/dist/api/auth.api.service.js +29 -0
- package/dist/api/basket.api.service.d.ts +53 -11
- package/dist/api/basket.api.service.js +63 -14
- package/dist/api/chat.api.service.d.ts +15 -3
- package/dist/api/chat.api.service.js +12 -0
- package/dist/api/credentials.d.ts +24 -0
- package/dist/api/credentials.js +46 -0
- package/dist/api/custom.data.api.service.d.ts +45 -9
- package/dist/api/custom.data.api.service.js +43 -9
- package/dist/api/lazy-instances.d.ts +49 -0
- package/dist/api/lazy-instances.js +95 -0
- package/dist/api/order.api.service.d.ts +34 -4
- package/dist/api/order.api.service.js +41 -3
- package/dist/api/products.api.service.d.ts +39 -9
- package/dist/api/products.api.service.js +43 -5
- package/dist/api/skills.api.service.d.ts +49 -2
- package/dist/api/skills.api.service.js +47 -1
- package/dist/api/tool.api.service.d.ts +39 -1
- package/dist/api/tool.api.service.js +38 -0
- package/dist/api/user.data.api.service.d.ts +23 -1
- package/dist/api/user.data.api.service.js +22 -0
- package/dist/api-exports.d.ts +236 -5
- package/dist/api-exports.js +264 -81
- package/dist/cli/command-definitions.d.ts +30 -0
- package/dist/cli/command-definitions.js +71 -0
- package/dist/commands/agents.d.ts +20 -0
- package/dist/commands/agents.js +24 -2
- package/dist/commands/apiKey.d.ts +23 -0
- package/dist/commands/apiKey.js +23 -0
- package/dist/commands/compile.d.ts +24 -0
- package/dist/commands/compile.js +67 -759
- package/dist/commands/configure.d.ts +24 -0
- package/dist/commands/configure.js +31 -96
- package/dist/commands/deploy.d.ts +31 -19
- package/dist/commands/deploy.js +45 -74
- package/dist/commands/destroy.d.ts +27 -0
- package/dist/commands/destroy.js +27 -1
- package/dist/commands/dev.d.ts +25 -62
- package/dist/commands/dev.js +58 -878
- package/dist/commands/init.d.ts +27 -0
- package/dist/commands/init.js +98 -260
- package/dist/commands/push.d.ts +24 -21
- package/dist/commands/push.js +39 -92
- package/dist/commands/test.d.ts +26 -0
- package/dist/commands/test.js +41 -188
- package/dist/common/basket.instance.d.ts +54 -3
- package/dist/common/basket.instance.js +56 -3
- package/dist/common/data.entry.instance.d.ts +25 -2
- package/dist/common/data.entry.instance.js +24 -0
- package/dist/common/http.client.d.ts +51 -1
- package/dist/common/http.client.js +50 -0
- package/dist/common/order.instance.d.ts +22 -0
- package/dist/common/order.instance.js +31 -4
- package/dist/common/product.instance.d.ts +22 -1
- package/dist/common/product.instance.js +24 -6
- package/dist/common/product.pagination.instance.d.ts +22 -2
- package/dist/common/product.pagination.instance.js +22 -1
- package/dist/common/product.search.instance.d.ts +13 -3
- package/dist/common/product.search.instance.js +12 -1
- package/dist/common/user.instance.d.ts +27 -3
- package/dist/common/user.instance.js +28 -7
- package/dist/config/auth.constants.d.ts +11 -0
- package/dist/config/auth.constants.js +11 -0
- package/dist/config/compile.constants.d.ts +67 -0
- package/dist/config/compile.constants.js +99 -0
- package/dist/config/constants.d.ts +5 -0
- package/dist/config/constants.js +5 -0
- package/dist/config/dev.constants.d.ts +65 -0
- package/dist/config/dev.constants.js +79 -0
- package/dist/config/init.constants.d.ts +23 -0
- package/dist/config/init.constants.js +41 -0
- package/dist/index.d.ts +19 -3
- package/dist/index.js +28 -44
- package/dist/interfaces/admin.d.ts +56 -50
- package/dist/interfaces/admin.js +4 -0
- package/dist/interfaces/agent.d.ts +21 -0
- package/dist/interfaces/agent.js +4 -0
- package/dist/interfaces/baskets.d.ts +60 -0
- package/dist/interfaces/baskets.js +12 -0
- package/dist/interfaces/chat.d.ts +48 -4
- package/dist/interfaces/chat.js +4 -0
- package/dist/interfaces/common.d.ts +62 -0
- package/dist/interfaces/common.js +8 -0
- package/dist/interfaces/compile.d.ts +11 -0
- package/dist/interfaces/compile.js +4 -0
- package/dist/interfaces/custom.data.d.ts +49 -19
- package/dist/interfaces/custom.data.js +4 -0
- package/dist/interfaces/deploy.d.ts +29 -0
- package/dist/interfaces/deploy.js +4 -0
- package/dist/interfaces/dev.d.ts +53 -0
- package/dist/interfaces/dev.js +5 -0
- package/dist/interfaces/init.d.ts +60 -0
- package/dist/interfaces/init.js +4 -0
- package/dist/interfaces/orders.d.ts +37 -0
- package/dist/interfaces/orders.js +12 -0
- package/dist/interfaces/product.d.ts +38 -10
- package/dist/interfaces/product.js +4 -0
- package/dist/interfaces/push.d.ts +26 -0
- package/dist/interfaces/push.js +4 -0
- package/dist/interfaces/test.d.ts +36 -0
- package/dist/interfaces/test.js +4 -0
- package/dist/services/auth.d.ts +54 -99
- package/dist/services/auth.js +76 -12
- package/dist/types/api-contracts.d.ts +211 -0
- package/dist/types/api-contracts.js +8 -0
- package/dist/types/compile.types.d.ts +76 -0
- package/dist/types/compile.types.js +4 -0
- package/dist/types/index.d.ts +23 -121
- package/dist/types/index.js +25 -14
- package/dist/types/skill.d.ts +142 -0
- package/dist/{skill.js → types/skill.js} +66 -17
- package/dist/types/tool-validation.d.ts +34 -0
- package/dist/types/tool-validation.js +42 -0
- package/dist/utils/auth-flows.d.ts +26 -0
- package/dist/utils/auth-flows.js +141 -0
- package/dist/utils/bundling.d.ts +36 -0
- package/dist/utils/bundling.js +137 -0
- package/dist/utils/compile.d.ts +37 -0
- package/dist/utils/compile.js +242 -0
- package/dist/utils/deploy-api.d.ts +26 -0
- package/dist/utils/deploy-api.js +53 -0
- package/dist/utils/deploy-helpers.d.ts +46 -0
- package/dist/utils/deploy-helpers.js +86 -0
- package/dist/utils/deployment.d.ts +25 -0
- package/dist/utils/deployment.js +161 -0
- package/dist/utils/dev-api.d.ts +61 -0
- package/dist/utils/dev-api.js +262 -0
- package/dist/utils/dev-helpers.d.ts +46 -0
- package/dist/utils/dev-helpers.js +83 -0
- package/dist/utils/dev-server.d.ts +24 -0
- package/dist/utils/dev-server.js +555 -0
- package/dist/utils/dev-watcher.d.ts +31 -0
- package/dist/utils/dev-watcher.js +110 -0
- package/dist/utils/files.js +0 -5
- package/dist/utils/init-agent.d.ts +34 -0
- package/dist/utils/init-agent.js +129 -0
- package/dist/utils/init-helpers.d.ts +41 -0
- package/dist/utils/init-helpers.js +73 -0
- package/dist/utils/init-prompts.d.ts +47 -0
- package/dist/utils/init-prompts.js +168 -0
- package/dist/utils/push-api.d.ts +15 -0
- package/dist/utils/push-api.js +48 -0
- package/dist/utils/push-helpers.d.ts +38 -0
- package/dist/utils/push-helpers.js +84 -0
- package/dist/utils/sandbox-storage.d.ts +27 -0
- package/dist/utils/sandbox-storage.js +71 -0
- package/dist/utils/sandbox.js +78 -114
- package/dist/utils/skill-management.d.ts +14 -0
- package/dist/utils/skill-management.js +148 -0
- package/dist/utils/test-helpers.d.ts +40 -0
- package/dist/utils/test-helpers.js +92 -0
- package/dist/utils/test-prompts.d.ts +23 -0
- package/dist/utils/test-prompts.js +186 -0
- package/dist/utils/tool-detection.d.ts +18 -0
- package/dist/utils/tool-detection.js +110 -0
- package/dist/web/app.css +14 -9
- package/package.json +7 -4
- package/template/QUICKSTART.md +299 -144
- package/template/README.md +928 -349
- package/template/TOOL_EXAMPLES.md +655 -0
- package/template/package-lock.json +5 -5
- package/template/package.json +1 -1
- package/template/src/index.ts +147 -207
- package/template/src/tools/BasketTool.ts +128 -0
- package/template/src/tools/CustomDataTool.ts +7 -13
- package/template/src/tools/OrderTool.ts +54 -0
- package/template/src/tools/PaymentTool.ts +1 -1
- package/template/src/tools/ProductsTool.ts +56 -118
- package/template/src/tools/UserDataTool.ts +4 -26
- package/dist/common/config.d.ts +0 -5
- package/dist/common/config.js +0 -5
- package/dist/custom-data-api.d.ts +0 -72
- package/dist/custom-data-api.js +0 -174
- package/dist/product-api.d.ts +0 -189
- package/dist/product-api.js +0 -141
- package/dist/services/api.d.ts +0 -549
- package/dist/services/api.js +0 -596
- package/dist/skill.d.ts +0 -50
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -2
- package/dist/user-data-api.d.ts +0 -39
- package/dist/user-data-api.js +0 -50
- package/template/API.md +0 -604
- package/template/DEVELOPER.md +0 -771
- package/template/lua.skill.yaml +0 -7
package/template/DEVELOPER.md
DELETED
|
@@ -1,771 +0,0 @@
|
|
|
1
|
-
# Lua CLI Developer Documentation
|
|
2
|
-
|
|
3
|
-
This document provides detailed technical information for developers building LuaSkills with the Lua CLI framework.
|
|
4
|
-
|
|
5
|
-
## 🏗️ Architecture Overview
|
|
6
|
-
|
|
7
|
-
The Lua CLI framework consists of several key components:
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
11
|
-
│ LuaSkill │ │ LuaTool │ │ Services │
|
|
12
|
-
│ (Orchestrator)│ │ (Individual │ │ (Shared │
|
|
13
|
-
│ │ │ Functions) │ │ Logic) │
|
|
14
|
-
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
15
|
-
│ │ │
|
|
16
|
-
└───────────────────────┼───────────────────────┘
|
|
17
|
-
│
|
|
18
|
-
┌─────────────────┐
|
|
19
|
-
│ Bundler │
|
|
20
|
-
│ (esbuild) │
|
|
21
|
-
└─────────────────┘
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Core Components
|
|
25
|
-
|
|
26
|
-
1. **LuaSkill**: Main orchestrator that manages tools and handles execution
|
|
27
|
-
2. **LuaTool**: Individual tool implementations with input/output schemas
|
|
28
|
-
3. **Services**: Reusable business logic shared across tools
|
|
29
|
-
4. **Bundler**: Compiles and bundles dependencies using esbuild
|
|
30
|
-
|
|
31
|
-
## 🔧 Tool Development
|
|
32
|
-
|
|
33
|
-
### Tool Lifecycle
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
// 1. Definition
|
|
37
|
-
class MyTool implements LuaTool<InputSchema, OutputSchema> {
|
|
38
|
-
// Tool metadata
|
|
39
|
-
name = "my_tool";
|
|
40
|
-
description = "Tool description";
|
|
41
|
-
|
|
42
|
-
// 2. Schema Definition
|
|
43
|
-
inputSchema = z.object({...});
|
|
44
|
-
outputSchema = z.object({...});
|
|
45
|
-
|
|
46
|
-
// 3. Execution
|
|
47
|
-
async execute(input) {
|
|
48
|
-
// Tool logic
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 4. Registration
|
|
54
|
-
const skill = new LuaSkill();
|
|
55
|
-
skill.addTool(new MyTool());
|
|
56
|
-
|
|
57
|
-
// 5. Execution
|
|
58
|
-
const result = await skill.run({ tool: "my_tool", ... });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Schema Design Patterns
|
|
62
|
-
|
|
63
|
-
#### 1. Simple Input/Output
|
|
64
|
-
```typescript
|
|
65
|
-
inputSchema = z.object({
|
|
66
|
-
text: z.string().describe("Text to process")
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
outputSchema = z.object({
|
|
70
|
-
result: z.string(),
|
|
71
|
-
length: z.number()
|
|
72
|
-
});
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
#### 2. Optional Parameters
|
|
76
|
-
```typescript
|
|
77
|
-
inputSchema = z.object({
|
|
78
|
-
required: z.string(),
|
|
79
|
-
optional: z.string().optional(),
|
|
80
|
-
withDefault: z.string().default("default value")
|
|
81
|
-
});
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
#### 3. Union Types
|
|
85
|
-
```typescript
|
|
86
|
-
inputSchema = z.object({
|
|
87
|
-
format: z.enum(["json", "xml", "csv"]),
|
|
88
|
-
data: z.union([z.string(), z.object({})])
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
#### 4. Complex Nested Objects
|
|
93
|
-
```typescript
|
|
94
|
-
inputSchema = z.object({
|
|
95
|
-
user: z.object({
|
|
96
|
-
name: z.string(),
|
|
97
|
-
email: z.string().email(),
|
|
98
|
-
preferences: z.object({
|
|
99
|
-
theme: z.enum(["light", "dark"]),
|
|
100
|
-
notifications: z.boolean()
|
|
101
|
-
}).optional()
|
|
102
|
-
}),
|
|
103
|
-
settings: z.record(z.string(), z.any())
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Error Handling Strategies
|
|
108
|
-
|
|
109
|
-
#### 1. Graceful Degradation
|
|
110
|
-
```typescript
|
|
111
|
-
async execute(input) {
|
|
112
|
-
try {
|
|
113
|
-
const result = await riskyOperation(input);
|
|
114
|
-
return { success: true, data: result };
|
|
115
|
-
} catch (error) {
|
|
116
|
-
return {
|
|
117
|
-
success: false,
|
|
118
|
-
error: error.message,
|
|
119
|
-
fallback: await getFallbackData(input)
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
#### 2. Validation Errors
|
|
126
|
-
```typescript
|
|
127
|
-
async execute(input) {
|
|
128
|
-
// Input is already validated by the framework
|
|
129
|
-
// But you can add additional validation
|
|
130
|
-
if (input.value < 0) {
|
|
131
|
-
throw new Error("Value must be positive");
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return { result: input.value * 2 };
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
#### 3. Retry Logic
|
|
139
|
-
```typescript
|
|
140
|
-
async execute(input) {
|
|
141
|
-
const maxRetries = 3;
|
|
142
|
-
let lastError;
|
|
143
|
-
|
|
144
|
-
for (let i = 0; i < maxRetries; i++) {
|
|
145
|
-
try {
|
|
146
|
-
return await unreliableOperation(input);
|
|
147
|
-
} catch (error) {
|
|
148
|
-
lastError = error;
|
|
149
|
-
if (i < maxRetries - 1) {
|
|
150
|
-
await new Promise(resolve => setTimeout(resolve, 1000 * i));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
throw lastError;
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## 🌐 Service Architecture
|
|
160
|
-
|
|
161
|
-
### Service Design Patterns
|
|
162
|
-
|
|
163
|
-
#### 1. Singleton Service
|
|
164
|
-
```typescript
|
|
165
|
-
class DatabaseService {
|
|
166
|
-
private static instance: DatabaseService;
|
|
167
|
-
private connection: Connection;
|
|
168
|
-
|
|
169
|
-
private constructor() {
|
|
170
|
-
this.connection = new Connection();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
static getInstance(): DatabaseService {
|
|
174
|
-
if (!DatabaseService.instance) {
|
|
175
|
-
DatabaseService.instance = new DatabaseService();
|
|
176
|
-
}
|
|
177
|
-
return DatabaseService.instance;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async query(sql: string) {
|
|
181
|
-
return this.connection.query(sql);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
#### 2. Factory Service
|
|
187
|
-
```typescript
|
|
188
|
-
class ApiServiceFactory {
|
|
189
|
-
static createService(type: 'rest' | 'graphql'): ApiService {
|
|
190
|
-
switch (type) {
|
|
191
|
-
case 'rest':
|
|
192
|
-
return new RestApiService();
|
|
193
|
-
case 'graphql':
|
|
194
|
-
return new GraphQLApiService();
|
|
195
|
-
default:
|
|
196
|
-
throw new Error(`Unknown service type: ${type}`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
#### 3. Dependency Injection
|
|
203
|
-
```typescript
|
|
204
|
-
class UserService {
|
|
205
|
-
constructor(
|
|
206
|
-
private dbService: DatabaseService,
|
|
207
|
-
private cacheService: CacheService
|
|
208
|
-
) {}
|
|
209
|
-
|
|
210
|
-
async getUser(id: string) {
|
|
211
|
-
// Check cache first
|
|
212
|
-
const cached = await this.cacheService.get(`user:${id}`);
|
|
213
|
-
if (cached) return cached;
|
|
214
|
-
|
|
215
|
-
// Fetch from database
|
|
216
|
-
const user = await this.dbService.query(`SELECT * FROM users WHERE id = ?`, [id]);
|
|
217
|
-
|
|
218
|
-
// Cache the result
|
|
219
|
-
await this.cacheService.set(`user:${id}`, user, 3600);
|
|
220
|
-
|
|
221
|
-
return user;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Service Integration Examples
|
|
227
|
-
|
|
228
|
-
#### 1. HTTP Client Service
|
|
229
|
-
```typescript
|
|
230
|
-
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
231
|
-
|
|
232
|
-
export class HttpClientService {
|
|
233
|
-
private client: AxiosInstance;
|
|
234
|
-
|
|
235
|
-
constructor(baseURL: string, timeout = 5000) {
|
|
236
|
-
this.client = axios.create({
|
|
237
|
-
baseURL,
|
|
238
|
-
timeout,
|
|
239
|
-
headers: {
|
|
240
|
-
'Content-Type': 'application/json',
|
|
241
|
-
'User-Agent': 'LuaSkill/1.0'
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// Add request interceptor
|
|
246
|
-
this.client.interceptors.request.use(
|
|
247
|
-
(config) => {
|
|
248
|
-
console.log(`Making ${config.method?.toUpperCase()} request to ${config.url}`);
|
|
249
|
-
return config;
|
|
250
|
-
},
|
|
251
|
-
(error) => Promise.reject(error)
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
// Add response interceptor
|
|
255
|
-
this.client.interceptors.response.use(
|
|
256
|
-
(response) => response,
|
|
257
|
-
(error) => {
|
|
258
|
-
console.error(`Request failed: ${error.message}`);
|
|
259
|
-
return Promise.reject(error);
|
|
260
|
-
}
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
265
|
-
const response = await this.client.get(url, config);
|
|
266
|
-
return response.data;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
|
|
270
|
-
const response = await this.client.post(url, data, config);
|
|
271
|
-
return response.data;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
#### 2. Database Service
|
|
277
|
-
```typescript
|
|
278
|
-
export class DatabaseService {
|
|
279
|
-
private pool: Pool;
|
|
280
|
-
|
|
281
|
-
constructor(connectionString: string) {
|
|
282
|
-
this.pool = new Pool({ connectionString });
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async query<T = any>(sql: string, params: any[] = []): Promise<T[]> {
|
|
286
|
-
const client = await this.pool.connect();
|
|
287
|
-
try {
|
|
288
|
-
const result = await client.query(sql, params);
|
|
289
|
-
return result.rows;
|
|
290
|
-
} finally {
|
|
291
|
-
client.release();
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
async transaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T> {
|
|
296
|
-
const client = await this.pool.connect();
|
|
297
|
-
try {
|
|
298
|
-
await client.query('BEGIN');
|
|
299
|
-
const result = await callback(client);
|
|
300
|
-
await client.query('COMMIT');
|
|
301
|
-
return result;
|
|
302
|
-
} catch (error) {
|
|
303
|
-
await client.query('ROLLBACK');
|
|
304
|
-
throw error;
|
|
305
|
-
} finally {
|
|
306
|
-
client.release();
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
## 📦 Bundling and Dependencies
|
|
313
|
-
|
|
314
|
-
### How Bundling Works
|
|
315
|
-
|
|
316
|
-
1. **Dependency Detection**: The bundler scans tool files for imports
|
|
317
|
-
2. **Dependency Resolution**: Uses esbuild to resolve and bundle dependencies
|
|
318
|
-
3. **Code Generation**: Creates self-contained JavaScript bundles
|
|
319
|
-
4. **Compression**: Compresses the final code for storage
|
|
320
|
-
|
|
321
|
-
### Supported Import Types
|
|
322
|
-
|
|
323
|
-
#### 1. Default Imports
|
|
324
|
-
```typescript
|
|
325
|
-
import axios from 'axios';
|
|
326
|
-
// Bundled as: const axios = require('axios');
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
#### 2. Named Imports
|
|
330
|
-
```typescript
|
|
331
|
-
import { z } from 'zod';
|
|
332
|
-
// Bundled as: const { z } = require('zod');
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
#### 3. Namespace Imports
|
|
336
|
-
```typescript
|
|
337
|
-
import * as fs from 'fs';
|
|
338
|
-
// Bundled as: const fs = require('fs');
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
#### 4. Local Imports
|
|
342
|
-
```typescript
|
|
343
|
-
import ApiService from '../services/ApiService';
|
|
344
|
-
// Resolved relative to tool file location
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### Bundling Configuration
|
|
348
|
-
|
|
349
|
-
The bundler uses the following esbuild configuration:
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
{
|
|
353
|
-
bundle: true,
|
|
354
|
-
format: 'cjs', // CommonJS for Node.js compatibility
|
|
355
|
-
platform: 'node', // Node.js platform
|
|
356
|
-
target: 'node16', // Node.js 16+ features
|
|
357
|
-
external: [], // Bundle everything (no externals)
|
|
358
|
-
minify: false, // Keep readable for debugging
|
|
359
|
-
sourcemap: false, // No source maps
|
|
360
|
-
resolveExtensions: ['.js', '.ts', '.json'],
|
|
361
|
-
mainFields: ['main', 'module', 'browser'],
|
|
362
|
-
conditions: ['node']
|
|
363
|
-
}
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### Handling Different Package Types
|
|
367
|
-
|
|
368
|
-
#### 1. CommonJS Packages
|
|
369
|
-
```typescript
|
|
370
|
-
// These work out of the box
|
|
371
|
-
import fs from 'fs';
|
|
372
|
-
import path from 'path';
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
#### 2. ES Module Packages
|
|
376
|
-
```typescript
|
|
377
|
-
// Bundled automatically
|
|
378
|
-
import axios from 'axios';
|
|
379
|
-
import { z } from 'zod';
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
#### 3. Native Modules
|
|
383
|
-
```typescript
|
|
384
|
-
// May require special handling
|
|
385
|
-
import { createHash } from 'crypto';
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
## 🧪 Testing Strategies
|
|
389
|
-
|
|
390
|
-
### Unit Testing Tools
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
394
|
-
import MyTool from '../tools/MyTool';
|
|
395
|
-
|
|
396
|
-
describe('MyTool', () => {
|
|
397
|
-
let tool: MyTool;
|
|
398
|
-
|
|
399
|
-
beforeEach(() => {
|
|
400
|
-
tool = new MyTool();
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
it('should process valid input', async () => {
|
|
404
|
-
const input = { text: 'Hello World' };
|
|
405
|
-
const result = await tool.execute(input);
|
|
406
|
-
|
|
407
|
-
expect(result).toEqual({
|
|
408
|
-
result: 'HELLO WORLD',
|
|
409
|
-
length: 11
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it('should handle invalid input', async () => {
|
|
414
|
-
const input = { text: '' };
|
|
415
|
-
|
|
416
|
-
await expect(tool.execute(input)).rejects.toThrow('Text cannot be empty');
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### Integration Testing
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
import { LuaSkill } from 'lua-cli/skill';
|
|
425
|
-
import MyTool from '../tools/MyTool';
|
|
426
|
-
|
|
427
|
-
describe('Skill Integration', () => {
|
|
428
|
-
let skill: LuaSkill;
|
|
429
|
-
|
|
430
|
-
beforeEach(() => {
|
|
431
|
-
skill = new LuaSkill();
|
|
432
|
-
skill.addTool(new MyTool());
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
it('should execute tool through skill', async () => {
|
|
436
|
-
const result = await skill.run({
|
|
437
|
-
tool: 'my_tool',
|
|
438
|
-
text: 'Hello World'
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
expect(result.result).toBe('HELLO WORLD');
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### Mocking External Dependencies
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
import { vi } from 'vitest';
|
|
450
|
-
import axios from 'axios';
|
|
451
|
-
|
|
452
|
-
// Mock axios
|
|
453
|
-
vi.mock('axios');
|
|
454
|
-
const mockedAxios = vi.mocked(axios);
|
|
455
|
-
|
|
456
|
-
describe('ApiTool', () => {
|
|
457
|
-
it('should handle API responses', async () => {
|
|
458
|
-
mockedAxios.get.mockResolvedValue({
|
|
459
|
-
data: { message: 'Success' },
|
|
460
|
-
status: 200
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
const tool = new ApiTool();
|
|
464
|
-
const result = await tool.execute({ url: 'https://api.example.com' });
|
|
465
|
-
|
|
466
|
-
expect(result.success).toBe(true);
|
|
467
|
-
expect(result.data.message).toBe('Success');
|
|
468
|
-
});
|
|
469
|
-
});
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
## 🚀 Performance Optimization
|
|
473
|
-
|
|
474
|
-
### 1. Lazy Loading
|
|
475
|
-
```typescript
|
|
476
|
-
class ExpensiveTool {
|
|
477
|
-
private expensiveService?: ExpensiveService;
|
|
478
|
-
|
|
479
|
-
private getService() {
|
|
480
|
-
if (!this.expensiveService) {
|
|
481
|
-
this.expensiveService = new ExpensiveService();
|
|
482
|
-
}
|
|
483
|
-
return this.expensiveService;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
async execute(input) {
|
|
487
|
-
const service = this.getService();
|
|
488
|
-
return service.process(input);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### 2. Caching
|
|
494
|
-
```typescript
|
|
495
|
-
class CachedTool {
|
|
496
|
-
private cache = new Map<string, any>();
|
|
497
|
-
|
|
498
|
-
async execute(input) {
|
|
499
|
-
const cacheKey = JSON.stringify(input);
|
|
500
|
-
|
|
501
|
-
if (this.cache.has(cacheKey)) {
|
|
502
|
-
return this.cache.get(cacheKey);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const result = await expensiveOperation(input);
|
|
506
|
-
this.cache.set(cacheKey, result);
|
|
507
|
-
|
|
508
|
-
return result;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
### 3. Connection Pooling
|
|
514
|
-
```typescript
|
|
515
|
-
class DatabaseTool {
|
|
516
|
-
private static pool: Pool;
|
|
517
|
-
|
|
518
|
-
static {
|
|
519
|
-
DatabaseTool.pool = new Pool({
|
|
520
|
-
connectionString: process.env.DATABASE_URL,
|
|
521
|
-
max: 20,
|
|
522
|
-
idleTimeoutMillis: 30000,
|
|
523
|
-
connectionTimeoutMillis: 2000
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
async execute(input) {
|
|
528
|
-
const client = await DatabaseTool.pool.connect();
|
|
529
|
-
try {
|
|
530
|
-
return await client.query(input.sql);
|
|
531
|
-
} finally {
|
|
532
|
-
client.release();
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
## 🔒 Security Considerations
|
|
539
|
-
|
|
540
|
-
### 1. Input Sanitization
|
|
541
|
-
```typescript
|
|
542
|
-
import DOMPurify from 'dompurify';
|
|
543
|
-
|
|
544
|
-
class SafeTool {
|
|
545
|
-
async execute(input) {
|
|
546
|
-
// Sanitize HTML input
|
|
547
|
-
const cleanHtml = DOMPurify.sanitize(input.html);
|
|
548
|
-
|
|
549
|
-
// Validate file paths
|
|
550
|
-
const safePath = path.resolve(input.basePath, input.fileName);
|
|
551
|
-
if (!safePath.startsWith(input.basePath)) {
|
|
552
|
-
throw new Error('Invalid file path');
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
return { cleanHtml, safePath };
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
### 2. Rate Limiting
|
|
561
|
-
```typescript
|
|
562
|
-
class RateLimitedTool {
|
|
563
|
-
private requests = new Map<string, number[]>();
|
|
564
|
-
|
|
565
|
-
async execute(input) {
|
|
566
|
-
const now = Date.now();
|
|
567
|
-
const windowMs = 60000; // 1 minute
|
|
568
|
-
const maxRequests = 10;
|
|
569
|
-
|
|
570
|
-
const userRequests = this.requests.get(input.userId) || [];
|
|
571
|
-
const recentRequests = userRequests.filter(time => now - time < windowMs);
|
|
572
|
-
|
|
573
|
-
if (recentRequests.length >= maxRequests) {
|
|
574
|
-
throw new Error('Rate limit exceeded');
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
recentRequests.push(now);
|
|
578
|
-
this.requests.set(input.userId, recentRequests);
|
|
579
|
-
|
|
580
|
-
return await processRequest(input);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
### 3. Secret Management
|
|
586
|
-
```typescript
|
|
587
|
-
class SecureTool {
|
|
588
|
-
async execute(input) {
|
|
589
|
-
// Never log sensitive data
|
|
590
|
-
const sanitizedInput = { ...input };
|
|
591
|
-
delete sanitizedInput.password;
|
|
592
|
-
delete sanitizedInput.apiKey;
|
|
593
|
-
|
|
594
|
-
console.log('Processing request:', sanitizedInput);
|
|
595
|
-
|
|
596
|
-
// Use environment variables for secrets
|
|
597
|
-
const apiKey = process.env.API_KEY;
|
|
598
|
-
if (!apiKey) {
|
|
599
|
-
throw new Error('API key not configured');
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
return await makeSecureRequest(input, apiKey);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
## 📊 Monitoring and Logging
|
|
608
|
-
|
|
609
|
-
### 1. Structured Logging
|
|
610
|
-
```typescript
|
|
611
|
-
class LoggedTool {
|
|
612
|
-
async execute(input) {
|
|
613
|
-
const startTime = Date.now();
|
|
614
|
-
const requestId = crypto.randomUUID();
|
|
615
|
-
|
|
616
|
-
console.log(JSON.stringify({
|
|
617
|
-
level: 'info',
|
|
618
|
-
message: 'Tool execution started',
|
|
619
|
-
requestId,
|
|
620
|
-
tool: this.name,
|
|
621
|
-
timestamp: new Date().toISOString()
|
|
622
|
-
}));
|
|
623
|
-
|
|
624
|
-
try {
|
|
625
|
-
const result = await this.processInput(input);
|
|
626
|
-
|
|
627
|
-
console.log(JSON.stringify({
|
|
628
|
-
level: 'info',
|
|
629
|
-
message: 'Tool execution completed',
|
|
630
|
-
requestId,
|
|
631
|
-
duration: Date.now() - startTime,
|
|
632
|
-
success: true
|
|
633
|
-
}));
|
|
634
|
-
|
|
635
|
-
return result;
|
|
636
|
-
} catch (error) {
|
|
637
|
-
console.log(JSON.stringify({
|
|
638
|
-
level: 'error',
|
|
639
|
-
message: 'Tool execution failed',
|
|
640
|
-
requestId,
|
|
641
|
-
duration: Date.now() - startTime,
|
|
642
|
-
error: error.message,
|
|
643
|
-
success: false
|
|
644
|
-
}));
|
|
645
|
-
|
|
646
|
-
throw error;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
### 2. Metrics Collection
|
|
653
|
-
```typescript
|
|
654
|
-
class MetricsTool {
|
|
655
|
-
private metrics = {
|
|
656
|
-
executionCount: 0,
|
|
657
|
-
successCount: 0,
|
|
658
|
-
errorCount: 0,
|
|
659
|
-
averageDuration: 0
|
|
660
|
-
};
|
|
661
|
-
|
|
662
|
-
async execute(input) {
|
|
663
|
-
const startTime = Date.now();
|
|
664
|
-
this.metrics.executionCount++;
|
|
665
|
-
|
|
666
|
-
try {
|
|
667
|
-
const result = await this.processInput(input);
|
|
668
|
-
this.metrics.successCount++;
|
|
669
|
-
return result;
|
|
670
|
-
} catch (error) {
|
|
671
|
-
this.metrics.errorCount++;
|
|
672
|
-
throw error;
|
|
673
|
-
} finally {
|
|
674
|
-
const duration = Date.now() - startTime;
|
|
675
|
-
this.updateAverageDuration(duration);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
private updateAverageDuration(duration: number) {
|
|
680
|
-
const total = this.metrics.successCount + this.metrics.errorCount;
|
|
681
|
-
this.metrics.averageDuration =
|
|
682
|
-
(this.metrics.averageDuration * (total - 1) + duration) / total;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
getMetrics() {
|
|
686
|
-
return { ...this.metrics };
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
## 🔧 Advanced Patterns
|
|
692
|
-
|
|
693
|
-
### 1. Plugin Architecture
|
|
694
|
-
```typescript
|
|
695
|
-
interface ToolPlugin {
|
|
696
|
-
name: string;
|
|
697
|
-
beforeExecute?(input: any): any;
|
|
698
|
-
afterExecute?(result: any): any;
|
|
699
|
-
onError?(error: Error): void;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
class PluggableTool {
|
|
703
|
-
private plugins: ToolPlugin[] = [];
|
|
704
|
-
|
|
705
|
-
addPlugin(plugin: ToolPlugin) {
|
|
706
|
-
this.plugins.push(plugin);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
async execute(input) {
|
|
710
|
-
let processedInput = input;
|
|
711
|
-
|
|
712
|
-
// Run before plugins
|
|
713
|
-
for (const plugin of this.plugins) {
|
|
714
|
-
if (plugin.beforeExecute) {
|
|
715
|
-
processedInput = plugin.beforeExecute(processedInput);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
try {
|
|
720
|
-
let result = await this.processInput(processedInput);
|
|
721
|
-
|
|
722
|
-
// Run after plugins
|
|
723
|
-
for (const plugin of this.plugins) {
|
|
724
|
-
if (plugin.afterExecute) {
|
|
725
|
-
result = plugin.afterExecute(result);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
return result;
|
|
730
|
-
} catch (error) {
|
|
731
|
-
// Run error plugins
|
|
732
|
-
for (const plugin of this.plugins) {
|
|
733
|
-
if (plugin.onError) {
|
|
734
|
-
plugin.onError(error);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
throw error;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
### 2. Middleware Pattern
|
|
744
|
-
```typescript
|
|
745
|
-
type Middleware = (input: any, next: () => Promise<any>) => Promise<any>;
|
|
746
|
-
|
|
747
|
-
class MiddlewareTool {
|
|
748
|
-
private middlewares: Middleware[] = [];
|
|
749
|
-
|
|
750
|
-
use(middleware: Middleware) {
|
|
751
|
-
this.middlewares.push(middleware);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
async execute(input) {
|
|
755
|
-
let index = 0;
|
|
756
|
-
|
|
757
|
-
const next = async (): Promise<any> => {
|
|
758
|
-
if (index >= this.middlewares.length) {
|
|
759
|
-
return this.processInput(input);
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
const middleware = this.middlewares[index++];
|
|
763
|
-
return middleware(input, next);
|
|
764
|
-
};
|
|
765
|
-
|
|
766
|
-
return next();
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
```
|
|
770
|
-
|
|
771
|
-
This developer documentation provides comprehensive technical guidance for building robust, scalable LuaSkills with the Lua CLI framework.
|