lua-cli 3.6.7 → 3.7.2
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/dist/api/agent.api.service.d.ts +2 -2
- package/dist/api/agent.api.service.js +2 -2
- package/dist/api/ai.api.service.d.ts +20 -0
- package/dist/api/ai.api.service.d.ts.map +1 -0
- package/dist/api/ai.api.service.js +38 -0
- package/dist/api/ai.api.service.js.map +1 -0
- package/dist/api/chat.api.service.d.ts +2 -1
- package/dist/api/chat.api.service.d.ts.map +1 -1
- package/dist/api/chat.api.service.js +9 -4
- package/dist/api/chat.api.service.js.map +1 -1
- package/dist/api/lazy-instances.d.ts +4 -4
- package/dist/api/lazy-instances.d.ts.map +1 -1
- package/dist/api/lazy-instances.js +9 -9
- package/dist/api/lazy-instances.js.map +1 -1
- package/dist/api-exports.d.ts +28 -30
- package/dist/api-exports.d.ts.map +1 -1
- package/dist/api-exports.js +6 -59
- package/dist/api-exports.js.map +1 -1
- package/dist/cli/command-definitions.d.ts.map +1 -1
- package/dist/cli/command-definitions.js +19 -7
- package/dist/cli/command-definitions.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +62 -2
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/chatClear.d.ts +6 -2
- package/dist/commands/chatClear.d.ts.map +1 -1
- package/dist/commands/chatClear.js +23 -16
- package/dist/commands/chatClear.js.map +1 -1
- package/dist/commands/features.d.ts +1 -1
- package/dist/commands/features.js +2 -2
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/interfaces/agent.d.ts +9 -2
- package/dist/interfaces/agent.d.ts.map +1 -1
- package/dist/interfaces/chat.d.ts +4 -0
- package/dist/interfaces/chat.d.ts.map +1 -1
- package/dist/primitives/agent.handler.d.ts +1 -1
- package/dist/primitives/agent.handler.d.ts.map +1 -1
- package/dist/primitives/agent.handler.js +25 -20
- package/dist/primitives/agent.handler.js.map +1 -1
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +11 -3
- package/dist/services/auth.js.map +1 -1
- package/dist/utils/init-agent.d.ts +1 -1
- package/dist/utils/init-agent.d.ts.map +1 -1
- package/dist/utils/init-agent.js +7 -2
- package/dist/utils/init-agent.js.map +1 -1
- package/dist/utils/keytar-loader.d.ts +20 -0
- package/dist/utils/keytar-loader.d.ts.map +1 -0
- package/dist/utils/keytar-loader.js +28 -0
- package/dist/utils/keytar-loader.js.map +1 -0
- package/dist/utils/sandbox-storage.d.ts.map +1 -1
- package/dist/utils/sandbox-storage.js +19 -1
- package/dist/utils/sandbox-storage.js.map +1 -1
- package/dist/utils/sandbox.d.ts.map +1 -1
- package/dist/utils/sandbox.js +6 -17
- package/dist/utils/sandbox.js.map +1 -1
- package/docs/README.md +2 -2
- package/docs/api/AI.md +157 -640
- package/package.json +3 -1
- package/template/package.json +1 -1
package/docs/api/AI.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AI API
|
|
2
2
|
|
|
3
|
-
The AI API
|
|
3
|
+
The AI API provides isolated text generation from within tools, aligned with [Vercel AI SDK `generateText`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text) semantics. Requests are proxied through the Lua API to a dedicated generation endpoint — they do **not** go through the agent chat pipeline.
|
|
4
4
|
|
|
5
5
|
## Import
|
|
6
6
|
|
|
@@ -19,59 +19,122 @@ The AI API enables:
|
|
|
19
19
|
- Create AI-powered features in your tools
|
|
20
20
|
- Use different personas for different tasks
|
|
21
21
|
- Multi-modal inputs (text, images, files)
|
|
22
|
+
- Access rich generation metadata (usage, finish reason, sources, reasoning)
|
|
22
23
|
|
|
23
24
|
## Methods
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
`AI.generate` has two overloads — a simplified form that returns plain text, and a full-options form that returns a rich result object.
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
### Simplified: `AI.generate(prompt, content?)`
|
|
29
|
+
|
|
30
|
+
Quick text generation. Returns plain text as a string.
|
|
28
31
|
|
|
29
32
|
**Parameters:**
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `agentId` (string, optional) - Agent ID to use (defaults to 'luaAgent')
|
|
33
|
+
- `prompt` (string) — When called with one argument this is the user prompt. When called with two arguments it becomes the system instruction.
|
|
34
|
+
- `content` (UserContent, optional) — User message content. Accepts a string or an array of multimodal parts (`TextPart`, `ImagePart`, `FilePart`) from the AI SDK.
|
|
33
35
|
|
|
34
|
-
**Returns:** `Promise<string>`
|
|
36
|
+
**Returns:** `Promise<string>`
|
|
35
37
|
|
|
36
|
-
**Example:**
|
|
37
38
|
```typescript
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
// Single argument — prompt is the user message
|
|
40
|
+
const text = await AI.generate('Summarize the latest AI news.');
|
|
41
|
+
|
|
42
|
+
// Two arguments — prompt is the system instruction, content is user message
|
|
43
|
+
const text2 = await AI.generate(
|
|
44
|
+
'You are a helpful assistant.',
|
|
40
45
|
[{ type: 'text', text: 'What products do you recommend?' }]
|
|
41
46
|
);
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
// Multi-modal content
|
|
49
|
+
const analysis = await AI.generate(
|
|
50
|
+
'You are an image analysis expert.',
|
|
51
|
+
[
|
|
52
|
+
{ type: 'text', text: 'What do you see in this image?' },
|
|
53
|
+
{ type: 'image', url: 'https://example.com/photo.jpg' }
|
|
54
|
+
]
|
|
55
|
+
);
|
|
45
56
|
```
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
### Full options: `AI.generate(options)`
|
|
59
|
+
|
|
60
|
+
Full control over generation parameters. Returns a rich result object with metadata.
|
|
61
|
+
|
|
62
|
+
**Parameters (AiGenerateInput):**
|
|
63
|
+
- `model?` (string) — Model to use, e.g. `'google/gemini-2.0-flash'`, `'openai/gpt-4o'`, `'anthropic/claude-sonnet-4-20250514'`. Defaults to the agent's configured model.
|
|
64
|
+
- `system?` (string) — System instruction.
|
|
65
|
+
- `prompt?` (string) — User prompt (simple text).
|
|
66
|
+
- `messages?` (array) — Conversation messages (AI SDK `ModelMessage[]`).
|
|
67
|
+
- `temperature?` (number) — Sampling temperature (0–2).
|
|
68
|
+
- `maxOutputTokens?` (number) — Maximum tokens to generate.
|
|
48
69
|
|
|
49
|
-
|
|
70
|
+
**Returns:** `Promise<AiGenerateOutput>`
|
|
50
71
|
|
|
51
72
|
```typescript
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
const result = await AI.generate({
|
|
74
|
+
model: 'google/gemini-2.0-flash',
|
|
75
|
+
system: 'You are concise.',
|
|
76
|
+
prompt: 'What is the weather in London?',
|
|
77
|
+
temperature: 0.7,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
console.log(result.text); // Generated text
|
|
81
|
+
console.log(result.finishReason); // 'stop', 'length', etc.
|
|
82
|
+
console.log(result.usage); // { promptTokens, completionTokens, totalTokens }
|
|
83
|
+
console.log(result.sources); // Google Search grounding URLs (when available)
|
|
56
84
|
```
|
|
57
85
|
|
|
58
|
-
###
|
|
86
|
+
### AiGenerateOutput
|
|
87
|
+
|
|
88
|
+
The full-options response mirrors AI SDK `GenerateTextResult` (serializable fields only, excluding `files` and `steps`):
|
|
89
|
+
|
|
90
|
+
| Field | Type | Description |
|
|
91
|
+
|-------|------|-------------|
|
|
92
|
+
| `text` | `string` | Generated text |
|
|
93
|
+
| `finishReason` | `FinishReason` | `'stop'`, `'length'`, `'content-filter'`, `'tool-calls'`, `'error'`, `'other'`, `'unknown'` |
|
|
94
|
+
| `usage` | `LanguageModelUsage` | `{ promptTokens, completionTokens, totalTokens }` |
|
|
95
|
+
| `reasoning?` | `ReasoningOutput[]` | Model reasoning steps (e.g. Gemini thinking) |
|
|
96
|
+
| `reasoningText?` | `string` | Concatenated reasoning text |
|
|
97
|
+
| `sources?` | `AiGenerateSource[]` | URL sources from Google Search grounding |
|
|
98
|
+
| `toolCalls?` | `AiGenerateToolCall[]` | Tool calls made during generation |
|
|
99
|
+
| `toolResults?` | `AiGenerateToolResult[]` | Tool results from generation |
|
|
100
|
+
| `warnings?` | `CallWarning[]` | Provider warnings (e.g. unsupported settings) |
|
|
101
|
+
|
|
102
|
+
## Supported Providers
|
|
103
|
+
|
|
104
|
+
| Provider | Model prefix | Example |
|
|
105
|
+
|----------|-------------|---------|
|
|
106
|
+
| Google (Vertex AI) | `google/` | `google/gemini-2.0-flash` |
|
|
107
|
+
| OpenAI | `openai/` | `openai/gpt-4o` |
|
|
108
|
+
| Anthropic | `anthropic/` | `anthropic/claude-sonnet-4-20250514` |
|
|
109
|
+
|
|
110
|
+
If the requested provider's API key is not configured, the request falls back to the default Vertex AI model.
|
|
111
|
+
|
|
112
|
+
Google models automatically get Google Search grounding — search result URLs appear in the `sources` field of the full-options response.
|
|
113
|
+
|
|
114
|
+
## Content Types
|
|
115
|
+
|
|
116
|
+
### Text
|
|
59
117
|
|
|
60
118
|
```typescript
|
|
61
|
-
{
|
|
62
|
-
type: 'image',
|
|
63
|
-
url: string
|
|
64
|
-
}
|
|
119
|
+
[{ type: 'text', text: 'Your message here' }]
|
|
65
120
|
```
|
|
66
121
|
|
|
67
|
-
###
|
|
122
|
+
### Image
|
|
68
123
|
|
|
69
124
|
```typescript
|
|
70
|
-
|
|
71
|
-
type: '
|
|
72
|
-
url:
|
|
73
|
-
|
|
74
|
-
|
|
125
|
+
[
|
|
126
|
+
{ type: 'text', text: 'What do you see in this image?' },
|
|
127
|
+
{ type: 'image', url: 'https://example.com/photo.jpg' }
|
|
128
|
+
]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### File
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
[
|
|
135
|
+
{ type: 'text', text: 'Summarize this document' },
|
|
136
|
+
{ type: 'file', url: 'https://example.com/doc.pdf', mimeType: 'application/pdf' }
|
|
137
|
+
]
|
|
75
138
|
```
|
|
76
139
|
|
|
77
140
|
## Complete Examples
|
|
@@ -92,34 +155,48 @@ export default class GenerateDescriptionTool implements LuaTool {
|
|
|
92
155
|
});
|
|
93
156
|
|
|
94
157
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
95
|
-
// Get product details
|
|
96
158
|
const product = await Products.getById(input.productId);
|
|
97
|
-
|
|
98
159
|
if (!product) {
|
|
99
160
|
return { success: false, error: 'Product not found' };
|
|
100
161
|
}
|
|
101
162
|
|
|
102
|
-
// Generate description with AI
|
|
103
163
|
const style = input.style || 'professional';
|
|
104
|
-
const context = `You are a ${style} copywriter for an e-commerce store.
|
|
105
|
-
Create an engaging product description that highlights benefits and features.
|
|
106
|
-
Keep it concise but compelling (2-3 sentences).`;
|
|
107
|
-
|
|
108
164
|
const description = await AI.generate(
|
|
109
|
-
|
|
110
|
-
[{
|
|
111
|
-
type: 'text',
|
|
112
|
-
text: `Write a product description for: ${product.name}, Price: $${product.price}`
|
|
113
|
-
}]
|
|
165
|
+
`You are a ${style} copywriter. Create a 2-3 sentence product description.`,
|
|
166
|
+
[{ type: 'text', text: `Product: ${product.name}, Price: $${product.price}` }]
|
|
114
167
|
);
|
|
115
168
|
|
|
116
|
-
// Update product with new description
|
|
117
169
|
await product.update({ description });
|
|
118
|
-
|
|
170
|
+
return { success: true, productId: input.productId, description };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Weather Search with Google Grounding
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { LuaTool, AI } from 'lua-cli/skill';
|
|
179
|
+
import { z } from 'zod';
|
|
180
|
+
|
|
181
|
+
export default class WeatherSearchTool implements LuaTool {
|
|
182
|
+
name = 'search_weather';
|
|
183
|
+
description = 'Search for current weather using AI with Google Search grounding';
|
|
184
|
+
|
|
185
|
+
inputSchema = z.object({
|
|
186
|
+
location: z.string().describe('City or location to search weather for')
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
190
|
+
const result = await AI.generate({
|
|
191
|
+
model: 'google/gemini-2.0-flash',
|
|
192
|
+
system: 'You report current weather conditions concisely.',
|
|
193
|
+
prompt: `What is the current weather in ${input.location}?`,
|
|
194
|
+
});
|
|
195
|
+
|
|
119
196
|
return {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
197
|
+
weather: result.text,
|
|
198
|
+
sources: result.sources?.map(s => ({ title: s.title, url: s.url })) ?? [],
|
|
199
|
+
usage: result.usage,
|
|
123
200
|
};
|
|
124
201
|
}
|
|
125
202
|
}
|
|
@@ -141,31 +218,15 @@ export default class AnalyzeImageTool implements LuaTool {
|
|
|
141
218
|
});
|
|
142
219
|
|
|
143
220
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const messages = [
|
|
152
|
-
{
|
|
153
|
-
type: 'text' as const,
|
|
154
|
-
text: input.question || 'Describe this image in detail'
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
type: 'image' as const,
|
|
158
|
-
url: input.imageUrl
|
|
159
|
-
}
|
|
160
|
-
];
|
|
161
|
-
|
|
162
|
-
const analysis = await AI.generate(context, messages);
|
|
221
|
+
const analysis = await AI.generate(
|
|
222
|
+
'You are an image analysis expert. Describe what you see in detail.',
|
|
223
|
+
[
|
|
224
|
+
{ type: 'text', text: input.question || 'Describe this image in detail' },
|
|
225
|
+
{ type: 'image', url: input.imageUrl }
|
|
226
|
+
]
|
|
227
|
+
);
|
|
163
228
|
|
|
164
|
-
return {
|
|
165
|
-
success: true,
|
|
166
|
-
imageUrl: input.imageUrl,
|
|
167
|
-
analysis
|
|
168
|
-
};
|
|
229
|
+
return { success: true, imageUrl: input.imageUrl, analysis };
|
|
169
230
|
}
|
|
170
231
|
}
|
|
171
232
|
```
|
|
@@ -186,147 +247,19 @@ export default class SummarizeTool implements LuaTool {
|
|
|
186
247
|
});
|
|
187
248
|
|
|
188
249
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
189
|
-
const
|
|
250
|
+
const instructions: Record<string, string> = {
|
|
190
251
|
brief: 'in 1-2 sentences',
|
|
191
252
|
medium: 'in 1 paragraph',
|
|
192
253
|
detailed: 'in 2-3 paragraphs with key points'
|
|
193
254
|
};
|
|
194
|
-
|
|
195
255
|
const length = input.maxLength || 'medium';
|
|
196
256
|
|
|
197
|
-
const context = `You are a professional content summarizer.
|
|
198
|
-
Create a clear, accurate summary ${lengthInstructions[length]}.
|
|
199
|
-
Focus on main ideas and key takeaways.`;
|
|
200
|
-
|
|
201
257
|
const summary = await AI.generate(
|
|
202
|
-
|
|
203
|
-
[{
|
|
204
|
-
type: 'text',
|
|
205
|
-
text: `Summarize this content:\n\n${input.content}`
|
|
206
|
-
}]
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
success: true,
|
|
211
|
-
originalLength: input.content.length,
|
|
212
|
-
summary,
|
|
213
|
-
summaryLength: summary.length
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Smart Recommendation Engine
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
import { LuaTool, AI, User, Products } from 'lua-cli/skill';
|
|
223
|
-
import { z } from 'zod';
|
|
224
|
-
|
|
225
|
-
export default class RecommendProductsTool implements LuaTool {
|
|
226
|
-
name = 'get_ai_recommendations';
|
|
227
|
-
description = 'Get AI-powered product recommendations based on user preferences';
|
|
228
|
-
|
|
229
|
-
inputSchema = z.object({
|
|
230
|
-
userQuery: z.string().optional()
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
234
|
-
// Get user data and product catalog
|
|
235
|
-
const user = await User.get();
|
|
236
|
-
const products = await Products.get(1, 50);
|
|
237
|
-
|
|
238
|
-
// Build context with product data
|
|
239
|
-
const productList = products.map(p =>
|
|
240
|
-
`- ${p.name}: $${p.price} (${p.category})`
|
|
241
|
-
).join('\n');
|
|
242
|
-
|
|
243
|
-
const context = `You are a personal shopping assistant.
|
|
244
|
-
|
|
245
|
-
Available products:
|
|
246
|
-
${productList}
|
|
247
|
-
|
|
248
|
-
User preferences: ${JSON.stringify(user.data.preferences || {})}
|
|
249
|
-
|
|
250
|
-
Task: Recommend 3-5 products that best match the user's needs.
|
|
251
|
-
Format: Return product names with brief explanations.`;
|
|
252
|
-
|
|
253
|
-
const query = input.userQuery || 'What products would you recommend for me?';
|
|
254
|
-
|
|
255
|
-
const recommendations = await AI.generate(
|
|
256
|
-
context,
|
|
257
|
-
[{ type: 'text', text: query }]
|
|
258
|
+
`You are a professional content summarizer. Create a clear summary ${instructions[length]}.`,
|
|
259
|
+
[{ type: 'text', text: `Summarize:\n\n${input.content}` }]
|
|
258
260
|
);
|
|
259
261
|
|
|
260
|
-
return {
|
|
261
|
-
success: true,
|
|
262
|
-
recommendations,
|
|
263
|
-
basedOn: {
|
|
264
|
-
userPreferences: user.data.preferences,
|
|
265
|
-
availableProducts: products.length,
|
|
266
|
-
query
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Content Moderator
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
import { LuaTool, AI } from 'lua-cli/skill';
|
|
277
|
-
import { z } from 'zod';
|
|
278
|
-
|
|
279
|
-
export default class ModerateContentTool implements LuaTool {
|
|
280
|
-
name = 'moderate_content';
|
|
281
|
-
description = 'Check if content is appropriate and safe';
|
|
282
|
-
|
|
283
|
-
inputSchema = z.object({
|
|
284
|
-
content: z.string()
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
288
|
-
const context = `You are a content moderation expert.
|
|
289
|
-
|
|
290
|
-
Analyze the following content for:
|
|
291
|
-
- Inappropriate language
|
|
292
|
-
- Harmful content
|
|
293
|
-
- Spam or advertising
|
|
294
|
-
- Personal information exposure
|
|
295
|
-
|
|
296
|
-
Respond with JSON in this exact format:
|
|
297
|
-
{
|
|
298
|
-
"safe": true/false,
|
|
299
|
-
"reason": "explanation",
|
|
300
|
-
"category": "appropriate/profanity/spam/harmful/pii",
|
|
301
|
-
"confidence": 0.95
|
|
302
|
-
}`;
|
|
303
|
-
|
|
304
|
-
const analysis = await AI.generate(
|
|
305
|
-
context,
|
|
306
|
-
[{
|
|
307
|
-
type: 'text',
|
|
308
|
-
text: `Analyze this content:\n\n"${input.content}"`
|
|
309
|
-
}]
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
try {
|
|
313
|
-
const result = JSON.parse(analysis);
|
|
314
|
-
return {
|
|
315
|
-
success: true,
|
|
316
|
-
...result,
|
|
317
|
-
originalContent: input.content
|
|
318
|
-
};
|
|
319
|
-
} catch {
|
|
320
|
-
// If AI didn't return valid JSON, parse manually
|
|
321
|
-
const safe = !analysis.toLowerCase().includes('inappropriate');
|
|
322
|
-
return {
|
|
323
|
-
success: true,
|
|
324
|
-
safe,
|
|
325
|
-
reason: analysis,
|
|
326
|
-
category: 'unknown',
|
|
327
|
-
confidence: 0.5
|
|
328
|
-
};
|
|
329
|
-
}
|
|
262
|
+
return { success: true, summary, originalLength: input.content.length };
|
|
330
263
|
}
|
|
331
264
|
}
|
|
332
265
|
```
|
|
@@ -348,83 +281,23 @@ export default class TranslateTool implements LuaTool {
|
|
|
348
281
|
});
|
|
349
282
|
|
|
350
283
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
351
|
-
const sourceLang = input.sourceLanguage || 'auto-detect';
|
|
352
|
-
|
|
353
|
-
const context = `You are a professional translator.
|
|
354
|
-
Translate the text accurately while preserving:
|
|
355
|
-
- Tone and style
|
|
356
|
-
- Cultural context
|
|
357
|
-
- Idiomatic expressions (adapt appropriately)
|
|
358
|
-
|
|
359
|
-
Source language: ${sourceLang}
|
|
360
|
-
Target language: ${input.targetLanguage}
|
|
361
|
-
|
|
362
|
-
Return ONLY the translated text, nothing else.`;
|
|
363
|
-
|
|
364
284
|
const translation = await AI.generate(
|
|
365
|
-
|
|
366
|
-
[{
|
|
367
|
-
type: 'text',
|
|
368
|
-
text: input.text
|
|
369
|
-
}]
|
|
285
|
+
`You are a professional translator. Translate accurately to ${input.targetLanguage}. Return ONLY the translated text.`,
|
|
286
|
+
[{ type: 'text', text: input.text }]
|
|
370
287
|
);
|
|
371
288
|
|
|
372
289
|
return {
|
|
373
290
|
success: true,
|
|
374
291
|
original: input.text,
|
|
375
292
|
translation,
|
|
376
|
-
from:
|
|
293
|
+
from: input.sourceLanguage || 'auto-detect',
|
|
377
294
|
to: input.targetLanguage
|
|
378
295
|
};
|
|
379
296
|
}
|
|
380
297
|
}
|
|
381
298
|
```
|
|
382
299
|
|
|
383
|
-
###
|
|
384
|
-
|
|
385
|
-
```typescript
|
|
386
|
-
import { LuaTool, AI } from 'lua-cli/skill';
|
|
387
|
-
import { z } from 'zod';
|
|
388
|
-
|
|
389
|
-
export default class DocumentQATool implements LuaTool {
|
|
390
|
-
name = 'ask_about_document';
|
|
391
|
-
description = 'Ask questions about a document using AI';
|
|
392
|
-
|
|
393
|
-
inputSchema = z.object({
|
|
394
|
-
documentUrl: z.string().url(),
|
|
395
|
-
question: z.string()
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
399
|
-
const context = `You are a document analysis assistant.
|
|
400
|
-
|
|
401
|
-
Read the document carefully and answer the user's question based on the content.
|
|
402
|
-
|
|
403
|
-
Guidelines:
|
|
404
|
-
- Only use information from the document
|
|
405
|
-
- If the answer isn't in the document, say so
|
|
406
|
-
- Cite specific parts when possible
|
|
407
|
-
- Be accurate and precise`;
|
|
408
|
-
|
|
409
|
-
const answer = await AI.generate(
|
|
410
|
-
context,
|
|
411
|
-
[
|
|
412
|
-
{ type: 'file', url: input.documentUrl },
|
|
413
|
-
{ type: 'text', text: input.question }
|
|
414
|
-
]
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
return {
|
|
418
|
-
success: true,
|
|
419
|
-
question: input.question,
|
|
420
|
-
answer,
|
|
421
|
-
documentUrl: input.documentUrl
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Sentiment Analysis
|
|
300
|
+
### Structured JSON Output
|
|
428
301
|
|
|
429
302
|
```typescript
|
|
430
303
|
import { LuaTool, AI } from 'lua-cli/skill';
|
|
@@ -434,404 +307,54 @@ export default class SentimentAnalysisTool implements LuaTool {
|
|
|
434
307
|
name = 'analyze_sentiment';
|
|
435
308
|
description = 'Analyze the sentiment of text';
|
|
436
309
|
|
|
437
|
-
inputSchema = z.object({
|
|
438
|
-
text: z.string()
|
|
439
|
-
});
|
|
310
|
+
inputSchema = z.object({ text: z.string() });
|
|
440
311
|
|
|
441
312
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
442
|
-
const context = `You are a sentiment analysis expert.
|
|
443
|
-
|
|
444
|
-
Analyze the sentiment of the text and respond with JSON:
|
|
445
|
-
{
|
|
446
|
-
"sentiment": "positive|negative|neutral",
|
|
447
|
-
"score": 0.0 to 1.0,
|
|
448
|
-
"emotions": ["happy", "excited", "satisfied"],
|
|
449
|
-
"summary": "brief explanation"
|
|
450
|
-
}`;
|
|
451
|
-
|
|
452
313
|
const analysis = await AI.generate(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
text: `Analyze the sentiment:\n\n"${input.text}"`
|
|
457
|
-
}]
|
|
314
|
+
`You are a sentiment analysis expert. Respond with JSON only:
|
|
315
|
+
{ "sentiment": "positive|negative|neutral", "score": 0.0-1.0, "summary": "brief explanation" }`,
|
|
316
|
+
[{ type: 'text', text: `Analyze:\n\n"${input.text}"` }]
|
|
458
317
|
);
|
|
459
318
|
|
|
460
319
|
try {
|
|
461
|
-
|
|
462
|
-
return {
|
|
463
|
-
success: true,
|
|
464
|
-
...result,
|
|
465
|
-
originalText: input.text
|
|
466
|
-
};
|
|
320
|
+
return { success: true, ...JSON.parse(analysis), originalText: input.text };
|
|
467
321
|
} catch {
|
|
468
|
-
return {
|
|
469
|
-
success: false,
|
|
470
|
-
error: 'Failed to parse AI response',
|
|
471
|
-
rawResponse: analysis
|
|
472
|
-
};
|
|
322
|
+
return { success: false, error: 'Failed to parse', rawResponse: analysis };
|
|
473
323
|
}
|
|
474
324
|
}
|
|
475
325
|
}
|
|
476
326
|
```
|
|
477
327
|
|
|
478
|
-
### Creative Writing Assistant
|
|
479
|
-
|
|
480
|
-
```typescript
|
|
481
|
-
import { LuaTool, AI } from 'lua-cli/skill';
|
|
482
|
-
import { z } from 'zod';
|
|
483
|
-
|
|
484
|
-
export default class CreativeWritingTool implements LuaTool {
|
|
485
|
-
name = 'write_creative_content';
|
|
486
|
-
description = 'Generate creative content (stories, poems, descriptions)';
|
|
487
|
-
|
|
488
|
-
inputSchema = z.object({
|
|
489
|
-
type: z.enum(['story', 'poem', 'description', 'dialogue']),
|
|
490
|
-
prompt: z.string(),
|
|
491
|
-
style: z.string().optional(),
|
|
492
|
-
length: z.enum(['short', 'medium', 'long']).optional()
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
496
|
-
const lengthGuide = {
|
|
497
|
-
short: '1-2 paragraphs',
|
|
498
|
-
medium: '3-5 paragraphs',
|
|
499
|
-
long: '6-10 paragraphs'
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
const length = lengthGuide[input.length || 'medium'];
|
|
503
|
-
const style = input.style || 'engaging and creative';
|
|
504
|
-
|
|
505
|
-
const contexts = {
|
|
506
|
-
story: `You are a creative fiction writer. Write ${length} of an ${style} story based on the prompt.`,
|
|
507
|
-
poem: `You are a poet. Write a ${style} poem based on the theme.`,
|
|
508
|
-
description: `You are a descriptive writer. Create a vivid ${length} description.`,
|
|
509
|
-
dialogue: `You are a screenwriter. Write ${length} of natural, ${style} dialogue.`
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
const content = await AI.generate(
|
|
513
|
-
contexts[input.type],
|
|
514
|
-
[{
|
|
515
|
-
type: 'text',
|
|
516
|
-
text: input.prompt
|
|
517
|
-
}]
|
|
518
|
-
);
|
|
519
|
-
|
|
520
|
-
return {
|
|
521
|
-
success: true,
|
|
522
|
-
type: input.type,
|
|
523
|
-
content,
|
|
524
|
-
wordCount: content.split(/\s+/).length
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Email Draft Generator
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
import { LuaTool, AI, User } from 'lua-cli/skill';
|
|
534
|
-
import { z } from 'zod';
|
|
535
|
-
|
|
536
|
-
export default class DraftEmailTool implements LuaTool {
|
|
537
|
-
name = 'draft_email';
|
|
538
|
-
description = 'Generate professional email drafts';
|
|
539
|
-
|
|
540
|
-
inputSchema = z.object({
|
|
541
|
-
purpose: z.string().describe('What the email is about'),
|
|
542
|
-
recipient: z.string().describe('Who it\'s addressed to'),
|
|
543
|
-
tone: z.enum(['formal', 'friendly', 'urgent']).optional(),
|
|
544
|
-
includeSignature: z.boolean().optional()
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
548
|
-
const tone = input.tone || 'friendly';
|
|
549
|
-
const user = await User.get();
|
|
550
|
-
|
|
551
|
-
const context = `You are a professional email writer.
|
|
552
|
-
|
|
553
|
-
Write a ${tone} email for the following purpose: ${input.purpose}
|
|
554
|
-
|
|
555
|
-
Recipient: ${input.recipient}
|
|
556
|
-
Sender: ${user.data.name || 'User'}
|
|
557
|
-
|
|
558
|
-
Format:
|
|
559
|
-
- Subject line
|
|
560
|
-
- Greeting
|
|
561
|
-
- Body (2-4 paragraphs)
|
|
562
|
-
- Closing${input.includeSignature ? '\n- Signature' : ''}
|
|
563
|
-
|
|
564
|
-
Be clear, concise, and ${tone}.`;
|
|
565
|
-
|
|
566
|
-
const email = await AI.generate(
|
|
567
|
-
context,
|
|
568
|
-
[{
|
|
569
|
-
type: 'text',
|
|
570
|
-
text: 'Generate the email'
|
|
571
|
-
}]
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
return {
|
|
575
|
-
success: true,
|
|
576
|
-
email,
|
|
577
|
-
metadata: {
|
|
578
|
-
tone,
|
|
579
|
-
recipient: input.recipient,
|
|
580
|
-
purpose: input.purpose
|
|
581
|
-
}
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
### Code Explainer
|
|
588
|
-
|
|
589
|
-
```typescript
|
|
590
|
-
import { LuaTool, AI } from 'lua-cli/skill';
|
|
591
|
-
import { z } from 'zod';
|
|
592
|
-
|
|
593
|
-
export default class ExplainCodeTool implements LuaTool {
|
|
594
|
-
name = 'explain_code';
|
|
595
|
-
description = 'Explain code snippets in plain language';
|
|
596
|
-
|
|
597
|
-
inputSchema = z.object({
|
|
598
|
-
code: z.string(),
|
|
599
|
-
language: z.string().optional(),
|
|
600
|
-
level: z.enum(['beginner', 'intermediate', 'expert']).optional()
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
604
|
-
const level = input.level || 'intermediate';
|
|
605
|
-
const language = input.language || 'auto-detect';
|
|
606
|
-
|
|
607
|
-
const context = `You are a programming instructor explaining code to ${level}-level developers.
|
|
608
|
-
|
|
609
|
-
Language: ${language}
|
|
610
|
-
|
|
611
|
-
Explain:
|
|
612
|
-
1. What the code does (high-level)
|
|
613
|
-
2. How it works (step-by-step)
|
|
614
|
-
3. Key concepts used
|
|
615
|
-
4. Potential improvements or issues
|
|
616
|
-
|
|
617
|
-
Use clear, simple language. Include examples if helpful.`;
|
|
618
|
-
|
|
619
|
-
const explanation = await AI.generate(
|
|
620
|
-
context,
|
|
621
|
-
[{
|
|
622
|
-
type: 'text',
|
|
623
|
-
text: `Explain this code:\n\n\`\`\`${language}\n${input.code}\n\`\`\``
|
|
624
|
-
}]
|
|
625
|
-
);
|
|
626
|
-
|
|
627
|
-
return {
|
|
628
|
-
success: true,
|
|
629
|
-
code: input.code,
|
|
630
|
-
explanation,
|
|
631
|
-
level,
|
|
632
|
-
language
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
### Multi-Agent Specialist
|
|
639
|
-
|
|
640
|
-
```typescript
|
|
641
|
-
import { LuaTool, AI } from 'lua-cli/skill';
|
|
642
|
-
import { z } from 'zod';
|
|
643
|
-
|
|
644
|
-
export default class GetExpertOpinionTool implements LuaTool {
|
|
645
|
-
name = 'get_expert_opinion';
|
|
646
|
-
description = 'Get expert opinions from specialized AI personas';
|
|
647
|
-
|
|
648
|
-
inputSchema = z.object({
|
|
649
|
-
expertType: z.enum(['lawyer', 'doctor', 'financial', 'technical']),
|
|
650
|
-
question: z.string()
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
654
|
-
const expertContexts = {
|
|
655
|
-
lawyer: `You are a legal expert providing general legal information.
|
|
656
|
-
Important: This is not legal advice. Recommend consulting a licensed attorney for specific cases.`,
|
|
657
|
-
|
|
658
|
-
doctor: `You are a medical professional providing general health information.
|
|
659
|
-
Important: This is not medical advice. Recommend seeing a healthcare provider for diagnosis/treatment.`,
|
|
660
|
-
|
|
661
|
-
financial: `You are a financial advisor providing general financial guidance.
|
|
662
|
-
Important: This is not financial advice. Recommend consulting a certified financial planner.`,
|
|
663
|
-
|
|
664
|
-
technical: `You are a technical expert with deep knowledge of software, hardware, and technology.
|
|
665
|
-
Provide detailed, accurate technical information.`
|
|
666
|
-
};
|
|
667
|
-
|
|
668
|
-
const opinion = await AI.generate(
|
|
669
|
-
expertContexts[input.expertType],
|
|
670
|
-
[{
|
|
671
|
-
type: 'text',
|
|
672
|
-
text: input.question
|
|
673
|
-
}]
|
|
674
|
-
);
|
|
675
|
-
|
|
676
|
-
return {
|
|
677
|
-
success: true,
|
|
678
|
-
expertType: input.expertType,
|
|
679
|
-
question: input.question,
|
|
680
|
-
opinion,
|
|
681
|
-
disclaimer: 'This is general information only. Consult a licensed professional for specific advice.'
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
### Conversational Context Builder
|
|
688
|
-
|
|
689
|
-
```typescript
|
|
690
|
-
import { LuaTool, AI, User } from 'lua-cli/skill';
|
|
691
|
-
import { z } from 'zod';
|
|
692
|
-
|
|
693
|
-
export default class ChatWithContextTool implements LuaTool {
|
|
694
|
-
name = 'chat_with_history';
|
|
695
|
-
description = 'Generate AI response with conversation history';
|
|
696
|
-
|
|
697
|
-
inputSchema = z.object({
|
|
698
|
-
newMessage: z.string()
|
|
699
|
-
});
|
|
700
|
-
|
|
701
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
702
|
-
// Get chat history
|
|
703
|
-
const history = await User.getChatHistory();
|
|
704
|
-
|
|
705
|
-
// Build conversation context
|
|
706
|
-
const conversationContext = history
|
|
707
|
-
.slice(-10) // Last 10 messages
|
|
708
|
-
.map(msg => `${msg.role}: ${msg.content[0]?.text}`)
|
|
709
|
-
.join('\n');
|
|
710
|
-
|
|
711
|
-
const context = `You are continuing a conversation.
|
|
712
|
-
|
|
713
|
-
Previous conversation:
|
|
714
|
-
${conversationContext}
|
|
715
|
-
|
|
716
|
-
Maintain conversation continuity and reference previous topics when relevant.`;
|
|
717
|
-
|
|
718
|
-
const response = await AI.generate(
|
|
719
|
-
context,
|
|
720
|
-
[{
|
|
721
|
-
type: 'text',
|
|
722
|
-
text: input.newMessage
|
|
723
|
-
}]
|
|
724
|
-
);
|
|
725
|
-
|
|
726
|
-
return {
|
|
727
|
-
success: true,
|
|
728
|
-
response,
|
|
729
|
-
contextUsed: history.length
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
```
|
|
734
|
-
|
|
735
|
-
## Using Different Agents
|
|
736
|
-
|
|
737
|
-
```typescript
|
|
738
|
-
// Use a specialized agent for specific tasks
|
|
739
|
-
const technicalResponse = await AI.generate(
|
|
740
|
-
'You are a technical support specialist.',
|
|
741
|
-
[{ type: 'text', text: 'How do I fix error code 500?' }],
|
|
742
|
-
'technical-support-agent-id'
|
|
743
|
-
);
|
|
744
|
-
|
|
745
|
-
const salesResponse = await AI.generate(
|
|
746
|
-
'You are a sales expert.',
|
|
747
|
-
[{ type: 'text', text: 'What are the benefits of product X?' }],
|
|
748
|
-
'sales-agent-id'
|
|
749
|
-
);
|
|
750
|
-
```
|
|
751
|
-
|
|
752
328
|
## Best Practices
|
|
753
329
|
|
|
754
|
-
###
|
|
330
|
+
### DO
|
|
755
331
|
|
|
756
332
|
- Provide clear, specific context
|
|
757
|
-
- Include relevant data in the
|
|
758
|
-
- Use
|
|
759
|
-
-
|
|
760
|
-
-
|
|
761
|
-
- Set expectations in
|
|
333
|
+
- Include relevant data in the system prompt
|
|
334
|
+
- Use the simplified overload for quick text generation
|
|
335
|
+
- Use the full-options overload when you need metadata (usage, sources, finish reason)
|
|
336
|
+
- Handle AI responses that may vary (validate, parse JSON carefully)
|
|
337
|
+
- Set format expectations in the system prompt (JSON structure, length, style)
|
|
762
338
|
|
|
763
|
-
###
|
|
339
|
+
### DON'T
|
|
764
340
|
|
|
765
341
|
- Don't expect exact JSON without clear instructions
|
|
766
342
|
- Don't use AI for simple logic (if/else, calculations)
|
|
767
|
-
- Don't expose sensitive data in
|
|
343
|
+
- Don't expose sensitive data in prompts
|
|
768
344
|
- Don't make critical decisions purely on AI output
|
|
769
345
|
- Don't forget to validate/sanitize AI responses
|
|
770
346
|
|
|
771
|
-
## Context Writing Tips
|
|
772
|
-
|
|
773
|
-
### Clear Instructions
|
|
774
|
-
|
|
775
|
-
```typescript
|
|
776
|
-
// ✅ Good - Specific and clear
|
|
777
|
-
const context = `You are a product reviewer.
|
|
778
|
-
Rate products on:
|
|
779
|
-
1. Quality (1-10)
|
|
780
|
-
2. Value (1-10)
|
|
781
|
-
3. Features (1-10)
|
|
782
|
-
|
|
783
|
-
Return ONLY a JSON object with these ratings.`;
|
|
784
|
-
|
|
785
|
-
// ❌ Bad - Vague
|
|
786
|
-
const context = `Review this product`;
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
### Structured Output
|
|
790
|
-
|
|
791
|
-
```typescript
|
|
792
|
-
// ✅ Good - Request specific format
|
|
793
|
-
const context = `Analyze the text and return JSON:
|
|
794
|
-
{
|
|
795
|
-
"summary": "brief summary",
|
|
796
|
-
"keyPoints": ["point 1", "point 2"],
|
|
797
|
-
"sentiment": "positive|negative|neutral"
|
|
798
|
-
}`;
|
|
799
|
-
|
|
800
|
-
// ❌ Bad - Free-form output
|
|
801
|
-
const context = `Analyze the text`;
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
### Example-Driven
|
|
805
|
-
|
|
806
|
-
```typescript
|
|
807
|
-
// ✅ Good - Include examples
|
|
808
|
-
const context = `Extract product names from text.
|
|
809
|
-
|
|
810
|
-
Examples:
|
|
811
|
-
"I want to buy an iPhone" → ["iPhone"]
|
|
812
|
-
"Looking for Nike shoes and Adidas jacket" → ["Nike shoes", "Adidas jacket"]
|
|
813
|
-
|
|
814
|
-
Return array of product names only.`;
|
|
815
|
-
```
|
|
816
|
-
|
|
817
347
|
## Error Handling
|
|
818
348
|
|
|
819
349
|
```typescript
|
|
820
350
|
try {
|
|
821
|
-
const response = await AI.generate(
|
|
351
|
+
const response = await AI.generate('Summarize this article.', content);
|
|
822
352
|
|
|
823
|
-
// Validate response
|
|
824
353
|
if (!response || response.trim().length === 0) {
|
|
825
|
-
return {
|
|
826
|
-
success: false,
|
|
827
|
-
error: 'AI returned empty response'
|
|
828
|
-
};
|
|
354
|
+
return { success: false, error: 'AI returned empty response' };
|
|
829
355
|
}
|
|
830
356
|
|
|
831
|
-
return {
|
|
832
|
-
success: true,
|
|
833
|
-
response
|
|
834
|
-
};
|
|
357
|
+
return { success: true, response };
|
|
835
358
|
} catch (error) {
|
|
836
359
|
return {
|
|
837
360
|
success: false,
|
|
@@ -867,16 +390,10 @@ try {
|
|
|
867
390
|
| Recommendations | Product suggestions, content curation |
|
|
868
391
|
| Moderation | Content filtering, safety checks |
|
|
869
392
|
| Q&A | Document queries, knowledge retrieval |
|
|
393
|
+
| Web search | Real-time information via Google Search grounding |
|
|
870
394
|
|
|
871
395
|
## Related APIs
|
|
872
396
|
|
|
873
397
|
- [User API](./User.md) - Get user context for personalization
|
|
874
398
|
- [Data API](./Data.md) - Store AI-generated content
|
|
875
399
|
- [Jobs API](./Jobs.md) - Schedule AI tasks
|
|
876
|
-
|
|
877
|
-
## See Also
|
|
878
|
-
|
|
879
|
-
- [AI Integration Patterns](../guides/AIPatterns.md)
|
|
880
|
-
- [Multi-Modal Examples](../guides/MultiModalAI.md)
|
|
881
|
-
- [Context Engineering Guide](../guides/ContextEngineering.md)
|
|
882
|
-
|