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.
Files changed (193) hide show
  1. package/API_REFERENCE.md +1408 -0
  2. package/CLI_REFERENCE.md +818 -0
  3. package/GETTING_STARTED.md +1040 -0
  4. package/README.md +738 -424
  5. package/TEMPLATE_GUIDE.md +1398 -0
  6. package/dist/api/agent.api.service.d.ts +33 -6
  7. package/dist/api/agent.api.service.js +27 -0
  8. package/dist/api/auth.api.service.d.ts +31 -2
  9. package/dist/api/auth.api.service.js +29 -0
  10. package/dist/api/basket.api.service.d.ts +53 -11
  11. package/dist/api/basket.api.service.js +63 -14
  12. package/dist/api/chat.api.service.d.ts +15 -3
  13. package/dist/api/chat.api.service.js +12 -0
  14. package/dist/api/credentials.d.ts +24 -0
  15. package/dist/api/credentials.js +46 -0
  16. package/dist/api/custom.data.api.service.d.ts +45 -9
  17. package/dist/api/custom.data.api.service.js +43 -9
  18. package/dist/api/lazy-instances.d.ts +49 -0
  19. package/dist/api/lazy-instances.js +95 -0
  20. package/dist/api/order.api.service.d.ts +34 -4
  21. package/dist/api/order.api.service.js +41 -3
  22. package/dist/api/products.api.service.d.ts +39 -9
  23. package/dist/api/products.api.service.js +43 -5
  24. package/dist/api/skills.api.service.d.ts +49 -2
  25. package/dist/api/skills.api.service.js +47 -1
  26. package/dist/api/tool.api.service.d.ts +39 -1
  27. package/dist/api/tool.api.service.js +38 -0
  28. package/dist/api/user.data.api.service.d.ts +23 -1
  29. package/dist/api/user.data.api.service.js +22 -0
  30. package/dist/api-exports.d.ts +236 -5
  31. package/dist/api-exports.js +264 -81
  32. package/dist/cli/command-definitions.d.ts +30 -0
  33. package/dist/cli/command-definitions.js +71 -0
  34. package/dist/commands/agents.d.ts +20 -0
  35. package/dist/commands/agents.js +24 -2
  36. package/dist/commands/apiKey.d.ts +23 -0
  37. package/dist/commands/apiKey.js +23 -0
  38. package/dist/commands/compile.d.ts +24 -0
  39. package/dist/commands/compile.js +67 -759
  40. package/dist/commands/configure.d.ts +24 -0
  41. package/dist/commands/configure.js +31 -96
  42. package/dist/commands/deploy.d.ts +31 -19
  43. package/dist/commands/deploy.js +45 -74
  44. package/dist/commands/destroy.d.ts +27 -0
  45. package/dist/commands/destroy.js +27 -1
  46. package/dist/commands/dev.d.ts +25 -62
  47. package/dist/commands/dev.js +58 -878
  48. package/dist/commands/init.d.ts +27 -0
  49. package/dist/commands/init.js +98 -260
  50. package/dist/commands/push.d.ts +24 -21
  51. package/dist/commands/push.js +39 -92
  52. package/dist/commands/test.d.ts +26 -0
  53. package/dist/commands/test.js +41 -188
  54. package/dist/common/basket.instance.d.ts +54 -3
  55. package/dist/common/basket.instance.js +56 -3
  56. package/dist/common/data.entry.instance.d.ts +25 -2
  57. package/dist/common/data.entry.instance.js +24 -0
  58. package/dist/common/http.client.d.ts +51 -1
  59. package/dist/common/http.client.js +50 -0
  60. package/dist/common/order.instance.d.ts +22 -0
  61. package/dist/common/order.instance.js +31 -4
  62. package/dist/common/product.instance.d.ts +22 -1
  63. package/dist/common/product.instance.js +24 -6
  64. package/dist/common/product.pagination.instance.d.ts +22 -2
  65. package/dist/common/product.pagination.instance.js +22 -1
  66. package/dist/common/product.search.instance.d.ts +13 -3
  67. package/dist/common/product.search.instance.js +12 -1
  68. package/dist/common/user.instance.d.ts +27 -3
  69. package/dist/common/user.instance.js +28 -7
  70. package/dist/config/auth.constants.d.ts +11 -0
  71. package/dist/config/auth.constants.js +11 -0
  72. package/dist/config/compile.constants.d.ts +67 -0
  73. package/dist/config/compile.constants.js +99 -0
  74. package/dist/config/constants.d.ts +5 -0
  75. package/dist/config/constants.js +5 -0
  76. package/dist/config/dev.constants.d.ts +65 -0
  77. package/dist/config/dev.constants.js +79 -0
  78. package/dist/config/init.constants.d.ts +23 -0
  79. package/dist/config/init.constants.js +41 -0
  80. package/dist/index.d.ts +19 -3
  81. package/dist/index.js +28 -44
  82. package/dist/interfaces/admin.d.ts +56 -50
  83. package/dist/interfaces/admin.js +4 -0
  84. package/dist/interfaces/agent.d.ts +21 -0
  85. package/dist/interfaces/agent.js +4 -0
  86. package/dist/interfaces/baskets.d.ts +60 -0
  87. package/dist/interfaces/baskets.js +12 -0
  88. package/dist/interfaces/chat.d.ts +48 -4
  89. package/dist/interfaces/chat.js +4 -0
  90. package/dist/interfaces/common.d.ts +62 -0
  91. package/dist/interfaces/common.js +8 -0
  92. package/dist/interfaces/compile.d.ts +11 -0
  93. package/dist/interfaces/compile.js +4 -0
  94. package/dist/interfaces/custom.data.d.ts +49 -19
  95. package/dist/interfaces/custom.data.js +4 -0
  96. package/dist/interfaces/deploy.d.ts +29 -0
  97. package/dist/interfaces/deploy.js +4 -0
  98. package/dist/interfaces/dev.d.ts +53 -0
  99. package/dist/interfaces/dev.js +5 -0
  100. package/dist/interfaces/init.d.ts +60 -0
  101. package/dist/interfaces/init.js +4 -0
  102. package/dist/interfaces/orders.d.ts +37 -0
  103. package/dist/interfaces/orders.js +12 -0
  104. package/dist/interfaces/product.d.ts +38 -10
  105. package/dist/interfaces/product.js +4 -0
  106. package/dist/interfaces/push.d.ts +26 -0
  107. package/dist/interfaces/push.js +4 -0
  108. package/dist/interfaces/test.d.ts +36 -0
  109. package/dist/interfaces/test.js +4 -0
  110. package/dist/services/auth.d.ts +54 -99
  111. package/dist/services/auth.js +76 -12
  112. package/dist/types/api-contracts.d.ts +211 -0
  113. package/dist/types/api-contracts.js +8 -0
  114. package/dist/types/compile.types.d.ts +76 -0
  115. package/dist/types/compile.types.js +4 -0
  116. package/dist/types/index.d.ts +23 -121
  117. package/dist/types/index.js +25 -14
  118. package/dist/types/skill.d.ts +142 -0
  119. package/dist/{skill.js → types/skill.js} +66 -17
  120. package/dist/types/tool-validation.d.ts +34 -0
  121. package/dist/types/tool-validation.js +42 -0
  122. package/dist/utils/auth-flows.d.ts +26 -0
  123. package/dist/utils/auth-flows.js +141 -0
  124. package/dist/utils/bundling.d.ts +36 -0
  125. package/dist/utils/bundling.js +137 -0
  126. package/dist/utils/compile.d.ts +37 -0
  127. package/dist/utils/compile.js +242 -0
  128. package/dist/utils/deploy-api.d.ts +26 -0
  129. package/dist/utils/deploy-api.js +53 -0
  130. package/dist/utils/deploy-helpers.d.ts +46 -0
  131. package/dist/utils/deploy-helpers.js +86 -0
  132. package/dist/utils/deployment.d.ts +25 -0
  133. package/dist/utils/deployment.js +161 -0
  134. package/dist/utils/dev-api.d.ts +61 -0
  135. package/dist/utils/dev-api.js +262 -0
  136. package/dist/utils/dev-helpers.d.ts +46 -0
  137. package/dist/utils/dev-helpers.js +83 -0
  138. package/dist/utils/dev-server.d.ts +24 -0
  139. package/dist/utils/dev-server.js +555 -0
  140. package/dist/utils/dev-watcher.d.ts +31 -0
  141. package/dist/utils/dev-watcher.js +110 -0
  142. package/dist/utils/files.js +0 -5
  143. package/dist/utils/init-agent.d.ts +34 -0
  144. package/dist/utils/init-agent.js +129 -0
  145. package/dist/utils/init-helpers.d.ts +41 -0
  146. package/dist/utils/init-helpers.js +73 -0
  147. package/dist/utils/init-prompts.d.ts +47 -0
  148. package/dist/utils/init-prompts.js +168 -0
  149. package/dist/utils/push-api.d.ts +15 -0
  150. package/dist/utils/push-api.js +48 -0
  151. package/dist/utils/push-helpers.d.ts +38 -0
  152. package/dist/utils/push-helpers.js +84 -0
  153. package/dist/utils/sandbox-storage.d.ts +27 -0
  154. package/dist/utils/sandbox-storage.js +71 -0
  155. package/dist/utils/sandbox.js +78 -114
  156. package/dist/utils/skill-management.d.ts +14 -0
  157. package/dist/utils/skill-management.js +148 -0
  158. package/dist/utils/test-helpers.d.ts +40 -0
  159. package/dist/utils/test-helpers.js +92 -0
  160. package/dist/utils/test-prompts.d.ts +23 -0
  161. package/dist/utils/test-prompts.js +186 -0
  162. package/dist/utils/tool-detection.d.ts +18 -0
  163. package/dist/utils/tool-detection.js +110 -0
  164. package/dist/web/app.css +14 -9
  165. package/package.json +7 -4
  166. package/template/QUICKSTART.md +299 -144
  167. package/template/README.md +928 -349
  168. package/template/TOOL_EXAMPLES.md +655 -0
  169. package/template/package-lock.json +5 -5
  170. package/template/package.json +1 -1
  171. package/template/src/index.ts +147 -207
  172. package/template/src/tools/BasketTool.ts +128 -0
  173. package/template/src/tools/CustomDataTool.ts +7 -13
  174. package/template/src/tools/OrderTool.ts +54 -0
  175. package/template/src/tools/PaymentTool.ts +1 -1
  176. package/template/src/tools/ProductsTool.ts +56 -118
  177. package/template/src/tools/UserDataTool.ts +4 -26
  178. package/dist/common/config.d.ts +0 -5
  179. package/dist/common/config.js +0 -5
  180. package/dist/custom-data-api.d.ts +0 -72
  181. package/dist/custom-data-api.js +0 -174
  182. package/dist/product-api.d.ts +0 -189
  183. package/dist/product-api.js +0 -141
  184. package/dist/services/api.d.ts +0 -549
  185. package/dist/services/api.js +0 -596
  186. package/dist/skill.d.ts +0 -50
  187. package/dist/types.d.ts +0 -1
  188. package/dist/types.js +0 -2
  189. package/dist/user-data-api.d.ts +0 -39
  190. package/dist/user-data-api.js +0 -50
  191. package/template/API.md +0 -604
  192. package/template/DEVELOPER.md +0 -771
  193. package/template/lua.skill.yaml +0 -7
