lua-cli 3.0.0-alpha.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +850 -0
  2. package/dist/api/chat.api.service.d.ts +8 -0
  3. package/dist/api/chat.api.service.js +55 -0
  4. package/dist/api/products.api.service.d.ts +2 -1
  5. package/dist/api/products.api.service.js +11 -10
  6. package/dist/api-exports.d.ts +1 -1
  7. package/dist/api-exports.js +6 -1
  8. package/dist/commands/chat.js +39 -34
  9. package/dist/commands/init.js +10 -2
  10. package/dist/index.js +2 -2
  11. package/dist/interfaces/message.d.ts +2 -2
  12. package/dist/utils/agent-management.d.ts +1 -1
  13. package/dist/utils/agent-management.js +5 -3
  14. package/dist/utils/init-helpers.d.ts +10 -1
  15. package/dist/utils/init-helpers.js +44 -1
  16. package/dist/utils/pre-bundle-jobs.js +9 -9
  17. package/dist/utils/sandbox.js +1 -2
  18. package/package.json +3 -3
  19. package/template/QUICKSTART.md +693 -191
  20. package/template/README.md +673 -802
  21. package/template/lua.skill.yaml +6 -28
  22. package/template/package.json +1 -1
  23. package/template/src/index.ts +18 -252
  24. package/template/src/postprocessors/modifyResponse.ts +21 -0
  25. package/template/src/preprocessors/messageMatching.ts +22 -0
  26. package/template/src/skills/basket.skill.ts +12 -0
  27. package/template/src/skills/product.skill.ts +13 -0
  28. package/template/src/{tools → skills/tools}/ProductsTool.ts +2 -1
  29. package/template/src/skills/tools/UserDataTool.ts +75 -0
  30. package/template/src/skills/user.skill.ts +13 -0
  31. package/template/src/seed.ts +0 -46
  32. package/template/src/tools/UserDataTool.ts +0 -33
  33. /package/template/src/{tools → skills/tools}/BasketTool.ts +0 -0
  34. /package/template/src/{tools → skills/tools}/CreateInlineJob.ts +0 -0
  35. /package/template/src/{tools → skills/tools}/CreatePostTool.ts +0 -0
  36. /package/template/src/{tools → skills/tools}/CustomDataTool.ts +0 -0
  37. /package/template/src/{tools → skills/tools}/GameScoreTrackerTool.ts +0 -0
  38. /package/template/src/{tools → skills/tools}/GetWeatherTool.ts +0 -0
  39. /package/template/src/{tools → skills/tools}/OrderTool.ts +0 -0
  40. /package/template/src/{tools → skills/tools}/PaymentTool.ts +0 -0
  41. /package/template/src/{tools → skills/tools}/SmartBasketTool.ts +0 -0
@@ -1,38 +1,16 @@
1
1
  agent:
2
2
  agentId: baseAgent_agent_1760922427216_fk9w0ezhh
3
3
  orgId: 026cc41b-e013-4474-9b65-5a15f8881f92
4
- persona: >
5
- Meet Vivienne, the vibrant and dynamic assistant at V3 Test, a lively retail and consumer goods store that
6
- specializes in bringing a splash of color and excitement to everyday life. Vivienne embodies the brand's energetic
7
- and fun personality, always ready to engage with customers in a way that makes shopping an enjoyable and memorable
8
- experience. Her role is to be the friendly face and knowledgeable guide for anyone who steps into the store, whether
9
- they're looking for the latest fashion trends or a unique gift for a loved one.
4
+ persona: |
5
+ Meet Vivienne, the vibrant and dynamic assistant at V3 Test, a lively retail and consumer goods store that specializes in bringing a splash of color and excitement to everyday life. Vivienne embodies the brand's energetic and fun personality, always ready to engage with customers in a way that makes shopping an enjoyable and memorable experience. Her role is to be the friendly face and knowledgeable guide for anyone who steps into the store, whether they're looking for the latest fashion trends or a unique gift for a loved one.
10
6
 
7
+ V3 Test is all about creating a joyful and spirited shopping environment, and Vivienne is the perfect personification of this ethos. She is lively, approachable, and always ready with a smile, making every interaction feel like a conversation with a good friend. Her voice is warm and enthusiastic, with a hint of playfulness that puts customers at ease and encourages them to explore the store's offerings.
11
8
 
12
- V3 Test is all about creating a joyful and spirited shopping environment, and Vivienne is the perfect
13
- personification of this ethos. She is lively, approachable, and always ready with a smile, making every interaction
14
- feel like a conversation with a good friend. Her voice is warm and enthusiastic, with a hint of playfulness that
15
- puts customers at ease and encourages them to explore the store's offerings.
9
+ Vivienne's target customers are diverse, ranging from young adults in their twenties who are fashion-forward and tech-savvy, to busy parents looking for quality products that add a touch of fun to their family life. She understands the fast-paced lifestyle of her customers and is adept at tailoring her approach to meet their individual needs, whether they're in a hurry or have time to browse.
16
10
 
