lua-cli 3.0.0-alpha.10 → 3.0.0-alpha.12
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/chat.api.service.js +27 -22
- package/dist/api-exports.d.ts +1 -1
- package/dist/api-exports.js +6 -1
- package/dist/commands/chat.js +30 -35
- package/dist/commands/init.js +10 -2
- package/dist/index.js +2 -2
- package/dist/interfaces/message.d.ts +2 -2
- package/dist/utils/agent-management.d.ts +1 -1
- package/dist/utils/agent-management.js +5 -3
- package/dist/utils/init-helpers.d.ts +10 -1
- package/dist/utils/init-helpers.js +44 -1
- package/dist/utils/pre-bundle-jobs.js +9 -9
- package/dist/utils/sandbox.js +1 -2
- package/package.json +2 -2
- package/template/src/index.ts +25 -252
- package/template/src/postprocessors/modifyResponse.ts +21 -0
- package/template/src/preprocessors/messageMatching.ts +22 -0
- package/template/src/skills/basket.skill.ts +12 -0
- package/template/src/skills/product.skill.ts +13 -0
- package/template/src/{tools → skills/tools}/ProductsTool.ts +2 -1
- package/template/src/skills/tools/UserDataTool.ts +75 -0
- package/template/src/skills/user.skill.ts +13 -0
- package/template/src/seed.ts +0 -46
- package/template/src/tools/UserDataTool.ts +0 -33
- /package/template/src/{tools → skills/tools}/BasketTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/CreateInlineJob.ts +0 -0
- /package/template/src/{tools → skills/tools}/CreatePostTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/CustomDataTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/GameScoreTrackerTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/GetWeatherTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/OrderTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/PaymentTool.ts +0 -0
- /package/template/src/{tools → skills/tools}/SmartBasketTool.ts +0 -0
|
@@ -40,35 +40,40 @@ export default class ChatApi extends HttpClient {
|
|
|
40
40
|
if (!response.ok) {
|
|
41
41
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
if (!reader) {
|
|
43
|
+
if (!response.body) {
|
|
45
44
|
throw new Error('Response body is not readable');
|
|
46
45
|
}
|
|
46
|
+
const reader = response.body.getReader();
|
|
47
47
|
const decoder = new TextDecoder();
|
|
48
48
|
let buffer = '';
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
49
|
+
try {
|
|
50
|
+
while (true) {
|
|
51
|
+
const { done, value } = await reader.read();
|
|
52
|
+
if (done)
|
|
53
|
+
break;
|
|
54
|
+
// Decode the chunk and add to buffer
|
|
55
|
+
buffer += decoder.decode(value, { stream: true });
|
|
56
|
+
// Process complete lines (chunks are separated by newlines)
|
|
57
|
+
const lines = buffer.split('\n');
|
|
58
|
+
buffer = lines.pop() || ''; // Keep incomplete line in buffer
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
if (!line.trim())
|
|
61
|
+
continue;
|
|
62
|
+
try {
|
|
63
|
+
const chunk = JSON.parse(line);
|
|
64
|
+
// Only process text-delta chunks and call onChunk immediately
|
|
65
|
+
if (chunk.type === 'text-delta' && chunk.textDelta) {
|
|
66
|
+
onChunk(chunk.textDelta);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
// Skip invalid JSON lines
|
|
66
71
|
}
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
// Skip invalid JSON lines
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
finally {
|
|
76
|
+
reader.releaseLock();
|
|
77
|
+
}
|
|
73
78
|
}
|
|
74
79
|
}
|
package/dist/api-exports.d.ts
CHANGED
|
@@ -402,5 +402,5 @@ export declare const AI: {
|
|
|
402
402
|
generate(context: string, messages: import("./interfaces/chat.js").ChatMessage[], agentId?: string): Promise<string>;
|
|
403
403
|
};
|
|
404
404
|
export { LuaSkill, LuaTool, LuaWebhook, LuaWebhookConfig, LuaJob, LuaJobConfig, JobSchedule, PreProcessor, PreProcessorConfig, PostProcessor, PostProcessorConfig, LuaAgent, LuaAgentConfig, BasketStatus, OrderStatus, env };
|
|
405
|
-
export { JobInstance };
|
|
405
|
+
export { JobInstance, UserDataInstance, DataEntryInstance, ProductInstance, BasketInstance, OrderInstance };
|
|
406
406
|
export { ChatHistoryMessage, ChatHistoryContent, ChatMessage, TextMessage, ImageMessage, FileMessage, PreProcessorOverride, PostProcessorOverride };
|
package/dist/api-exports.js
CHANGED
|
@@ -31,6 +31,11 @@ import { BasketStatus } from "./interfaces/baskets.js";
|
|
|
31
31
|
import { OrderStatus } from "./interfaces/orders.js";
|
|
32
32
|
import { getUserInstance, getDataInstance, getProductsInstance, getBasketsInstance, getOrderInstance, getJobInstance, getChatInstance, } from "./api/lazy-instances.js";
|
|
33
33
|
import { JobInstance } from "./common/job.instance.js";
|
|
34
|
+
import ProductInstance from "./common/product.instance.js";
|
|
35
|
+
import DataEntryInstance from "./common/data.entry.instance.js";
|
|
36
|
+
import UserDataInstance from "./common/user.instance.js";
|
|
37
|
+
import BasketInstance from "./common/basket.instance.js";
|
|
38
|
+
import OrderInstance from "./common/order.instance.js";
|
|
34
39
|
export const User = {
|
|
35
40
|
/**
|
|
36
41
|
* Retrieves current user data.
|
|
@@ -543,4 +548,4 @@ export const AI = {
|
|
|
543
548
|
// Export skill classes and utilities
|
|
544
549
|
export { LuaSkill, LuaWebhook, LuaJob, PreProcessor, PostProcessor, LuaAgent, BasketStatus, OrderStatus, env };
|
|
545
550
|
// Export instance classes
|
|
546
|
-
export { JobInstance };
|
|
551
|
+
export { JobInstance, UserDataInstance, DataEntryInstance, ProductInstance, BasketInstance, OrderInstance };
|
package/dist/commands/chat.js
CHANGED
|
@@ -148,22 +148,41 @@ async function startChatLoop(chatEnv) {
|
|
|
148
148
|
rl.prompt();
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
|
+
// Start typing indicator
|
|
152
|
+
const typingInterval = startTypingIndicator();
|
|
153
|
+
let firstChunk = true;
|
|
151
154
|
try {
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
// Create a callback that stops typing on first chunk
|
|
156
|
+
const handleChunk = (chunk) => {
|
|
157
|
+
if (firstChunk) {
|
|
158
|
+
// Stop typing indicator and show assistant label
|
|
159
|
+
stopTypingIndicator(typingInterval);
|
|
160
|
+
process.stdout.write('🌙 Assistant: ');
|
|
161
|
+
firstChunk = false;
|
|
162
|
+
}
|
|
163
|
+
// Write the chunk immediately
|
|
164
|
+
process.stdout.write(chunk);
|
|
165
|
+
};
|
|
155
166
|
if (chatEnv.type === 'sandbox') {
|
|
156
167
|
// Send to sandbox with skill overrides (streaming)
|
|
157
|
-
|
|
168
|
+
await sendSandboxMessageStream(chatEnv, message, handleChunk);
|
|
158
169
|
}
|
|
159
170
|
else {
|
|
160
171
|
// Send to production (streaming)
|
|
161
|
-
|
|
172
|
+
await sendProductionMessageStream(chatEnv, message, handleChunk);
|
|
173
|
+
}
|
|
174
|
+
// If no chunks arrived, stop the typing indicator
|
|
175
|
+
if (firstChunk) {
|
|
176
|
+
stopTypingIndicator(typingInterval);
|
|
162
177
|
}
|
|
163
178
|
// Add newline after response
|
|
164
179
|
console.log('\n');
|
|
165
180
|
}
|
|
166
181
|
catch (error) {
|
|
182
|
+
// Make sure typing indicator is stopped on error
|
|
183
|
+
if (firstChunk) {
|
|
184
|
+
stopTypingIndicator(typingInterval);
|
|
185
|
+
}
|
|
167
186
|
console.error(`\n❌ Error: ${error instanceof Error ? error.message : 'Unknown error'}\n`);
|
|
168
187
|
}
|
|
169
188
|
rl.prompt();
|
|
@@ -200,14 +219,14 @@ function stopTypingIndicator(interval) {
|
|
|
200
219
|
/**
|
|
201
220
|
* Sends a message to the sandbox environment with skill overrides (streaming)
|
|
202
221
|
*/
|
|
203
|
-
async function sendSandboxMessageStream(chatEnv, message) {
|
|
222
|
+
async function sendSandboxMessageStream(chatEnv, message, onChunk) {
|
|
204
223
|
if (!chatEnv.deployData) {
|
|
205
|
-
|
|
224
|
+
throw new Error("Sandbox environment not properly initialized.");
|
|
206
225
|
}
|
|
207
226
|
// Get all sandbox skill IDs for skill override
|
|
208
227
|
const allSkillOverrides = await getAllSandboxSkillIds(chatEnv.deployData);
|
|
209
228
|
if (allSkillOverrides.length === 0) {
|
|
210
|
-
|
|
229
|
+
throw new Error("No sandbox skills found. Please try running the command again.");
|
|
211
230
|
}
|
|
212
231
|
const chatRequest = {
|
|
213
232
|
messages: [
|
|
@@ -226,24 +245,12 @@ async function sendSandboxMessageStream(chatEnv, message) {
|
|
|
226
245
|
chatRequest.personaOverride = chatEnv.persona;
|
|
227
246
|
}
|
|
228
247
|
const chatApi = new ChatApi(BASE_URLS.CHAT, chatEnv.apiKey);
|
|
229
|
-
|
|
230
|
-
try {
|
|
231
|
-
await chatApi.sendMessageStream(chatEnv.agentId, chatRequest, (chunk) => {
|
|
232
|
-
// Write each chunk to stdout as it arrives
|
|
233
|
-
process.stdout.write(chunk);
|
|
234
|
-
fullResponse += chunk;
|
|
235
|
-
});
|
|
236
|
-
return fullResponse;
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
console.error(`\n❌ Chat API error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
240
|
-
return '';
|
|
241
|
-
}
|
|
248
|
+
await chatApi.sendMessageStream(chatEnv.agentId, chatRequest, onChunk);
|
|
242
249
|
}
|
|
243
250
|
/**
|
|
244
251
|
* Sends a message to the production environment (streaming)
|
|
245
252
|
*/
|
|
246
|
-
async function sendProductionMessageStream(chatEnv, message) {
|
|
253
|
+
async function sendProductionMessageStream(chatEnv, message, onChunk) {
|
|
247
254
|
const chatRequest = {
|
|
248
255
|
messages: [
|
|
249
256
|
{
|
|
@@ -257,17 +264,5 @@ async function sendProductionMessageStream(chatEnv, message) {
|
|
|
257
264
|
postprocessorOverride: []
|
|
258
265
|
};
|
|
259
266
|
const chatApi = new ChatApi(BASE_URLS.CHAT, chatEnv.apiKey);
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
await chatApi.sendMessageStream(chatEnv.agentId, chatRequest, (chunk) => {
|
|
263
|
-
// Write each chunk to stdout as it arrives
|
|
264
|
-
process.stdout.write(chunk);
|
|
265
|
-
fullResponse += chunk;
|
|
266
|
-
});
|
|
267
|
-
return fullResponse;
|
|
268
|
-
}
|
|
269
|
-
catch (error) {
|
|
270
|
-
console.error(`\n❌ Chat API error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
271
|
-
return '';
|
|
272
|
-
}
|
|
267
|
+
await chatApi.sendMessageStream(chatEnv.agentId, chatRequest, onChunk);
|
|
273
268
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -127,14 +127,18 @@ export async function initCommand() {
|
|
|
127
127
|
}
|
|
128
128
|
// Step 5: Initialize or update project
|
|
129
129
|
if (yamlExists) {
|
|
130
|
-
// Update existing YAML
|
|
130
|
+
// Update existing YAML and LuaAgent in index.ts
|
|
131
131
|
writeInfo("📝 Updating existing lua.skill.yaml with new agent...");
|
|
132
132
|
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, persona, welcomeMessage);
|
|
133
|
+
// Also update LuaAgent in index.ts if it exists
|
|
134
|
+
const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
|
|
135
|
+
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, persona, welcomeMessage);
|
|
133
136
|
writeSuccess("✅ lua.skill.yaml updated successfully!");
|
|
137
|
+
writeSuccess("✅ LuaAgent configuration updated!");
|
|
134
138
|
}
|
|
135
139
|
else {
|
|
136
140
|
// Full project initialization
|
|
137
|
-
const currentDir = initializeProject(selectedAgent.agentId, selectedOrg.id, persona, welcomeMessage);
|
|
141
|
+
const currentDir = initializeProject(selectedAgent.agentId, selectedOrg.id, persona, welcomeMessage, selectedAgent.name);
|
|
138
142
|
// Step 6: Install dependencies
|
|
139
143
|
await installDependencies(currentDir);
|
|
140
144
|
writeSuccess("✅ Lua skill project initialized successfully!");
|
|
@@ -290,7 +294,11 @@ async function handleAgentSwitch(userData, apiKey, existingYaml) {
|
|
|
290
294
|
// Update existing YAML file with new agent
|
|
291
295
|
writeInfo("\n📝 Updating lua.skill.yaml with new agent...");
|
|
292
296
|
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, finalPersona, finalWelcomeMessage);
|
|
297
|
+
// Also update LuaAgent in index.ts if it exists
|
|
298
|
+
const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
|
|
299
|
+
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, finalPersona, finalWelcomeMessage);
|
|
293
300
|
writeSuccess("✅ lua.skill.yaml updated successfully!");
|
|
301
|
+
writeSuccess("✅ LuaAgent configuration updated!");
|
|
294
302
|
writeInfo("\n💡 Your project now uses the new agent. Run 'lua compile' to update your skills.\n");
|
|
295
303
|
}
|
|
296
304
|
/**
|
package/dist/index.js
CHANGED
|
@@ -16,10 +16,10 @@ const program = new Command();
|
|
|
16
16
|
program
|
|
17
17
|
.name("lua")
|
|
18
18
|
.description("Lua AI - Build and deploy AI agents with superpowers")
|
|
19
|
-
.version("2.
|
|
19
|
+
.version("2.5.8")
|
|
20
20
|
.addHelpText('before', `
|
|
21
21
|
------------------------------------------------------------------
|
|
22
|
-
Lua AI CLI v2.
|
|
22
|
+
Lua AI CLI v2.5.8 - Build and deploy AI agents with superpowers
|
|
23
23
|
------------------------------------------------------------------
|
|
24
24
|
`)
|
|
25
25
|
.addHelpText('after', `
|
|
@@ -5,12 +5,12 @@ export type TextMessage = {
|
|
|
5
5
|
export type ImageMessage = {
|
|
6
6
|
type: "image";
|
|
7
7
|
image: string;
|
|
8
|
-
|
|
8
|
+
mediaType: string;
|
|
9
9
|
};
|
|
10
10
|
export type FileMessage = {
|
|
11
11
|
type: "file";
|
|
12
12
|
data: string;
|
|
13
|
-
|
|
13
|
+
mediaType: string;
|
|
14
14
|
};
|
|
15
15
|
export type Message = TextMessage | ImageMessage | FileMessage;
|
|
16
16
|
export interface SendMessageRequest {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Handles LuaAgent persona and welcome message synchronization with lua.skill.yaml
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* Syncs the agent's persona and welcome message with lua.skill.yaml.
|
|
6
|
+
* Syncs the agent's name, persona, and welcome message with lua.skill.yaml.
|
|
7
7
|
* This ensures the YAML configuration reflects the agent definition in code.
|
|
8
8
|
*
|
|
9
9
|
* @param agentMetadata - Agent metadata extracted from LuaAgent
|
|
@@ -7,7 +7,7 @@ import path from "path";
|
|
|
7
7
|
import yaml from "js-yaml";
|
|
8
8
|
import { COMPILE_FILES, YAML_FORMAT } from '../config/compile.constants.js';
|
|
9
9
|
/**
|
|
10
|
-
* Syncs the agent's persona and welcome message with lua.skill.yaml.
|
|
10
|
+
* Syncs the agent's name, persona, and welcome message with lua.skill.yaml.
|
|
11
11
|
* This ensures the YAML configuration reflects the agent definition in code.
|
|
12
12
|
*
|
|
13
13
|
* @param agentMetadata - Agent metadata extracted from LuaAgent
|
|
@@ -20,12 +20,14 @@ export async function syncAgentPersonaWithYaml(agentMetadata) {
|
|
|
20
20
|
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
21
21
|
config = yaml.load(yamlContent);
|
|
22
22
|
}
|
|
23
|
-
// Update agent section with persona and welcome message
|
|
23
|
+
// Update agent section with name, persona, and welcome message
|
|
24
24
|
config.agent = {
|
|
25
25
|
...config.agent,
|
|
26
26
|
persona: agentMetadata.persona,
|
|
27
27
|
welcomeMessage: agentMetadata.welcomeMessage
|
|
28
28
|
};
|
|
29
|
+
// Store agent name as a comment or in metadata (YAML doesn't have an agentName field)
|
|
30
|
+
// The agent name is primarily for the LuaAgent in code
|
|
29
31
|
// Write updated YAML with consistent formatting
|
|
30
32
|
const yamlContent = yaml.dump(config, {
|
|
31
33
|
indent: YAML_FORMAT.INDENT,
|
|
@@ -37,7 +39,7 @@ export async function syncAgentPersonaWithYaml(agentMetadata) {
|
|
|
37
39
|
}
|
|
38
40
|
});
|
|
39
41
|
fs.writeFileSync(yamlPath, yamlContent);
|
|
40
|
-
console.log(`✅ Synced agent
|
|
42
|
+
console.log(`✅ Synced agent configuration to lua.skill.yaml`);
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
45
|
* Reads the agent persona from lua.skill.yaml.
|
|
@@ -17,7 +17,7 @@ export declare function getTemplateDir(): string;
|
|
|
17
17
|
* @param welcomeMessage - Optional welcome message
|
|
18
18
|
* @returns Current working directory
|
|
19
19
|
*/
|
|
20
|
-
export declare function initializeProject(agentId: string, orgId: string, persona?: string, welcomeMessage?: string): string;
|
|
20
|
+
export declare function initializeProject(agentId: string, orgId: string, persona?: string, welcomeMessage?: string, agentName?: string): string;
|
|
21
21
|
/**
|
|
22
22
|
* Installs npm dependencies for the project.
|
|
23
23
|
*
|
|
@@ -39,3 +39,12 @@ export declare function calculatePromptLines(baseCount: number, additionalLines:
|
|
|
39
39
|
* @param lineCount - Number of lines to clear
|
|
40
40
|
*/
|
|
41
41
|
export declare function clearLinesIfNeeded(lineCount: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Updates the LuaAgent configuration in the template's index.ts file
|
|
44
|
+
*
|
|
45
|
+
* @param projectDir - Project directory containing src/index.ts
|
|
46
|
+
* @param agentName - Name of the agent
|
|
47
|
+
* @param persona - Agent persona
|
|
48
|
+
* @param welcomeMessage - Welcome message
|
|
49
|
+
*/
|
|
50
|
+
export declare function updateLuaAgentInIndexFile(projectDir: string, agentName?: string, persona?: string, welcomeMessage?: string): void;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import path from "path";
|
|
7
|
+
import fs from "fs";
|
|
7
8
|
import { copyTemplateFiles, createSkillYaml } from "./files.js";
|
|
8
9
|
import { clearPromptLines, writeProgress } from "./cli.js";
|
|
9
10
|
import { execSync } from 'child_process';
|
|
@@ -26,13 +27,16 @@ export function getTemplateDir() {
|
|
|
26
27
|
* @param welcomeMessage - Optional welcome message
|
|
27
28
|
* @returns Current working directory
|
|
28
29
|
*/
|
|
29
|
-
export function initializeProject(agentId, orgId, persona, welcomeMessage) {
|
|
30
|
+
export function initializeProject(agentId, orgId, persona, welcomeMessage, agentName) {
|
|
30
31
|
const templateDir = getTemplateDir();
|
|
31
32
|
const currentDir = process.cwd();
|
|
32
33
|
copyTemplateFiles(templateDir, currentDir);
|
|
33
34
|
createSkillYaml(agentId, orgId, undefined, undefined, persona, welcomeMessage);
|
|
35
|
+
// Update LuaAgent in index.ts with agent configuration
|
|
36
|
+
updateLuaAgentInIndexFile(currentDir, agentName, persona, welcomeMessage);
|
|
34
37
|
writeProgress("✅ Created lua.skill.yaml");
|
|
35
38
|
writeProgress("✅ Copied template files");
|
|
39
|
+
writeProgress("✅ Updated LuaAgent configuration");
|
|
36
40
|
return currentDir;
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
@@ -71,3 +75,42 @@ export function clearLinesIfNeeded(lineCount) {
|
|
|
71
75
|
clearPromptLines(lineCount);
|
|
72
76
|
}
|
|
73
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Updates the LuaAgent configuration in the template's index.ts file
|
|
80
|
+
*
|
|
81
|
+
* @param projectDir - Project directory containing src/index.ts
|
|
82
|
+
* @param agentName - Name of the agent
|
|
83
|
+
* @param persona - Agent persona
|
|
84
|
+
* @param welcomeMessage - Welcome message
|
|
85
|
+
*/
|
|
86
|
+
export function updateLuaAgentInIndexFile(projectDir, agentName, persona, welcomeMessage) {
|
|
87
|
+
const indexPath = path.join(projectDir, 'src', 'index.ts');
|
|
88
|
+
if (!fs.existsSync(indexPath)) {
|
|
89
|
+
// If no index.ts, skip (might be an old template structure)
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
let content = fs.readFileSync(indexPath, 'utf8');
|
|
94
|
+
// Check if LuaAgent exists in the file
|
|
95
|
+
if (!content.includes('new LuaAgent(')) {
|
|
96
|
+
return; // No LuaAgent to update
|
|
97
|
+
}
|
|
98
|
+
// Update agent name
|
|
99
|
+
if (agentName) {
|
|
100
|
+
content = content.replace(/name:\s*['"][^'"]*['"]/, `name: '${agentName.replace(/'/g, "\\'")}'`);
|
|
101
|
+
}
|
|
102
|
+
// Update persona
|
|
103
|
+
if (persona) {
|
|
104
|
+
content = content.replace(/(persona:\s*['"`])[\s\S]*?(['"`])/, `$1${persona.replace(/'/g, "\\'").replace(/`/g, '\\`')}$2`);
|
|
105
|
+
}
|
|
106
|
+
// Update welcome message
|
|
107
|
+
if (welcomeMessage) {
|
|
108
|
+
content = content.replace(/(welcomeMessage:\s*['"])[\s\S]*?(['"])/, `$1${welcomeMessage.replace(/'/g, "\\'")}$2`);
|
|
109
|
+
}
|
|
110
|
+
fs.writeFileSync(indexPath, content);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// Silently fail - not critical
|
|
114
|
+
console.warn('Warning: Could not update LuaAgent in index.ts');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -40,7 +40,7 @@ export async function preBundleJobsInSource(sourceFilePath, project, distDir) {
|
|
|
40
40
|
if (object.getText() === 'Jobs' && property === 'create') {
|
|
41
41
|
jobIndex++;
|
|
42
42
|
const placeholder = `${JOB_PLACEHOLDER}_${jobIndex}`;
|
|
43
|
-
console.log(`[PreBundleJobs] Found Jobs.create() #${jobIndex}`);
|
|
43
|
+
// console.log(`[PreBundleJobs] Found Jobs.create() #${jobIndex}`);
|
|
44
44
|
// Get the config object argument
|
|
45
45
|
const args = node.getArguments();
|
|
46
46
|
if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {
|
|
@@ -51,12 +51,12 @@ export async function preBundleJobsInSource(sourceFilePath, project, distDir) {
|
|
|
51
51
|
const executeInitializer = executeProperty.getInitializer();
|
|
52
52
|
if (executeInitializer) {
|
|
53
53
|
const executeCode = executeInitializer.getText();
|
|
54
|
-
console.log(`[PreBundleJobs] Extracting execute function for bundling...`);
|
|
54
|
+
// console.log(`[PreBundleJobs] Extracting execute function for bundling...`);
|
|
55
55
|
// Bundle the execute function with dependencies (async)
|
|
56
56
|
const bundlePromise = bundleJobExecuteFunction(executeCode, `job_${jobIndex}`, distDir, sourceFilePath).then(bundledCode => {
|
|
57
57
|
if (bundledCode) {
|
|
58
58
|
jobBundles.set(placeholder, bundledCode);
|
|
59
|
-
console.log(`[PreBundleJobs] ✅ Bundled job #${jobIndex} with dependencies`);
|
|
59
|
+
// console.log(`[PreBundleJobs] ✅ Bundled job #${jobIndex} with dependencies`);
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
bundlingPromises.push(bundlePromise);
|
|
@@ -74,9 +74,9 @@ export async function preBundleJobsInSource(sourceFilePath, project, distDir) {
|
|
|
74
74
|
});
|
|
75
75
|
// Wait for all bundling to complete
|
|
76
76
|
if (bundlingPromises.length > 0) {
|
|
77
|
-
console.log(`[PreBundleJobs] Waiting for ${bundlingPromises.length} job(s) to bundle...`);
|
|
77
|
+
// console.log(`[PreBundleJobs] Waiting for ${bundlingPromises.length} job(s) to bundle...`);
|
|
78
78
|
await Promise.all(bundlingPromises);
|
|
79
|
-
console.log(`[PreBundleJobs] ✅ All job bundles complete`);
|
|
79
|
+
// console.log(`[PreBundleJobs] ✅ All job bundles complete`);
|
|
80
80
|
}
|
|
81
81
|
return { modifiedSource, jobBundles };
|
|
82
82
|
}
|
|
@@ -103,7 +103,7 @@ async function bundleJobExecuteFunction(executeCode, jobName, distDir, sourceFil
|
|
|
103
103
|
!imp.includes('api-exports') && // Exclude api-exports
|
|
104
104
|
!imp.includes('../../../dist/api-exports') // Exclude direct api-exports imports
|
|
105
105
|
);
|
|
106
|
-
console.log(`[PreBundleJobs] Including ${relevantImports.length} import(s) in job bundle`);
|
|
106
|
+
// console.log(`[PreBundleJobs] Including ${relevantImports.length} import(s) in job bundle`);
|
|
107
107
|
// Create a TypeScript module with the execute function and all imports
|
|
108
108
|
const moduleCode = `
|
|
109
109
|
// Auto-generated job execute bundle
|
|
@@ -133,7 +133,7 @@ export default executeFunc;
|
|
|
133
133
|
});
|
|
134
134
|
// Read bundled code
|
|
135
135
|
const bundledCode = fs.readFileSync(tempOutput, 'utf8');
|
|
136
|
-
console.log(`[PreBundleJobs] Bundle size: ${(bundledCode.length / 1024).toFixed(2)}KB`);
|
|
136
|
+
// console.log(`[PreBundleJobs] Bundle size: ${(bundledCode.length / 1024).toFixed(2)}KB`);
|
|
137
137
|
// DON'T compress - just wrap for VM execution
|
|
138
138
|
// Compression happens later when the entire tool is bundled
|
|
139
139
|
const wrappedCode = `(async (job) => {
|
|
@@ -150,7 +150,7 @@ export default executeFunc;
|
|
|
150
150
|
return wrappedCode;
|
|
151
151
|
}
|
|
152
152
|
catch (error) {
|
|
153
|
-
console.warn(`[PreBundleJobs] Error bundling job ${jobName}:`, error);
|
|
153
|
+
// console.warn(`[PreBundleJobs] Error bundling job ${jobName}:`, error);
|
|
154
154
|
try {
|
|
155
155
|
if (fs.existsSync(tempOutput))
|
|
156
156
|
fs.unlinkSync(tempOutput);
|
|
@@ -170,7 +170,7 @@ export function replaceJobPlaceholders(bundledCode, jobBundles) {
|
|
|
170
170
|
// It appears as: execute: __BUNDLED_JOB_EXECUTE___1
|
|
171
171
|
const placeholderPattern = new RegExp(placeholder, 'g');
|
|
172
172
|
result = result.replace(placeholderPattern, bundledJobCode);
|
|
173
|
-
console.log(`[PreBundleJobs] ✅ Replaced ${placeholder} with bundled code (${(bundledJobCode.length / 1024).toFixed(1)}KB)`);
|
|
173
|
+
// console.log(`[PreBundleJobs] ✅ Replaced ${placeholder} with bundled code (${(bundledJobCode.length / 1024).toFixed(1)}KB)`);
|
|
174
174
|
});
|
|
175
175
|
return result;
|
|
176
176
|
}
|
package/dist/utils/sandbox.js
CHANGED
|
@@ -231,10 +231,9 @@ export function createSandbox(options) {
|
|
|
231
231
|
const executeString = typeof config.execute === 'function'
|
|
232
232
|
? config.execute.toString()
|
|
233
233
|
: config.execute;
|
|
234
|
-
console.log('IsDynamicJob', config.dynamic);
|
|
235
234
|
// Create job with version and activation
|
|
236
235
|
return await jobService.createJobInstance({
|
|
237
|
-
name: config.name,
|
|
236
|
+
name: config.name + '_' + Date.now(),
|
|
238
237
|
description: config.description,
|
|
239
238
|
context: config.description || '',
|
|
240
239
|
schedule: config.schedule,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lua-cli",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.12",
|
|
4
4
|
"description": "Command-line interface for Lua AI platform - develop, test, and deploy LuaSkills with custom tools",
|
|
5
5
|
"readmeFilename": "README.md",
|
|
6
6
|
"main": "dist/api-exports.js",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"inquirer": "^12.9.6",
|
|
73
73
|
"js-yaml": "^4.1.0",
|
|
74
74
|
"keytar": "^7.9.0",
|
|
75
|
-
"lua-ai-chat": "^0.0.
|
|
75
|
+
"lua-ai-chat": "^0.0.6",
|
|
76
76
|
"lua-cli": "^2.3.0-alpha.1",
|
|
77
77
|
"luaniverse": "^4.0.43",
|
|
78
78
|
"node-fetch": "^3.3.2",
|
package/template/src/index.ts
CHANGED
|
@@ -1,260 +1,33 @@
|
|
|
1
|
-
import { LuaSkill, User, Products, Orders, Data, Baskets, LuaJob, JobInstance, LuaWebhook, Jobs } from "lua-cli";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Jobs are scheduled tasks that run at specific times or intervals
|
|
26
|
-
// See: WEBHOOK_JOB_EXAMPLES.md for detailed explanations
|
|
27
|
-
|
|
28
|
-
import dailyCleanupJob from "./jobs/DailyCleanupJob";
|
|
29
|
-
// import healthCheckJob from "./jobs/HealthCheckJob";
|
|
30
|
-
// import dataMigrationJob from "./jobs/DataMigrationJob";
|
|
31
|
-
// import abandonedBasketProcessorJob from "./jobs/AbandonedBasketProcessorJob";
|
|
32
|
-
|
|
33
|
-
// ============================================================================
|
|
34
|
-
// SMART BASKET TOOL (Uncomment to enable)
|
|
35
|
-
// ============================================================================
|
|
36
|
-
// This tool creates baskets with automatic abandoned cart reminders
|
|
37
|
-
// Uses Jobs.create() to schedule one-time check 3 hours after creation
|
|
38
|
-
|
|
39
|
-
// import { CreateSmartBasketTool, CheckAbandonedBasketsTool } from "./tools/SmartBasketTool";
|
|
40
|
-
|
|
41
|
-
// ============================================================================
|
|
42
|
-
// GAME SCORE TRACKER (Uncomment to enable) - ADVANCED EXAMPLE
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// Complex example showing:
|
|
45
|
-
// - Interval jobs that start at specific time
|
|
46
|
-
// - Jobs that stop themselves when condition is met
|
|
47
|
-
// - Real-time monitoring with external API integration
|
|
48
|
-
// See: COMPLEX_JOB_EXAMPLES.md for detailed explanation
|
|
49
|
-
|
|
50
|
-
// import { TrackGameScoresTool, GetGameScoresTool, StopGameTrackingTool } from "./tools/GameScoreTrackerTool";
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Initialize skill with tools
|
|
54
|
-
const generalSkill = new LuaSkill({
|
|
55
|
-
name: "general-skill",
|
|
56
|
-
version: "0.0.2",
|
|
57
|
-
description: "A comprehensive Lua skill with weather, user data, post creation, and mathematical tools",
|
|
58
|
-
context: "This skill provides various utilities including weather information, user data retrieval, post creation, basic calculator operations, and advanced mathematical functions. Use get_weather to fetch current weather conditions for any city, get_user_data to retrieve user information, create_post to publish new posts, calculator for basic arithmetic operations, and advanced_math for complex mathematical computations like factorials, prime checking, fibonacci sequences, and greatest common divisor calculations.",
|
|
59
|
-
tools: [
|
|
60
|
-
new GetWeatherTool(),
|
|
61
|
-
new CreatePostTool(),
|
|
62
|
-
new CreateInlineJobTool()
|
|
63
|
-
]
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const userDataSkill = new LuaSkill({
|
|
67
|
-
name: "user-data-skill",
|
|
68
|
-
version: "0.0.1",
|
|
69
|
-
description: "A specific Lua skill with user data",
|
|
70
|
-
context: "This skill provides various utilities including user data retrieval, creation, and updating.",
|
|
71
|
-
tools: [
|
|
72
|
-
new GetUserDataTool(),
|
|
73
|
-
new UpdateUserDataTool()
|
|
74
|
-
]
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const productSkill = new LuaSkill({
|
|
79
|
-
name: "product-skill",
|
|
80
|
-
version: "0.0.1",
|
|
81
|
-
description: "A specific Lua skill with products",
|
|
82
|
-
context: "This skill provides various utilities including products.",
|
|
83
|
-
tools: [
|
|
84
|
-
new SearchProductsTool(),
|
|
85
|
-
new GetAllProductsTool(),
|
|
86
|
-
new CreateProductTool(),
|
|
87
|
-
new UpdateProductTool(),
|
|
88
|
-
new GetProductByIdTool(),
|
|
89
|
-
new DeleteProductTool()
|
|
90
|
-
]
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const basketSkill = new LuaSkill({
|
|
95
|
-
name: "basket-skill",
|
|
96
|
-
version: "0.0.1",
|
|
97
|
-
description: "A specific Lua skill with baskets",
|
|
98
|
-
context: "This skill provides various utilities including baskets.",
|
|
99
|
-
tools: [
|
|
100
|
-
new CreateBasketTool(),
|
|
101
|
-
new GetBasketsTool(),
|
|
102
|
-
new AddItemToBasketTool(),
|
|
103
|
-
new RemoveItemFromBasketTool(),
|
|
104
|
-
new ClearBasketTool(),
|
|
105
|
-
new UpdateBasketStatusTool(),
|
|
106
|
-
new UpdateBasketMetadataTool(),
|
|
107
|
-
new CheckoutBasketTool(),
|
|
108
|
-
new GetBasketByIdTool()
|
|
109
|
-
]
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const orderSkill = new LuaSkill({
|
|
114
|
-
name: "order-skill",
|
|
115
|
-
version: "0.0.1",
|
|
116
|
-
description: "A specific Lua skill with orders",
|
|
117
|
-
context: "This skill provides various utilities including orders.",
|
|
118
|
-
tools: [
|
|
119
|
-
new CreateOrderTool(),
|
|
120
|
-
new UpdateOrderStatusTool(),
|
|
121
|
-
new GetOrderByIdTool(),
|
|
122
|
-
new GetUserOrdersTool()
|
|
123
|
-
]
|
|
1
|
+
import { LuaAgent, LuaSkill, User, Products, Orders, Data, Baskets, LuaJob, JobInstance, LuaWebhook, Jobs } from "lua-cli";
|
|
2
|
+
import userSkill from "./skills/user.skill";
|
|
3
|
+
import productSkill from "./skills/product.skill";
|
|
4
|
+
import basketSkill from "./skills/basket.skill";
|
|
5
|
+
import userEventWebhook from "./webhooks/UserEventWebhook";
|
|
6
|
+
import healthCheckJob from "./jobs/HealthCheckJob";
|
|
7
|
+
import messageMatchingPreProcessor from "./preprocessors/messageMatching";
|
|
8
|
+
import modifyResponsePostProcessor from "./postprocessors/modifyResponse";
|
|
9
|
+
|
|
10
|
+
const agent = new LuaAgent({
|
|
11
|
+
name: "my-agent",
|
|
12
|
+
persona: `Meet Vivienne Spark, the energetic and fun assistant at CLI V3 Test, a dynamic retail presence in the clothing and bookstore sector. Vivienne embodies the lively spirit of the brand, bursting with enthusiasm and a zest for life. Her role as a retail agent is not just about assisting but about transforming shopping into an exciting experience. The brand's personality is vibrant and playful, resonating with a young and adventurous clientele who thrives on creativity and innovation.
|
|
13
|
+
|
|
14
|
+
Vivienne thrives on curiosity and optimism, forever ready to brighten a customer's day with her infectious positivity. She communicates with a warmth that makes shopping feel personal and enjoyable, speaking with a friendly, down-to-earth tone that invites discussion. Customers ranging from fashionable teenagers to busy young professionals look to Vivienne for her fresh, lively insight on the latest trends and must-have reads.
|
|
15
|
+
|
|
16
|
+
Her sales approach is consultative and engaging, effortlessly guiding customers through options with confident yet non-intrusive recommendations. Vivienne excels at upselling in a way that feels helpful, pointing out complementary items that align with her customers' tastes and needs. She creates a seamless, personalized shopping experience that feels more like a spirited adventure than a transaction.
|
|
17
|
+
|
|
18
|
+
The environment she fosters is informal and approachable, with a focus on efficiency while maintaining a welcoming and entertaining communication style. With Vivienne's help, every visit to CLI V3 Test is transformed into a vibrant journey of discovery and delight.`,
|
|
19
|
+
welcomeMessage: "Hello! How can I help you today?",
|
|
20
|
+
skills: [ userSkill, productSkill, basketSkill ],
|
|
21
|
+
webhooks: [ userEventWebhook ],
|
|
22
|
+
jobs: [ healthCheckJob ],
|
|
23
|
+
preProcessors: [ messageMatchingPreProcessor ],
|
|
24
|
+
postProcessors: [ modifyResponsePostProcessor ]
|
|
124
25
|
});
|
|
125
26
|
|
|
126
|
-
const customDataSkill = new LuaSkill({
|
|
127
|
-
name: "custom-data-skill",
|
|
128
|
-
version: "0.0.1",
|
|
129
|
-
description: "A specific Lua skill with custom data",
|
|
130
|
-
context: "This skill provides various utilities including custom data.",
|
|
131
|
-
tools: [
|
|
132
|
-
new CreateMovieTool(),
|
|
133
|
-
new GetMoviesTool(),
|
|
134
|
-
new GetMovieByIdTool(),
|
|
135
|
-
new UpdateMovieTool(),
|
|
136
|
-
new SearchMoviesTool(),
|
|
137
|
-
new DeleteMovieTool()
|
|
138
|
-
]
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const paymentSkill = new LuaSkill({
|
|
142
|
-
name: "payment-skill",
|
|
143
|
-
version: "0.0.1",
|
|
144
|
-
description: "A specific Lua skill with payments",
|
|
145
|
-
context: "This skill provides various utilities including payments.",
|
|
146
|
-
tools: [
|
|
147
|
-
new CreatePaymentLinkTool()
|
|
148
|
-
]
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Test cases
|
|
152
|
-
const testCases = [
|
|
153
|
-
{ tool: "get_weather", city: "London" },
|
|
154
|
-
{ tool: "get_user_data", userId: "user123" },
|
|
155
|
-
{ tool: "create_post", title: "Test Post", content: "This is a test post content" },
|
|
156
|
-
{ tool: "calculator", operation: "add", a: 5, b: 3 },
|
|
157
|
-
{ tool: "advanced_math", operation: "factorial", numbers: [5] },
|
|
158
|
-
{ tool: "advanced_math", operation: "is_prime", numbers: [17] },
|
|
159
|
-
{ tool: "advanced_math", operation: "fibonacci", numbers: [10] },
|
|
160
|
-
{ tool: "advanced_math", operation: "gcd", numbers: [48, 18] },
|
|
161
|
-
// This should fail - wrong property name
|
|
162
|
-
{ tool: "get_weather", cityLong: "London", apiKey: "123" }
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
const job = new LuaJob({
|
|
166
|
-
description: "Test job",
|
|
167
|
-
context: "Test job context",
|
|
168
|
-
name: "test-job",
|
|
169
|
-
schedule: {
|
|
170
|
-
type: "once",
|
|
171
|
-
executeAt: new Date(Date.now() + 1000).toISOString()
|
|
172
|
-
},
|
|
173
|
-
metadata: {
|
|
174
|
-
test: "test"
|
|
175
|
-
},
|
|
176
|
-
execute: async (job: JobInstance) => {
|
|
177
|
-
console.log("Job executed");
|
|
178
|
-
return { success: true, message: "Job executed successfully" };
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
//create webhook
|
|
183
|
-
const webhook = new LuaWebhook({
|
|
184
|
-
description: "Test webhook",
|
|
185
|
-
context: "Test webhook context",
|
|
186
|
-
name: "test-webhook",
|
|
187
|
-
execute: async (query: any, headers: any, body: any) => {
|
|
188
|
-
console.log("Webhook executed");
|
|
189
|
-
return { success: true, message: "Webhook executed successfully" };
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const newJob = new LuaJob({
|
|
194
|
-
description: "Test job",
|
|
195
|
-
context: "Test job context",
|
|
196
|
-
name: "test-job",
|
|
197
|
-
schedule: {
|
|
198
|
-
type: "once",
|
|
199
|
-
executeAt: new Date(Date.now() + 1000).toISOString()
|
|
200
|
-
},
|
|
201
|
-
execute: async (job: JobInstance) => {
|
|
202
|
-
console.log("Job executed", job);
|
|
203
|
-
const realtimeJob = await Jobs.create({
|
|
204
|
-
name: `realtime-job-new-this-again`,
|
|
205
|
-
description: "Realtime job",
|
|
206
|
-
schedule: {
|
|
207
|
-
type: "once",
|
|
208
|
-
executeAt: new Date(Date.now() + 1000).toISOString()
|
|
209
|
-
},
|
|
210
|
-
execute: async (job: JobInstance) => {
|
|
211
|
-
// console.log("Executing realtime job", job.data);
|
|
212
|
-
console.log("Realtime job metadata", job.metadata);
|
|
213
|
-
console.log("Realtime job user", job.user);
|
|
214
|
-
return { success: true, message: "Realtime job executed successfully" };
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
return { success: true, message: "Job executed successfully" };
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
console.log("Job created:", job);
|
|
223
|
-
|
|
224
|
-
async function runTests() {
|
|
225
|
-
// await seedProducts();
|
|
226
|
-
console.log("🧪 Running tool tests...\n");
|
|
227
|
-
|
|
228
|
-
const user = await User.get();
|
|
229
|
-
console.log("✅ Success:", user);
|
|
230
|
-
const products = await Products.get();
|
|
231
|
-
console.log("✅ Success:", products);
|
|
232
|
-
const orders = await Orders.get();
|
|
233
|
-
console.log("✅ Success:", orders);
|
|
234
|
-
const data = await Data.get("movies");
|
|
235
|
-
console.log("✅ Success:", data);
|
|
236
|
-
const baskets = await Baskets.get();
|
|
237
|
-
console.log("✅ Success:", baskets);
|
|
238
|
-
|
|
239
|
-
for (const [index, testCase] of testCases.entries()) {
|
|
240
|
-
try {
|
|
241
|
-
// console.log(`Test ${index + 1}: ${testCase.tool}`);
|
|
242
|
-
// const resultGeneral = await generalSkill.run(testCase);
|
|
243
|
-
// console.log("✅ Success:", resultGeneral);
|
|
244
|
-
// const resultUserData = await userDataSkill.run(testCase);
|
|
245
|
-
// console.log("✅ Success:", resultUserData);
|
|
246
|
-
// const resultEccomerce = await eccomerceSkill.run(testCase);
|
|
247
|
-
// console.log("✅ Success:", resultEccomerce);
|
|
248
|
-
} catch (error: any) {
|
|
249
|
-
console.log("❌ Error:", error.message);
|
|
250
|
-
}
|
|
251
|
-
console.log(""); // Empty line for readability
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
27
|
|
|
255
28
|
async function main() {
|
|
256
29
|
try {
|
|
257
|
-
|
|
30
|
+
|
|
258
31
|
} catch (error) {
|
|
259
32
|
console.error("💥 Unexpected error:", error);
|
|
260
33
|
process.exit(1);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChatMessage, PostProcessor, UserDataInstance } from "lua-cli";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const modifyResponsePostProcessor = new PostProcessor({
|
|
5
|
+
name: "modify-response",
|
|
6
|
+
description: "Modifies the response to the user",
|
|
7
|
+
context: "Modifies the response to the user",
|
|
8
|
+
execute: async (user: UserDataInstance, message: string, response: string, channel: string) => {
|
|
9
|
+
console.log("Modify response post processor", user, message, response, channel);
|
|
10
|
+
console.log("User data", await user.data);
|
|
11
|
+
console.log("Message", message);
|
|
12
|
+
console.log("Response", response);
|
|
13
|
+
console.log("Channel", channel);
|
|
14
|
+
if (response.includes("test")) {
|
|
15
|
+
return message.toUpperCase();
|
|
16
|
+
}
|
|
17
|
+
return response;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export default modifyResponsePostProcessor;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ChatMessage, PreProcessor, UserDataInstance } from "lua-cli";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const messageMatchingPreProcessor = new PreProcessor({
|
|
5
|
+
name: "message-matching",
|
|
6
|
+
description: "Matches the message to the appropriate skill",
|
|
7
|
+
context: "Matches the message to the appropriate skill",
|
|
8
|
+
execute: async (user: UserDataInstance, messages: ChatMessage[], channel: string) => {
|
|
9
|
+
console.log("Message matching pre processor", user, messages, channel);
|
|
10
|
+
console.log("User data", await user.data);
|
|
11
|
+
console.log("Messages", messages);
|
|
12
|
+
console.log("Channel", channel);
|
|
13
|
+
//check if message type text contains test and return the message
|
|
14
|
+
const testMessage = messages.find((message) => message.type === "text" && message.text.includes("test"));
|
|
15
|
+
if (testMessage) {
|
|
16
|
+
return [{ type: "text", text: "Tell the user that you got their test message and nothing else" }];
|
|
17
|
+
}
|
|
18
|
+
return messages;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export default messageMatchingPreProcessor;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LuaSkill } from "lua-cli";
|
|
2
|
+
import { CreateBasketTool, GetBasketByIdTool, UpdateBasketStatusTool, UpdateBasketMetadataTool, CheckoutBasketTool, GetBasketsTool, ClearBasketTool, RemoveItemFromBasketTool, AddItemToBasketTool } from "./tools/BasketTool";
|
|
3
|
+
|
|
4
|
+
const basketSkill = new LuaSkill({
|
|
5
|
+
name: "basket-skill",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
description: "Basket management skill",
|
|
8
|
+
context: "Basket management skill",
|
|
9
|
+
tools: [new CreateBasketTool(), new GetBasketByIdTool(), new UpdateBasketStatusTool(), new UpdateBasketMetadataTool(), new CheckoutBasketTool(), new GetBasketsTool(), new AddItemToBasketTool(), new RemoveItemFromBasketTool(), new ClearBasketTool()],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export default basketSkill;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LuaSkill } from "lua-cli";
|
|
2
|
+
import { SearchProductsTool, CreateProductTool, UpdateProductTool, GetAllProductsTool, GetProductByIdTool, DeleteProductTool } from "./tools/ProductsTool";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const productSkill = new LuaSkill({
|
|
6
|
+
name: "product-skill",
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
description: "Product management skill",
|
|
9
|
+
context: "Product management skill",
|
|
10
|
+
tools: [new SearchProductsTool(), new CreateProductTool(), new UpdateProductTool(), new GetAllProductsTool(), new GetProductByIdTool(), new DeleteProductTool()],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export default productSkill;
|
|
@@ -58,7 +58,8 @@ export class UpdateProductTool implements LuaTool {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
61
|
-
|
|
61
|
+
const product = await Products.getById(input.product.id);
|
|
62
|
+
return product.update({ ...input.product });
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AI, LuaTool, User, Jobs, JobInstance } from "lua-cli";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export class GetUserDataTool implements LuaTool {
|
|
6
|
+
name = "get_user_data";
|
|
7
|
+
description = "Get the user data for a given user id";
|
|
8
|
+
inputSchema = z.object({ });
|
|
9
|
+
|
|
10
|
+
constructor() {}
|
|
11
|
+
|
|
12
|
+
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
13
|
+
return User.get();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class UpdateUserDataTool implements LuaTool {
|
|
18
|
+
name = "update_user_data";
|
|
19
|
+
description = "Update the user data for a given user id";
|
|
20
|
+
inputSchema = z.object({
|
|
21
|
+
data: z.object({
|
|
22
|
+
name: z.string().optional(),
|
|
23
|
+
age: z.number().optional()
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
constructor() {}
|
|
28
|
+
|
|
29
|
+
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
30
|
+
const user = await User.get(); //get instance of user
|
|
31
|
+
await user.send([{ type: "text", text: "Hello, how are you?" }]);
|
|
32
|
+
return await user.update(input.data);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class WritePoemTool implements LuaTool {
|
|
37
|
+
name = "write_poem";
|
|
38
|
+
description = "Write a poem about a given topic";
|
|
39
|
+
inputSchema = z.object({
|
|
40
|
+
topic: z.string()
|
|
41
|
+
});
|
|
42
|
+
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
43
|
+
return await AI.generate("Write a poem about the following topic:", [{ type: "text", text: input.topic }]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class CreateInlineJobTool implements LuaTool {
|
|
48
|
+
name = "create-job-to-notify-user";
|
|
49
|
+
description = "Create a new job to notify the user";
|
|
50
|
+
inputSchema = z.object({
|
|
51
|
+
message: z.string()
|
|
52
|
+
});
|
|
53
|
+
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
54
|
+
//create a job to notify the user in exactly 20 seconds
|
|
55
|
+
const job = await Jobs.create({
|
|
56
|
+
name: "notify-user-new",
|
|
57
|
+
description: "Notify the user",
|
|
58
|
+
schedule: {
|
|
59
|
+
type: "once",
|
|
60
|
+
executeAt: new Date(Date.now() + 0)
|
|
61
|
+
},
|
|
62
|
+
metadata: {
|
|
63
|
+
message: input.message
|
|
64
|
+
},
|
|
65
|
+
execute: async (jobInstance: JobInstance) => {
|
|
66
|
+
const user = await jobInstance.user();
|
|
67
|
+
const metadata = jobInstance.metadata; //we do this to access runtime variables in the job when the job is executed
|
|
68
|
+
console.log("Metadata", metadata);
|
|
69
|
+
await user.send([{ type: "text", text: metadata.message }]);
|
|
70
|
+
return { success: true, message: "User notified" };
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return { success: true, job: job };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LuaSkill } from "lua-cli";
|
|
2
|
+
import { CreateInlineJobTool, GetUserDataTool, UpdateUserDataTool, WritePoemTool } from "./tools/UserDataTool";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const userSkill = new LuaSkill({
|
|
6
|
+
name: "user-skill",
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
description: "User management skill",
|
|
9
|
+
context: "User management skill",
|
|
10
|
+
tools: [new GetUserDataTool(), new UpdateUserDataTool(), new WritePoemTool(), new CreateInlineJobTool()],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export default userSkill;
|
package/template/src/seed.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import fetch from "node-fetch";
|
|
2
|
-
import OpenAI from "openai";
|
|
3
|
-
import { Pinecone } from "@pinecone-database/pinecone";
|
|
4
|
-
import { env } from "lua-cli/skill";
|
|
5
|
-
|
|
6
|
-
const openai = new OpenAI({ apiKey: env("OPENAI_API_KEY") || "" });
|
|
7
|
-
const pinecone = new Pinecone({ apiKey: env("PINECONE_API_KEY") || "" });
|
|
8
|
-
const indexName = "products-demo";
|
|
9
|
-
|
|
10
|
-
async function embed(text: string) {
|
|
11
|
-
const res = await openai.embeddings.create({
|
|
12
|
-
model: "text-embedding-3-small",
|
|
13
|
-
input: text,
|
|
14
|
-
});
|
|
15
|
-
return res.data[0].embedding;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default async function seedProducts() {
|
|
19
|
-
const index = pinecone.Index(indexName);
|
|
20
|
-
|
|
21
|
-
// Example: Fake Store API
|
|
22
|
-
const response = await fetch("https://fakestoreapi.com/products");
|
|
23
|
-
const products = await response.json() as any[];
|
|
24
|
-
|
|
25
|
-
const vectors = await Promise.all(
|
|
26
|
-
products.map(async (product) => {
|
|
27
|
-
const embedding = await embed(`${product.title}. ${product.description}`);
|
|
28
|
-
return {
|
|
29
|
-
id: product.id.toString(),
|
|
30
|
-
values: embedding,
|
|
31
|
-
metadata: {
|
|
32
|
-
title: product.title,
|
|
33
|
-
description: product.description,
|
|
34
|
-
category: product.category,
|
|
35
|
-
price: product.price,
|
|
36
|
-
image: product.image,
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
})
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
await index.upsert(vectors);
|
|
43
|
-
console.log("Dummy products inserted!");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
seedProducts().catch(console.error);
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { LuaTool, User } from "lua-cli";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class GetUserDataTool implements LuaTool {
|
|
6
|
-
name = "get_user_data";
|
|
7
|
-
description = "Get the user data for a given user id";
|
|
8
|
-
inputSchema = z.object({ });
|
|
9
|
-
|
|
10
|
-
constructor() {}
|
|
11
|
-
|
|
12
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
13
|
-
return User.get();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class UpdateUserDataTool implements LuaTool {
|
|
18
|
-
name = "update_user_data";
|
|
19
|
-
description = "Update the user data for a given user id";
|
|
20
|
-
inputSchema = z.object({
|
|
21
|
-
data: z.object({
|
|
22
|
-
name: z.string().optional(),
|
|
23
|
-
age: z.number().optional()
|
|
24
|
-
})
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
constructor() {}
|
|
28
|
-
|
|
29
|
-
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
30
|
-
const user = await User.get(); //get instance of user
|
|
31
|
-
return await user.update(input.data);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|