@@ -0,0 +1,1408 @@
1
+ # Lua CLI - API Reference
2
+
3
+ Complete API reference for building Lua AI skills.
4
+
5
+ ---
6
+
7
+ ## 📋 Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Core Concepts](#core-concepts)
11
+ - [LuaSkill Class](#luaskill-class)
12
+ - [LuaTool Interface](#luatool-interface)
13
+ - [Platform APIs](#platform-apis)
14
+ - [Environment Variables](#environment-variables)
15
+ - [Complete Examples](#complete-examples)
16
+
17
+ ---
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install lua-cli zod
23
+ ```
24
+
25
+ **Dependencies:**
26
+ - `lua-cli` - Lua CLI and APIs
27
+ - `zod` - Schema validation (peer dependency)
28
+
29
+ ---
30
+
31
+ ## Core Concepts
32
+
33
+ ### What is a Lua Skill?
34
+
35
+ A **skill** is a collection of **tools** that an AI agent can use. Each tool:
36
+ - Has a specific purpose (e.g., "get weather", "create order")
37
+ - Accepts validated inputs (using Zod schemas)
38
+ - Returns structured outputs
39
+ - Can call external APIs, databases, or services
40
+
41
+ ### Architecture
42
+
43
+ ```
44
+ LuaSkill
45
+ ├── Tool 1 (e.g., Get Weather)
46
+ ├── Tool 2 (e.g., Create Product)
47
+ └── Tool 3 (e.g., Send Email)
48
+ ```
49
+
50
+ The AI agent:
51
+ 1. Receives user request
52
+ 2. Selects appropriate tool(s)
53
+ 3. Calls tools with validated inputs
54
+ 4. Returns results to user
55
+
56
+ ---
57
+
58
+ ## LuaSkill Class
59
+
60
+ ### Importing
61
+
62
+ ```typescript
63
+ import { LuaSkill } from 'lua-cli';
64
+ ```
65
+
66
+ ### Constructor
67
+
68
+ ```typescript
69
+ new LuaSkill(config: LuaSkillConfig)
70
+ ```
71
+
72
+ **Parameters:**
73
+
74
+ | Parameter | Type | Required | Description |
75
+ |-----------|------|----------|-------------|
76
+ | `config.name` | string | No | Skill name (default: 'unnamed-skill') |
77
+ | `config.version` | string | No | Skill version (default: '1.0.0') |
78
+ | `config.description` | string | Yes | Brief description (1-2 sentences) |
79
+ | `config.context` | string | Yes | Detailed usage instructions for the AI |
80
+ | `config.tools` | LuaTool[] | No | Array of tools to add immediately |
81
+
82
+ **Example:**
83
+
84
+ ```typescript
85
+ const skill = new LuaSkill({
86
+ name: 'weather-skill',
87
+ version: '1.0.0',
88
+ description: 'Provides weather information for any city',
89
+ context: 'Use the get_weather tool when users ask about weather, temperature, or conditions. The tool requires a city name and returns current weather data.',
90
+ tools: [new GetWeatherTool()]
91
+ });
92
+ ```
93
+
94
+ ### Methods
95
+
96
+ #### `addTool(tool: LuaTool): void`
97
+
98
+ Adds a single tool to the skill.
99
+
100
+ ```typescript
101
+ skill.addTool(new MyTool());
102
+ ```
103
+
104
+ **Validation:**
105
+ - Tool name must be unique
106
+ - Tool name must only contain: `a-z`, `A-Z`, `0-9`, `-`, `_`
107
+ - Throws error if validation fails
108
+
109
+ ---
110
+
111
+ #### `addTools(tools: LuaTool[]): void`
112
+
113
+ Adds multiple tools to the skill.
114
+
115
+ ```typescript
116
+ skill.addTools([
117
+ new Tool1(),
118
+ new Tool2(),
119
+ new Tool3()
120
+ ]);
121
+ ```
122
+
123
+ **Validation:**
124
+ - All tools validated before adding
125
+ - Atomic operation (all or nothing)
126
+
127
+ ---
128
+
129
+ ### Best Practices
130
+
131
+ **✅ Good Context:**
132
+ ```typescript
133
+ context: "Use get_weather for current conditions. Use search_products when users want to find items. Use create_order to complete purchases. Always confirm details before creating orders."
134
+ ```
135
+
136
+ **❌ Poor Context:**
137
+ ```typescript
138
+ context: "A skill with tools"
139
+ ```
140
+
141
+ **Tips:**
142
+ - Be specific about when to use each tool
143
+ - Mention required vs optional parameters
144
+ - Include edge cases and limitations
145
+ - Give the AI clear decision criteria
146
+
147
+ ---
148
+
149
+ ## LuaTool Interface
150
+
151
+ ### Structure
152
+
153
+ ```typescript
154
+ interface LuaTool<TInput extends ZodType = ZodType> {
155
+ name: string;
156
+ description: string;
157
+ inputSchema: TInput;
158
+ execute: (input: any) => Promise<any>;
159
+ }
160
+ ```
161
+
162
+ ### Implementing a Tool
163
+
164
+ #### Method 1: Class Implementation
165
+
166
+ ```typescript
167
+ import { LuaTool } from 'lua-cli';
168
+ import { z } from 'zod';
169
+
170
+ export default class GetWeatherTool implements LuaTool {
171
+ name = "get_weather";
172
+ description = "Get current weather for a city";
173
+
174
+ inputSchema = z.object({
175
+ city: z.string().describe("City name"),
176
+ units: z.enum(['metric', 'imperial']).optional()
177
+ });
178
+
179
+ async execute(input: z.infer<typeof this.inputSchema>) {
180
+ // input is automatically validated and typed
181
+ const { city, units = 'metric' } = input;
182
+
183
+ // Call weather API...
184
+ const weather = await fetchWeather(city, units);
185
+
186
+ return {
187
+ temperature: weather.temp,
188
+ condition: weather.condition,
189
+ city: weather.location
190
+ };
191
+ }
192
+ }
193
+ ```
194
+
195
+ #### Method 2: Object Implementation
196
+
197
+ ```typescript
198
+ const weatherTool: LuaTool = {
199
+ name: "get_weather",
200
+ description: "Get current weather for a city",
201
+ inputSchema: z.object({
202
+ city: z.string()
203
+ }),
204
+ async execute(input) {
205
+ // Implementation...
206
+ return { temperature: 72 };
207
+ }
208
+ };
209
+ ```
210
+
211
+ ### Tool Properties
212
+
213
+ #### `name: string`
214
+
215
+ - **Format**: Lowercase, alphanumeric, hyphens, underscores only
216
+ - **Valid**: `get_weather`, `create-product`, `sendEmail123`
217
+ - **Invalid**: `get weather`, `create.product`, `send@email`
218
+ - **Purpose**: Unique identifier for the tool
219
+
220
+ ---
221
+
222
+ #### `description: string`
223
+
224
+ - **Format**: Clear, concise description (1 sentence)
225
+ - **Purpose**: Helps AI understand when to use the tool
226
+ - **Best Practice**: Mention what the tool does and its primary use case
227
+
228
+ **Examples:**
229
+ ```typescript
230
+ description = "Get current weather conditions for any city worldwide"
231
+ description = "Create a new product in the catalog with price and details"
232
+ description = "Search for products by name, category, or description"
233
+ ```
234
+
235
+ ---
236
+
237
+ #### `inputSchema: ZodType`
238
+
239
+ Zod schema defining valid inputs.
240
+
241
+ **Simple Schema:**
242
+ ```typescript
243
+ inputSchema = z.object({
244
+ city: z.string()
245
+ });
246
+ ```
247
+
248
+ **Complex Schema:**
249
+ ```typescript
250
+ inputSchema = z.object({
251
+ city: z.string().describe("City name"),
252
+ units: z.enum(['metric', 'imperial']).default('metric'),
253
+ includeForecast: z.boolean().optional(),
254
+ days: z.number().min(1).max(7).optional()
255
+ });
256
+ ```
257
+
258
+ **Nested Schema:**
259
+ ```typescript
260
+ inputSchema = z.object({
261
+ user: z.object({
262
+ name: z.string(),
263
+ email: z.string().email()
264
+ }),
265
+ preferences: z.object({
266
+ notifications: z.boolean(),
267
+ language: z.string()
268
+ }).optional()
269
+ });
270
+ ```
271
+
272
+ **Supported Types:**
273
+ - `z.string()` - String values
274
+ - `z.number()` - Numeric values
275
+ - `z.boolean()` - True/false
276
+ - `z.enum([...])` - Fixed set of values
277
+ - `z.array(T)` - Arrays
278
+ - `z.object({...})` - Nested objects
279
+ - `.optional()` - Optional fields
280
+ - `.default(value)` - Default values
281
+
282
+ ---
283
+
284
+ #### `execute: (input: any) => Promise<any>`
285
+
286
+ Async function that implements the tool logic.
287
+
288
+ **Signature:**
289
+ ```typescript
290
+ async execute(input: z.infer<typeof this.inputSchema>) {
291
+ // Implementation
292
+ return result;
293
+ }
294
+ ```
295
+
296
+ **Input:**
297
+ - Automatically validated against `inputSchema`
298
+ - Type-safe when using `z.infer<typeof this.inputSchema>`
299
+
300
+ **Return:**
301
+ - Can return any JSON-serializable value
302
+ - Should return structured data when possible
303
+
304
+ **Error Handling:**
305
+ ```typescript
306
+ async execute(input: any) {
307
+ // Throw descriptive errors
308
+ if (!input.id) {
309
+ throw new Error("ID is required");
310
+ }
311
+
312
+ try {
313
+ const result = await externalApi.call(input);
314
+ return result;
315
+ } catch (error) {
316
+ // Re-throw with context
317
+ throw new Error(`Failed to call external API: ${error.message}`);
318
+ }
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Platform APIs
325
+
326
+ The Lua CLI provides built-in APIs for common operations.
327
+
328
+ ### Importing
329
+
330
+ ```typescript
331
+ import { User, Data, Products, Baskets, Orders } from 'lua-cli';
332
+ ```
333
+
334
+ ---
335
+
336
+ ## User API
337
+
338
+ Access and manage user data.
339
+
340
+ ### `User.get()`
341
+
342
+ Retrieves the current user's data.
343
+
344
+ **Usage:**
345
+ ```typescript
346
+ const user = await User.get();
347
+ ```
348
+
349
+ **Returns:**
350
+ ```typescript
351
+ {
352
+ id: string;
353
+ email: string;
354
+ name: string;
355
+ // ... additional user fields
356
+ }
357
+ ```
358
+
359
+ **Example:**
360
+ ```typescript
361
+ export class GetUserDataTool implements LuaTool {
362
+ name = "get_user_data";
363
+ description = "Retrieve current user's information";
364
+ inputSchema = z.object({});
365
+
366
+ async execute(input: any) {
367
+ const user = await User.get();
368
+ return {
369
+ name: user.name,
370
+ email: user.email
371
+ };
372
+ }
373
+ }
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Data API
379
+
380
+ Store and retrieve custom data with vector search.
381
+
382
+ ### `Data.create(collectionName, data, searchText?)`
383
+
384
+ Creates a new entry in a collection.
385
+
386
+ **Parameters:**
387
+
388
+ | Parameter | Type | Required | Description |
389
+ |-----------|------|----------|-------------|
390
+ | `collectionName` | string | Yes | Collection name (e.g., 'movies', 'customers') |
391
+ | `data` | object | Yes | Data to store (any JSON object) |
392
+ | `searchText` | string | No | Text for vector search indexing |
393
+
394
+ **Usage:**
395
+ ```typescript
396
+ const entry = await Data.create('movies', {
397
+ title: 'Inception',
398
+ year: 2010,
399
+ director: 'Christopher Nolan'
400
+ }, 'Inception 2010 Christopher Nolan sci-fi thriller');
401
+ ```
402
+
403
+ **Returns:**
404
+ ```typescript
405
+ {
406
+ id: string;
407
+ data: object;
408
+ createdAt: number;
409
+ updatedAt: number;
410
+ searchText?: string;
411
+ }
412
+ ```
413
+
414
+ ---
415
+
416
+ ### `Data.get(collectionName, filter?, page?, limit?)`
417
+
418
+ Retrieves entries from a collection.
419
+
420
+ **Parameters:**
421
+
422
+ | Parameter | Type | Default | Description |
423
+ |-----------|------|---------|-------------|
424
+ | `collectionName` | string | - | Collection name |
425
+ | `filter` | object | {} | Filter criteria |
426
+ | `page` | number | 1 | Page number |
427
+ | `limit` | number | 10 | Items per page |
428
+
429
+ **Usage:**
430
+ ```typescript
431
+ // Get all
432
+ const movies = await Data.get('movies');
433
+
434
+ // With pagination
435
+ const page2 = await Data.get('movies', {}, 2, 20);
436
+
437
+ // With filter
438
+ const recentMovies = await Data.get('movies', { year: { $gte: 2020 } });
439
+ ```
440
+
441
+ **Returns:**
442
+ ```typescript
443
+ {
444
+ data: Entry[];
445
+ pagination: {
446
+ currentPage: number;
447
+ totalPages: number;
448
+ totalCount: number;
449
+ // ...
450
+ };
451
+ }
452
+ ```
453
+
454
+ ---
455
+
456
+ ### `Data.getEntry(collectionName, entryId)`
457
+
458
+ Retrieves a specific entry by ID.
459
+
460
+ **Usage:**
461
+ ```typescript
462
+ const movie = await Data.getEntry('movies', 'entry_abc123');
463
+ ```
464
+
465
+ ---
466
+
467
+ ### `Data.update(collectionName, entryId, data)`
468
+
469
+ Updates an existing entry.
470
+
471
+ **Usage:**
472
+ ```typescript
473
+ const updated = await Data.update('movies', 'entry_abc123', {
474
+ rating: 9.5,
475
+ reviews: 1000
476
+ });
477
+ ```
478
+
479
+ ---
480
+
481
+ ### `Data.search(collectionName, searchText, limit?, scoreThreshold?)`
482
+
483
+ Performs vector search on a collection.
484
+
485
+ **Parameters:**
486
+
487
+ | Parameter | Type | Default | Description |
488
+ |-----------|------|---------|-------------|
489
+ | `collectionName` | string | - | Collection name |
490
+ | `searchText` | string | - | Search query |
491
+ | `limit` | number | 10 | Max results |
492
+ | `scoreThreshold` | number | 0.7 | Min similarity (0-1) |
493
+
494
+ **Usage:**
495
+ ```typescript
496
+ const results = await Data.search(
497
+ 'movies',
498
+ 'sci-fi thriller about dreams',
499
+ 5,
500
+ 0.8
501
+ );
502
+ ```
503
+
504
+ **Returns:**
505
+ ```typescript
506
+ {
507
+ data: Array<Entry & { score: number }>;
508
+ count: number;
509
+ }
510
+ ```
511
+
512
+ **Similarity Scores:**
513
+ - `1.0` = Perfect match
514
+ - `0.8-0.9` = Very similar
515
+ - `0.6-0.7` = Somewhat similar
516
+ - `<0.6` = Low similarity
517
+
518
+ ---
519
+
520
+ ### `Data.delete(collectionName, entryId)`
521
+
522
+ Deletes an entry.
523
+
524
+ **Usage:**
525
+ ```typescript
526
+ await Data.delete('movies', 'entry_abc123');
527
+ ```
528
+
529
+ ---
530
+
531
+ ## Products API
532
+
533
+ Manage product catalog.
534
+
535
+ ### `Products.get(limit?, page?)`
536
+
537
+ Retrieves products with pagination.
538
+
539
+ **Usage:**
540
+ ```typescript
541
+ const products = await Products.get(20, 1);
542
+ ```
543
+
544
+ **Returns:**
545
+ ```typescript
546
+ {
547
+ success: boolean;
548
+ data: Product[];
549
+ pagination: {
550
+ currentPage: number;
551
+ totalPages: number;
552
+ totalCount: number;
553
+ hasNextPage: boolean;
554
+ // ...
555
+ };
556
+ }
557
+ ```
558
+
559
+ ---
560
+
561
+ ### `Products.create(product)`
562
+
563
+ Creates a new product.
564
+
565
+ **Usage:**
566
+ ```typescript
567
+ const product = await Products.create({
568
+ name: 'Laptop',
569
+ price: 999.99,
570
+ category: 'Electronics',
571
+ sku: 'LAP-001',
572
+ inStock: true
573
+ });
574
+ ```
575
+
576
+ **Returns:**
577
+ ```typescript
578
+ {
579
+ updated: boolean;
580
+ isNew: boolean;
581
+ product: Product;
582
+ }
583
+ ```
584
+
585
+ ---
586
+
587
+ ### `Products.update(data, id)`
588
+
589
+ Updates an existing product.
590
+
591
+ **Usage:**
592
+ ```typescript
593
+ const updated = await Products.update({
594
+ price: 899.99,
595
+ inStock: false
596
+ }, 'product_abc123');
597
+ ```
598
+
599
+ ---
600
+
601
+ ### `Products.delete(id)`
602
+
603
+ Deletes a product.
604
+
605
+ **Usage:**
606
+ ```typescript
607
+ await Products.delete('product_abc123');
608
+ ```
609
+
610
+ ---
611
+
612
+ ### `Products.search(query)`
613
+
614
+ Searches products.
615
+
616
+ **Usage:**
617
+ ```typescript
618
+ const results = await Products.search('laptop');
619
+ ```
620
+
621
+ **Returns:**
622
+ ```typescript
623
+ {
624
+ success: boolean;
625
+ data: Product[];
626
+ }
627
+ ```
628
+
629
+ ---
630
+
631
+ ### `Products.getById(id)`
632
+
633
+ Gets a specific product.
634
+
635
+ **Usage:**
636
+ ```typescript
637
+ const product = await Products.getById('product_abc123');
638
+ ```
639
+
640
+ ---
641
+
642
+ ## Baskets API
643
+
644
+ Manage shopping baskets.
645
+
646
+ ### `Baskets.create(basketData)`
647
+
648
+ Creates a new basket.
649
+
650
+ **Usage:**
651
+ ```typescript
652
+ const basket = await Baskets.create({
653
+ currency: 'USD',
654
+ metadata: {
655
+ source: 'web',
656
+ campaign: 'summer_sale'
657
+ }
658
+ });
659
+ ```
660
+
661
+ ---
662
+
663
+ ### `Baskets.get(status?)`
664
+
665
+ Gets baskets, optionally filtered by status.
666
+
667
+ **Usage:**
668
+ ```typescript
669
+ // All baskets
670
+ const allBaskets = await Baskets.get();
671
+
672
+ // Active baskets only
673
+ const activeBaskets = await Baskets.get(BasketStatus.ACTIVE);
674
+ ```
675
+
676
+ **Basket Statuses:**
677
+ ```typescript
678
+ import { BasketStatus } from 'lua-cli';
679
+
680
+ BasketStatus.ACTIVE // Currently being used
681
+ BasketStatus.CHECKED_OUT // Converted to order
682
+ BasketStatus.ABANDONED // User left without checkout
683
+ BasketStatus.EXPIRED // TTL exceeded
684
+ ```
685
+
686
+ ---
687
+
688
+ ### `Baskets.addItem(basketId, itemData)`
689
+
690
+ Adds an item to a basket.
691
+
692
+ **Usage:**
693
+ ```typescript
694
+ const updated = await Baskets.addItem('basket_abc123', {
695
+ id: 'product_xyz',
696
+ price: 29.99,
697
+ quantity: 2,
698
+ SKU: 'SHIRT-M-BLUE'
699
+ });
700
+ ```
701
+
702
+ ---
703
+
704
+ ### `Baskets.removeItem(basketId, itemId)`
705
+
706
+ Removes an item from a basket.
707
+
708
+ **Usage:**
709
+ ```typescript
710
+ await Baskets.removeItem('basket_abc123', 'item_xyz');
711
+ ```
712
+
713
+ ---
714
+
715
+ ### `Baskets.clear(basketId)`
716
+
717
+ Removes all items from a basket.
718
+
719
+ **Usage:**
720
+ ```typescript
721
+ await Baskets.clear('basket_abc123');
722
+ ```
723
+
724
+ ---
725
+
726
+ ### `Baskets.updateStatus(basketId, status)`
727
+
728
+ Updates basket status.
729
+
730
+ **Usage:**
731
+ ```typescript
732
+ await Baskets.updateStatus('basket_abc123', BasketStatus.ABANDONED);
733
+ ```
734
+
735
+ ---
736
+
737
+ ### `Baskets.updateMetadata(basketId, metadata)`
738
+
739
+ Updates basket metadata.
740
+
741
+ **Usage:**
742
+ ```typescript
743
+ await Baskets.updateMetadata('basket_abc123', {
744
+ notes: 'Gift wrapping requested',
745
+ deliveryDate: '2025-12-25'
746
+ });
747
+ ```
748
+
749
+ ---
750
+
751
+ ### `Baskets.placeOrder(orderData, basketId)`
752
+
753
+ Converts basket to order.
754
+
755
+ **Usage:**
756
+ ```typescript
757
+ const order = await Baskets.placeOrder({
758
+ shippingAddress: {
759
+ street: '123 Main St',
760
+ city: 'New York',
761
+ zip: '10001'
762
+ },
763
+ paymentMethod: 'credit_card'
764
+ }, 'basket_abc123');
765
+ ```
766
+
767
+ ---
768
+
769
+ ### `Baskets.getById(basketId)`
770
+
771
+ Gets a specific basket.
772
+
773
+ **Usage:**
774
+ ```typescript
775
+ const basket = await Baskets.getById('basket_abc123');
776
+ ```
777
+
778
+ ---
779
+
780
+ ## Orders API
781
+
782
+ Manage orders.
783
+
784
+ ### `Orders.create(orderData)`
785
+
786
+ Creates a new order.
787
+
788
+ **Usage:**
789
+ ```typescript
790
+ const order = await Orders.create({
791
+ basketId: 'basket_abc123',
792
+ data: {
793
+ shippingAddress: {...},
794
+ paymentMethod: 'stripe'
795
+ }
796
+ });
797
+ ```
798
+
799
+ ---
800
+
801
+ ### `Orders.updateStatus(status, orderId)`
802
+
803
+ Updates order status.
804
+
805
+ **Usage:**
806
+ ```typescript
807
+ await Orders.updateStatus(OrderStatus.FULFILLED, 'order_abc123');
808
+ ```
809
+
810
+ **Order Statuses:**
811
+ ```typescript
812
+ import { OrderStatus } from 'lua-cli';
813
+
814
+ OrderStatus.PENDING // Created, not confirmed
815
+ OrderStatus.CONFIRMED // Confirmed, being processed
816
+ OrderStatus.FULFILLED // Completed and delivered
817
+ OrderStatus.CANCELLED // Cancelled
818
+ ```
819
+
820
+ ---
821
+
822
+ ### `Orders.updateData(data, orderId)`
823
+
824
+ Updates order data.
825
+
826
+ **Usage:**
827
+ ```typescript
828
+ await Orders.updateData({
829
+ trackingNumber: 'TRACK123',
830
+ estimatedDelivery: '2025-10-10'
831
+ }, 'order_abc123');
832
+ ```
833
+
834
+ ---
835
+
836
+ ### `Orders.get(status?)`
837
+
838
+ Gets orders, optionally filtered by status.
839
+
840
+ **Usage:**
841
+ ```typescript
842
+ // All orders
843
+ const allOrders = await Orders.get();
844
+
845
+ // Pending orders only
846
+ const pending = await Orders.get(OrderStatus.PENDING);
847
+ ```
848
+
849
+ ---
850
+
851
+ ### `Orders.getById(orderId)`
852
+
853
+ Gets a specific order.
854
+
855
+ **Usage:**
856
+ ```typescript
857
+ const order = await Orders.getById('order_abc123');
858
+ ```
859
+
860
+ ---
861
+
862
+ ## Environment Variables
863
+
864
+ ### `env(key: string): string | undefined`
865
+
866
+ Safely access environment variables.
867
+
868
+ **Usage:**
869
+ ```typescript
870
+ import { env } from 'lua-cli';
871
+
872
+ export class MyTool implements LuaTool {
873
+ async execute(input: any) {
874
+ const apiKey = env('EXTERNAL_API_KEY');
875
+ const baseUrl = env('API_BASE_URL') || 'https://default.com';
876
+
877
+ if (!apiKey) {
878
+ throw new Error('EXTERNAL_API_KEY not configured');
879
+ }
880
+
881
+ // Use environment variables...
882
+ }
883
+ }
884
+ ```
885
+
886
+ **Loading Priority:**
887
+ 1. Process environment variables
888
+ 2. `.env` file in project root
889
+ 3. `lua.skill.yaml` under `skill.env`
890
+
891
+ **Configuration:**
892
+
893
+ ```yaml
894
+ # lua.skill.yaml
895
+ skill:
896
+ env:
897
+ EXTERNAL_API_KEY: sk_abc123
898
+ API_BASE_URL: https://api.example.com
899
+ ```
900
+
901
+ Or create `.env` file:
902
+ ```bash
903
+ # .env
904
+ EXTERNAL_API_KEY=sk_abc123
905
+ API_BASE_URL=https://api.example.com
906
+ ```
907
+
908
+ ---
909
+
910
+ ## Complete Examples
911
+
912
+ ### Example 1: Weather Tool
913
+
914
+ ```typescript
915
+ import { LuaTool, env } from 'lua-cli';
916
+ import { z } from 'zod';
917
+
918
+ export default class GetWeatherTool implements LuaTool {
919
+ name = "get_weather";
920
+ description = "Get current weather conditions for any city";
921
+
922
+ inputSchema = z.object({
923
+ city: z.string().describe("City name (e.g., 'London', 'New York')"),
924
+ units: z.enum(['metric', 'imperial']).optional().describe("Temperature units")
925
+ });
926
+
927
+ async execute(input: z.infer<typeof this.inputSchema>) {
928
+ const { city, units = 'metric' } = input;
929
+
930
+ // Call weather API (using free Open-Meteo API)
931
+ const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1`;
932
+ const geoRes = await fetch(geoUrl);
933
+ const geoData = await geoRes.json();
934
+
935
+ if (!geoData.results?.[0]) {
936
+ throw new Error(`City not found: ${city}`);
937
+ }
938
+
939
+ const { latitude, longitude, name } = geoData.results[0];
940
+
941
+ const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true&temperature_unit=${units === 'imperial' ? 'fahrenheit' : 'celsius'}`;
942
+ const weatherRes = await fetch(weatherUrl);
943
+ const weatherData = await weatherRes.json();
944
+
945
+ const current = weatherData.current_weather;
946
+
947
+ return {
948
+ city: name,
949
+ temperature: current.temperature,
950
+ windSpeed: current.windspeed,
951
+ condition: current.weathercode
952
+ };
953
+ }
954
+ }
955
+ ```
956
+
957
+ ---
958
+
959
+ ### Example 2: E-commerce Tool
960
+
961
+ ```typescript
962
+ import { LuaTool, Products, Baskets } from 'lua-cli';
963
+ import { z } from 'zod';
964
+
965
+ export default class AddToCartTool implements LuaTool {
966
+ name = "add_to_cart";
967
+ description = "Add a product to the shopping cart";
968
+
969
+ inputSchema = z.object({
970
+ productId: z.string().describe("Product ID to add"),
971
+ quantity: z.number().min(1).describe("Quantity to add"),
972
+ basketId: z.string().optional().describe("Existing basket ID (creates new if not provided)")
973
+ });
974
+
975
+ async execute(input: z.infer<typeof this.inputSchema>) {
976
+ const { productId, quantity, basketId } = input;
977
+
978
+ // Get product details
979
+ const product = await Products.getById(productId);
980
+
981
+ // Get or create basket
982
+ let basket;
983
+ if (basketId) {
984
+ basket = await Baskets.getById(basketId);
985
+ } else {
986
+ basket = await Baskets.create({
987
+ currency: 'USD',
988
+ metadata: { source: 'chat' }
989
+ });
990
+ }
991
+
992
+ // Add item to basket
993
+ const updated = await Baskets.addItem(basket.id, {
994
+ id: productId,
995
+ price: product.price,
996
+ quantity: quantity,
997
+ SKU: product.sku
998
+ });
999
+
1000
+ return {
1001
+ basketId: updated.id,
1002
+ itemCount: updated.common.itemCount,
1003
+ totalAmount: updated.common.totalAmount,
1004
+ message: `Added ${quantity}x ${product.name} to cart`
1005
+ };
1006
+ }
1007
+ }
1008
+ ```
1009
+
1010
+ ---
1011
+
1012
+ ### Example 3: Custom Data with Search
1013
+
1014
+ ```typescript
1015
+ import { LuaTool, Data } from 'lua-cli';
1016
+ import { z } from 'zod';
1017
+
1018
+ export class CreateMovieTool implements LuaTool {
1019
+ name = "create_movie";
1020
+ description = "Add a new movie to the database";
1021
+
1022
+ inputSchema = z.object({
1023
+ title: z.string(),
1024
+ year: z.number(),
1025
+ director: z.string(),
1026
+ genre: z.string()
1027
+ });
1028
+
1029
+ async execute(input: z.infer<typeof this.inputSchema>) {
1030
+ // Create searchable text
1031
+ const searchText = `${input.title} ${input.year} ${input.director} ${input.genre}`;
1032
+
1033
+ const movie = await Data.create('movies', input, searchText);
1034
+
1035
+ return {
1036
+ id: movie.id,
1037
+ message: `Created movie: ${input.title}`
1038
+ };
1039
+ }
1040
+ }
1041
+
1042
+ export class SearchMoviesTool implements LuaTool {
1043
+ name = "search_movies";
1044
+ description = "Search for movies by title, director, or genre";
1045
+
1046
+ inputSchema = z.object({
1047
+ query: z.string().describe("Search query")
1048
+ });
1049
+
1050
+ async execute(input: z.infer<typeof this.inputSchema>) {
1051
+ const results = await Data.search('movies', input.query, 10, 0.7);
1052
+
1053
+ return {
1054
+ movies: results.data.map(entry => ({
1055
+ id: entry.id,
1056
+ ...entry.data,
1057
+ relevance: entry.score
1058
+ })),
1059
+ count: results.count
1060
+ };
1061
+ }
1062
+ }
1063
+ ```
1064
+
1065
+ ---
1066
+
1067
+ ### Example 4: Multi-Step Tool
1068
+
1069
+ ```typescript
1070
+ import { LuaTool, Products, Baskets, Orders } from 'lua-cli';
1071
+ import { z } from 'zod';
1072
+
1073
+ export default class QuickCheckoutTool implements LuaTool {
1074
+ name = "quick_checkout";
1075
+ description = "Search for product, add to cart, and create order in one step";
1076
+
1077
+ inputSchema = z.object({
1078
+ productName: z.string(),
1079
+ quantity: z.number().default(1),
1080
+ shippingAddress: z.object({
1081
+ street: z.string(),
1082
+ city: z.string(),
1083
+ zip: z.string()
1084
+ })
1085
+ });
1086
+
1087
+ async execute(input: z.infer<typeof this.inputSchema>) {
1088
+ // Step 1: Search for product
1089
+ const searchResults = await Products.search(input.productName);
1090
+ if (searchResults.data.length === 0) {
1091
+ throw new Error(`Product not found: ${input.productName}`);
1092
+ }
1093
+
1094
+ const product = searchResults.data[0];
1095
+
1096
+ // Step 2: Create basket
1097
+ const basket = await Baskets.create({ currency: 'USD' });
1098
+
1099
+ // Step 3: Add product to basket
1100
+ await Baskets.addItem(basket.id, {
1101
+ id: product.id,
1102
+ price: product.price,
1103
+ quantity: input.quantity
1104
+ });
1105
+
1106
+ // Step 4: Create order
1107
+ const order = await Baskets.placeOrder({
1108
+ shippingAddress: input.shippingAddress,
1109
+ paymentMethod: 'stripe'
1110
+ }, basket.id);
1111
+
1112
+ return {
1113
+ orderId: order.id,
1114
+ product: product.name,
1115
+ quantity: input.quantity,
1116
+ total: basket.common.totalAmount,
1117
+ message: 'Order created successfully'
1118
+ };
1119
+ }
1120
+ }
1121
+ ```
1122
+
1123
+ ---
1124
+
1125
+ ### Example 5: Using Environment Variables
1126
+
1127
+ ```typescript
1128
+ import { LuaTool, env } from 'lua-cli';
1129
+ import { z } from 'zod';
1130
+
1131
+ export default class SendEmailTool implements LuaTool {
1132
+ name = "send_email";
1133
+ description = "Send an email via external service";
1134
+
1135
+ inputSchema = z.object({
1136
+ to: z.string().email(),
1137
+ subject: z.string(),
1138
+ body: z.string()
1139
+ });
1140
+
1141
+ async execute(input: z.infer<typeof this.inputSchema>) {
1142
+ // Get API credentials from environment
1143
+ const apiKey = env('SENDGRID_API_KEY');
1144
+ const fromEmail = env('FROM_EMAIL');
1145
+
1146
+ if (!apiKey) {
1147
+ throw new Error('SENDGRID_API_KEY not configured');
1148
+ }
1149
+
1150
+ // Call external API
1151
+ const response = await fetch('https://api.sendgrid.com/v3/mail/send', {
1152
+ method: 'POST',
1153
+ headers: {
1154
+ 'Authorization': `Bearer ${apiKey}`,
1155
+ 'Content-Type': 'application/json'
1156
+ },
1157
+ body: JSON.stringify({
1158
+ personalizations: [{
1159
+ to: [{ email: input.to }]
1160
+ }],
1161
+ from: { email: fromEmail || 'noreply@example.com' },
1162
+ subject: input.subject,
1163
+ content: [{
1164
+ type: 'text/plain',
1165
+ value: input.body
1166
+ }]
1167
+ })
1168
+ });
1169
+
1170
+ if (!response.ok) {
1171
+ throw new Error(`Email sending failed: ${response.statusText}`);
1172
+ }
1173
+
1174
+ return {
1175
+ success: true,
1176
+ message: `Email sent to ${input.to}`
1177
+ };
1178
+ }
1179
+ }
1180
+ ```
1181
+
1182
+ ---
1183
+
1184
+ ## Type Definitions
1185
+
1186
+ ### Importing Types
1187
+
1188
+ ```typescript
1189
+ import {
1190
+ LuaSkill,
1191
+ LuaTool,
1192
+ BasketStatus,
1193
+ OrderStatus,
1194
+ env
1195
+ } from 'lua-cli';
1196
+ ```
1197
+
1198
+ ### Full Type Signature
1199
+
1200
+ ```typescript
1201
+ interface LuaTool<TInput extends ZodType = ZodType> {
1202
+ name: string;
1203
+ description: string;
1204
+ inputSchema: TInput;
1205
+ execute: (input: z.infer<TInput>) => Promise<any>;
1206
+ }
1207
+ ```
1208
+
1209
+ ---
1210
+
1211
+ ## Best Practices
1212
+
1213
+ ### Tool Design
1214
+
1215
+ **✅ Do:**
1216
+ - Use clear, descriptive names
1217
+ - Write detailed descriptions
1218
+ - Validate all inputs with Zod
1219
+ - Return structured data
1220
+ - Handle errors gracefully
1221
+ - Use environment variables for secrets
1222
+
1223
+ **❌ Don't:**
1224
+ - Use spaces in tool names
1225
+ - Hardcode API keys
1226
+ - Return unstructured strings
1227
+ - Ignore input validation
1228
+ - Swallow errors silently
1229
+
1230
+ ---
1231
+
1232
+ ### Error Handling
1233
+
1234
+ ```typescript
1235
+ async execute(input: any) {
1236
+ try {
1237
+ // Validate business logic
1238
+ if (input.amount <= 0) {
1239
+ throw new Error("Amount must be positive");
1240
+ }
1241
+
1242
+ // Call external service
1243
+ const result = await externalApi.call(input);
1244
+
1245
+ // Validate response
1246
+ if (!result.success) {
1247
+ throw new Error(`API error: ${result.error}`);
1248
+ }
1249
+
1250
+ return result.data;
1251
+
1252
+ } catch (error) {
1253
+ // Add context to errors
1254
+ throw new Error(`Failed to process request: ${error.message}`);
1255
+ }
1256
+ }
1257
+ ```
1258
+
1259
+ ---
1260
+
1261
+ ### Schema Design
1262
+
1263
+ **Simple and Clear:**
1264
+ ```typescript
1265
+ inputSchema = z.object({
1266
+ email: z.string().email().describe("User's email address"),
1267
+ amount: z.number().positive().describe("Amount in USD"),
1268
+ sendReceipt: z.boolean().default(true).describe("Send email receipt")
1269
+ });
1270
+ ```
1271
+
1272
+ **With Validation:**
1273
+ ```typescript
1274
+ inputSchema = z.object({
1275
+ age: z.number().min(0).max(120),
1276
+ email: z.string().email(),
1277
+ password: z.string().min(8),
1278
+ phone: z.string().regex(/^\+?[1-9]\d{1,14}$/),
1279
+ url: z.string().url()
1280
+ });
1281
+ ```
1282
+
1283
+ ---
1284
+
1285
+ ## Testing Your Skills
1286
+
1287
+ ### Local Testing
1288
+
1289
+ ```bash
1290
+ # Interactive testing
1291
+ lua test
1292
+
1293
+ # Select tool, enter inputs, see results
1294
+ ```
1295
+
1296
+ ### Development Mode
1297
+
1298
+ ```bash
1299
+ # Start dev mode
1300
+ lua dev
1301
+
1302
+ # Chat interface opens at http://localhost:3000
1303
+ # Edit files - auto-reloads
1304
+ # Test conversational interaction
1305
+ ```
1306
+
1307
+ ### Production Testing
1308
+
1309
+ ```bash
1310
+ # Push to server
1311
+ lua push
1312
+
1313
+ # Test in sandbox before deploying
1314
+ lua dev
1315
+
1316
+ # Deploy when ready
1317
+ lua deploy
1318
+ ```
1319
+
1320
+ ---
1321
+
1322
+ ## TypeScript Support
1323
+
1324
+ All Lua APIs are fully typed:
1325
+
1326
+ ```typescript
1327
+ import { User, Products, Data } from 'lua-cli';
1328
+
1329
+ // Autocomplete and type checking work!
1330
+ const user = await User.get(); // user is typed
1331
+ const products = await Products.get(); // products is typed
1332
+ const data = await Data.get('movies'); // data is typed
1333
+ ```
1334
+
1335
+ ---
1336
+
1337
+ ## Common Patterns
1338
+
1339
+ ### Pattern: Conditional Tool Execution
1340
+
1341
+ ```typescript
1342
+ async execute(input: any) {
1343
+ if (input.query) {
1344
+ // Search path
1345
+ return await Products.search(input.query);
1346
+ } else {
1347
+ // List all path
1348
+ return await Products.get(20, 1);
1349
+ }
1350
+ }
1351
+ ```
1352
+
1353
+ ### Pattern: Data Transformation
1354
+
1355
+ ```typescript
1356
+ async execute(input: any) {
1357
+ const products = await Products.get(100);
1358
+
1359
+ // Transform for AI consumption
1360
+ return products.data.map(p => ({
1361
+ name: p.name,
1362
+ price: `$${p.price}`,
1363
+ available: p.inStock ? 'Yes' : 'No'
1364
+ }));
1365
+ }
1366
+ ```
1367
+
1368
+ ### Pattern: Error Recovery
1369
+
1370
+ ```typescript
1371
+ async execute(input: any) {
1372
+ try {
1373
+ return await externalApi.call(input);
1374
+ } catch (error) {
1375
+ // Fallback behavior
1376
+ console.warn('External API failed, using fallback');
1377
+ return await fallbackService.call(input);
1378
+ }
1379
+ }
1380
+ ```
1381
+
1382
+ ---
1383
+
1384
+ ## Limits and Quotas
1385
+
1386
+ - **Vector Search**: `scoreThreshold` 0-1 (0.7 recommended minimum)
1387
+ - **Pagination**: Default 10 items, max 100 per page
1388
+ - **Tool Names**: 1-50 characters, alphanumeric + `-` `_` only
1389
+ - **Data Storage**: No hard limits on custom data collections
1390
+
1391
+ ---
1392
+
1393
+ ## Additional Resources
1394
+
1395
+ - **CLI Commands**: See `CLI_REFERENCE.md`
1396
+ - **Template Guide**: See `TEMPLATE_GUIDE.md`
1397
+ - **Development**: See `DEVELOPER_GUIDE.md`
1398
+ - **Examples**: Check `template/src/tools/` directory
1399
+ - **Platform Docs**: https://docs.lua.ai
1400
+
1401
+ ---
1402
+
1403
+ ## Support
1404
+
1405
+ - **Issues**: https://github.com/lua-ai/lua-cli/issues
1406
+ - **Docs**: https://docs.lua.ai
1407
+ - **Email**: support@lua.ai
1408
+