11
+ Her sales approach is consultative and friendly, focusing on understanding the customer's needs and preferences before suggesting products that align with their style and personality. Vivienne is confident in her recommendations, always ready to upsell when appropriate, but never pushy. She believes in building relationships with customers, ensuring they leave the store not only with products they love but also with a positive impression of the brand.
17
12
 
18
- Vivienne's target customers are diverse, ranging from young adults in their twenties who are fashion-forward and
19
- tech-savvy, to busy parents looking for quality products that add a touch of fun to their family life. She
20
- understands the fast-paced lifestyle of her customers and is adept at tailoring her approach to meet their
21
- individual needs, whether they're in a hurry or have time to browse.
22
-
23
-
24
- Her sales approach is consultative and friendly, focusing on understanding the customer's needs and preferences
25
- before suggesting products that align with their style and personality. Vivienne is confident in her
26
- recommendations, always ready to upsell when appropriate, but never pushy. She believes in building relationships
27
- with customers, ensuring they leave the store not only with products they love but also with a positive impression
28
- of the brand.
29
-
30
-
31
- In terms of communication style, Vivienne strikes a perfect balance between being informal and efficient. She is
32
- warm and engaging, making customers feel valued and appreciated, while also being mindful of their time. Her
33
- interactions are peppered with humor and light-hearted banter, creating a shopping experience that is both enjoyable
34
- and efficient. Whether it's through in-person interactions or digital communication, Vivienne ensures that every
35
- customer feels like a part of the V3 Test family.
13
+ In terms of communication style, Vivienne strikes a perfect balance between being informal and efficient. She is warm and engaging, making customers feel valued and appreciated, while also being mindful of their time. Her interactions are peppered with humor and light-hearted banter, creating a shopping experience that is both enjoyable and efficient. Whether it's through in-person interactions or digital communication, Vivienne ensures that every customer feels like a part of the V3 Test family.
36
14
  welcomeMessage: Hi, I am your AI assistant. How can I help you today?
37
15
  skills:
38
16
  - name: general-skill
@@ -20,7 +20,7 @@
20
20
  "inquirer": "^12.9.6",
21
21
  "stripe": "^17.5.0",
22
22
  "js-yaml": "^4.1.0",
23
- "lua-cli": "file:..",
23
+ "lua-cli": "^3.0.0",
24
24
  "openai": "^5.23.0",
25
25
  "uuid": "^13.0.0",
26
26
  "zod": "^3.24.1"
@@ -1,260 +1,26 @@
1
- import { LuaSkill, User, Products, Orders, Data, Baskets, LuaJob, JobInstance, LuaWebhook, Jobs } from "lua-cli";
2
- import GetWeatherTool from "./tools/GetWeatherTool";
3
- import { GetUserDataTool, UpdateUserDataTool } from "./tools/UserDataTool";
4
- import CreatePostTool from "./tools/CreatePostTool";
5
- import { SearchProductsTool, CreateProductTool, UpdateProductTool, GetAllProductsTool, GetProductByIdTool, DeleteProductTool } from "./tools/ProductsTool";
6
- import CreatePaymentLinkTool from "./tools/PaymentTool";
7
- import { CreateBasketTool, GetBasketsTool, AddItemToBasketTool, RemoveItemFromBasketTool, ClearBasketTool, UpdateBasketStatusTool, UpdateBasketMetadataTool, CheckoutBasketTool, GetBasketByIdTool } from "./tools/BasketTool";
8
- import { CreateOrderTool, UpdateOrderStatusTool, GetOrderByIdTool, GetUserOrdersTool } from "./tools/OrderTool";
9
- import { CreateMovieTool, GetMoviesTool, GetMovieByIdTool, UpdateMovieTool, SearchMoviesTool, DeleteMovieTool } from "./tools/CustomDataTool";
10
- import CreateInlineJobTool from "./tools/CreateInlineJob";
11
- import { v4 } from 'uuid';
12
-
13
- // ============================================================================
14
- // WEBHOOK EXAMPLES (Uncomment to enable)
15
- // ============================================================================
16
- // Webhooks receive HTTP requests from external systems
17
- // See: WEBHOOK_JOB_EXAMPLES.md for detailed explanations
18
-
19
- // import userEventWebhook from "./webhooks/UserEventWebhook";
20
- // import paymentWebhook from "./webhooks/PaymentWebhook";
21
-
22
- // ============================================================================
23
- // JOB EXAMPLES (Uncomment to enable)
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 } 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: ``,
12
+ persona: ``,
13
+ skills: [ userSkill, productSkill, basketSkill ],
14
+ webhooks: [ userEventWebhook ],
15
+ jobs: [ healthCheckJob ],
16
+ preProcessors: [ messageMatchingPreProcessor ],
17
+ postProcessors: [ modifyResponsePostProcessor ]
124
18
  });
125
19
 
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
20
 
255
21
  async function main() {
256
22
  try {
257
- await runTests();
23
+
258
24
  } catch (error) {
259
25
  console.error("💥 Unexpected error:", error);
260
26
  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
- return Products.update({ ...input.product }, input.product.id);
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;
@@ -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
- }