create-message-kit 1.2.11 → 1.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. package/index.js +9 -4
  2. package/package.json +1 -1
  3. package/templates/{agent → ens}/.cursorrules +68 -3
  4. package/templates/{agent → ens}/package.json +1 -1
  5. package/templates/{agent → ens}/src/prompt.ts +1 -1
  6. package/templates/{agent → ens}/src/skills/check.ts +1 -1
  7. package/templates/{agent → ens}/src/skills/cool.ts +1 -1
  8. package/templates/{agent → ens}/src/skills/info.ts +1 -1
  9. package/templates/{agent → ens}/src/skills/pay.ts +1 -1
  10. package/templates/{agent → ens}/src/skills/register.ts +1 -1
  11. package/templates/{agent → ens}/src/skills/renew.ts +1 -1
  12. package/templates/{agent → ens}/src/skills/reset.ts +1 -2
  13. package/templates/{experimental → simple}/.cursorrules +68 -3
  14. package/templates/{gpt → simple}/package.json +1 -1
  15. package/templates/experimental/.env.example +0 -6
  16. package/templates/experimental/package.json +0 -26
  17. package/templates/experimental/src/index.ts +0 -52
  18. package/templates/experimental/src/lib/alchemy.ts +0 -31
  19. package/templates/experimental/src/lib/minilog.ts +0 -26
  20. package/templates/experimental/src/lib/usdc.ts +0 -99
  21. package/templates/experimental/src/lib/xmtp.ts +0 -139
  22. package/templates/experimental/src/prompt.ts +0 -24
  23. package/templates/experimental/src/skills/broadcast.ts +0 -39
  24. package/templates/experimental/src/skills/cash.ts +0 -114
  25. package/templates/experimental/src/skills/gated.ts +0 -89
  26. package/templates/experimental/src/skills/todo.ts +0 -80
  27. package/templates/experimental/src/skills/token.ts +0 -57
  28. package/templates/experimental/src/skills/wordle.ts +0 -97
  29. package/templates/gpt/.cursorrules +0 -225
  30. package/templates/gpt/.yarnrc.yml +0 -4
  31. /package/templates/{agent → ens}/.env.example +0 -0
  32. /package/templates/{agent → ens}/.yarnrc.yml +0 -0
  33. /package/templates/{agent → ens}/src/index.ts +0 -0
  34. /package/templates/{gpt → simple}/.env.example +0 -0
  35. /package/templates/{experimental → simple}/.yarnrc.yml +0 -0
  36. /package/templates/{gpt → simple}/src/index.ts +0 -0
  37. /package/templates/{gpt → simple}/src/prompt.ts +0 -0
@@ -1,139 +0,0 @@
1
- import { isOnXMTP, V3Client, V2Client } from "@xmtp/message-kit";
2
-
3
- export async function createGroup(
4
- client: V3Client,
5
- senderAddress: string,
6
- clientAddress: string,
7
- ) {
8
- try {
9
- let senderInboxId = "";
10
- await client.conversations.sync();
11
- const conversations = await client.conversations.list();
12
- console.log("Conversations", conversations.length);
13
- const group = await client?.conversations.newGroup([
14
- senderAddress,
15
- clientAddress,
16
- ]);
17
- console.log("Group created", group?.id);
18
- const members = await group.members();
19
- const senderMember = members.find((member) =>
20
- member.accountAddresses.includes(senderAddress.toLowerCase()),
21
- );
22
- if (senderMember) {
23
- senderInboxId = senderMember.inboxId;
24
- console.log("Sender's inboxId:", senderInboxId);
25
- } else {
26
- console.log("Sender not found in members list");
27
- }
28
- await group.addSuperAdmin(senderInboxId);
29
- console.log(
30
- "Sender is superAdmin",
31
- await group.isSuperAdmin(senderInboxId),
32
- );
33
- await group.send(`Welcome to the new group!`);
34
- await group.send(`You are now the admin of this group as well as the bot`);
35
- return group;
36
- } catch (error) {
37
- console.log("Error creating group", error);
38
- return null;
39
- }
40
- }
41
-
42
- export async function removeFromGroup(
43
- groupId: string,
44
- client: V3Client,
45
- v2client: V2Client,
46
- senderAddress: string,
47
- ): Promise<{ code: number; message: string }> {
48
- try {
49
- let lowerAddress = senderAddress.toLowerCase();
50
- const { v2, v3 } = await isOnXMTP(client, v2client, lowerAddress);
51
- console.warn("Checking if on XMTP: v2", v2, "v3", v3);
52
- if (!v3)
53
- return {
54
- code: 400,
55
- message: "You don't seem to have a v3 identity ",
56
- };
57
- const conversation =
58
- await client.conversations.getConversationById(groupId);
59
- console.warn("removing from group", conversation?.id);
60
- await conversation?.sync();
61
- await conversation?.removeMembers([lowerAddress]);
62
- console.warn("Removed member from group");
63
- await conversation?.sync();
64
- const members = await conversation?.members();
65
- console.warn("Number of members", members?.length);
66
-
67
- let wasRemoved = true;
68
- if (members) {
69
- for (const member of members) {
70
- let lowerMemberAddress = member.accountAddresses[0].toLowerCase();
71
- if (lowerMemberAddress === lowerAddress) {
72
- wasRemoved = false;
73
- break;
74
- }
75
- }
76
- }
77
- return {
78
- code: wasRemoved ? 200 : 400,
79
- message: wasRemoved
80
- ? "You have been removed from the group"
81
- : "Failed to remove from group",
82
- };
83
- } catch (error) {
84
- console.log("Error removing from group", error);
85
- return {
86
- code: 400,
87
- message: "Failed to remove from group",
88
- };
89
- }
90
- }
91
- export async function addToGroup(
92
- groupId: string,
93
- client: V3Client,
94
- address: string,
95
- asAdmin: boolean = false,
96
- ): Promise<{ code: number; message: string }> {
97
- try {
98
- let lowerAddress = address.toLowerCase();
99
- const { v2, v3 } = await isOnXMTP(client, null, lowerAddress);
100
- if (!v3)
101
- return {
102
- code: 400,
103
- message: "You don't seem to have a v3 identity ",
104
- };
105
- const group = await client.conversations.getConversationById(groupId);
106
- console.warn("Adding to group", group?.id);
107
- await group?.sync();
108
- await group?.addMembers([lowerAddress]);
109
- console.warn("Added member to group");
110
- await group?.sync();
111
- if (asAdmin) {
112
- await group?.addSuperAdmin(lowerAddress);
113
- }
114
- const members = await group?.members();
115
- console.warn("Number of members", members?.length);
116
-
117
- if (members) {
118
- for (const member of members) {
119
- let lowerMemberAddress = member.accountAddresses[0].toLowerCase();
120
- if (lowerMemberAddress === lowerAddress) {
121
- console.warn("Member exists", lowerMemberAddress);
122
- return {
123
- code: 200,
124
- message: "You have been added to the group",
125
- };
126
- }
127
- }
128
- }
129
- return {
130
- code: 400,
131
- message: "Failed to add to group",
132
- };
133
- } catch (error) {
134
- return {
135
- code: 400,
136
- message: "Failed to add to group",
137
- };
138
- }
139
- }
@@ -1,24 +0,0 @@
1
- export const systemPrompt = `
2
- Your are helpful and playful experimental agent called {agent_name} that lives inside a messaging app called Converse.
3
-
4
- {rules}
5
-
6
- {user_context}
7
-
8
- {skills}
9
-
10
- ## Scenarios
11
- 1. Missing commands in responses
12
- **Issue**: Sometimes responses are sent without the required command.
13
- **Example**:
14
- Incorrect:
15
- > "Looks like vitalik.eth is registered! What about these cool alternatives?"
16
- Correct:
17
- > "Looks like vitalik.eth is registered! What about these cool alternatives?
18
- > /cool vitalik.eth"
19
-
20
- Incorrect:
21
- > Here is a summary of your TODOs. I will now send it via email.
22
- Correct:
23
- > /todo
24
- `;
@@ -1,39 +0,0 @@
1
- import { XMTPContext, Skill } from "@xmtp/message-kit";
2
-
3
- export const broadcast: Skill[] = [
4
- {
5
- skill: "/send",
6
- adminOnly: true,
7
- handler: handler,
8
- examples: ["/send Hello everyone, the event is starting now!"],
9
- description: "Send updates to all subscribers.",
10
- params: {
11
- message: {
12
- type: "prompt",
13
- },
14
- },
15
- },
16
- ];
17
-
18
- async function handler(context: XMTPContext) {
19
- const {
20
- message: {
21
- content: {
22
- params: { message },
23
- },
24
- },
25
- } = context;
26
-
27
- const fakeSubscribers = ["0x93E2fc3e99dFb1238eB9e0eF2580EFC5809C7204"];
28
- await context.send("This is how your message will look like:");
29
- await context.send(message);
30
- const emailResponse = await context.awaitResponse(
31
- "Are you sure you want to send this broadcast?\nType 'yes' to confirm.",
32
- ["yes", "no"],
33
- );
34
- if (emailResponse === "yes") {
35
- await context.send("Sending broadcast...");
36
- await context.sendTo(message, fakeSubscribers);
37
- await context.send("Broadcast sent!");
38
- }
39
- }
@@ -1,114 +0,0 @@
1
- import { XMTPContext } from "@xmtp/message-kit";
2
- import type { Skill } from "@xmtp/message-kit";
3
- import { USDCWallet } from "../lib/usdc.js";
4
-
5
- export const cash: Skill[] = [
6
- {
7
- skill: "/balance",
8
- handler: balanceHandler,
9
- examples: ["/balance"],
10
- params: {},
11
- description: "Check your balance.",
12
- },
13
- {
14
- skill: "/fund [amount]",
15
- handler: fundHandler,
16
- examples: ["/fund 1", "/fund 10"],
17
- params: {
18
- amount: {
19
- type: "number",
20
- default: "",
21
- },
22
- },
23
- description: "Fund your wallet. Returns a url to fund your wallet.",
24
- },
25
- {
26
- skill: "/transfer [address] [amount]",
27
- handler: transferHandler,
28
- examples: ["/transfer 0x40f08f0f853d1c42c61815652b7ccd5a50f0be09 1"],
29
- params: {},
30
- description: "Transfer USDC to another address.",
31
- },
32
- ];
33
-
34
- async function balanceHandler(context: XMTPContext) {
35
- const {
36
- message: { sender },
37
- } = context;
38
- const usdcWallet = new USDCWallet(sender.address);
39
- const { usdc } = await usdcWallet.checkBalances();
40
- await context.send(
41
- `Your balance is ${usdc} USDC. let me know if you want check again or to fund your wallet.`,
42
- );
43
- }
44
-
45
- async function fundHandler(context: XMTPContext) {
46
- try {
47
- const {
48
- message: {
49
- sender,
50
- content: {
51
- params: { amount },
52
- },
53
- },
54
- } = context;
55
- const usdcWallet = new USDCWallet(sender.address);
56
- const { usdc } = await usdcWallet.checkBalances();
57
- const MAX_USDC = 10;
58
-
59
- if (usdc >= MAX_USDC) {
60
- await context.send(`Your balance is maxed out at ${MAX_USDC} USDC.`);
61
- return;
62
- }
63
-
64
- const remainingLimit = MAX_USDC - usdc;
65
- let fundAmount: number;
66
-
67
- if (!amount) {
68
- const options = Array.from(
69
- { length: Math.floor(remainingLimit) },
70
- (_, i) => (i + 1).toString(),
71
- );
72
- const response = await context.awaitResponse(
73
- `Please specify the amount of USDC to prefund (1 to ${remainingLimit}):`,
74
- options,
75
- );
76
- fundAmount = parseInt(response);
77
- } else {
78
- fundAmount = parseInt(amount);
79
- }
80
-
81
- if (isNaN(fundAmount) || fundAmount <= 0 || fundAmount > remainingLimit) {
82
- await context.send(
83
- `Invalid amount. Please specify a value between 1 and ${remainingLimit} USDC.`,
84
- );
85
- return;
86
- }
87
-
88
- await context.requestPayment(fundAmount, "USDC", usdcWallet.agentAddress);
89
- await context.send(
90
- "After funding, let me know so I can check your balance.",
91
- );
92
- } catch (error) {
93
- await context.send(
94
- "An error occurred while processing your request. Please try again.",
95
- );
96
- }
97
- }
98
-
99
- async function transferHandler(context: XMTPContext) {
100
- const {
101
- message: {
102
- sender,
103
- content: {
104
- params: { address, amount },
105
- },
106
- },
107
- } = context;
108
- const usdcWallet = new USDCWallet(sender.address);
109
- if (amount > 10) {
110
- await context.send("You can only transfer up to 10 USDC at a time.");
111
- return;
112
- }
113
- await usdcWallet.transferUsdc(address, amount);
114
- }
@@ -1,89 +0,0 @@
1
- import { XMTPContext, Skill, V3Client } from "@xmtp/message-kit";
2
- import { createGroup } from "../lib/xmtp.js";
3
- import express from "express";
4
- import { checkNft } from "../lib/alchemy.js";
5
- import { addToGroup } from "../lib/xmtp.js";
6
- export const gated: Skill[] = [
7
- {
8
- skill: "/create",
9
- examples: ["/create"],
10
- handler: handler,
11
- adminOnly: true,
12
- params: {},
13
- description: "Create a new group.",
14
- },
15
- ];
16
-
17
- async function handler(context: XMTPContext) {
18
- const {
19
- message: {
20
- sender,
21
- content: { skill },
22
- },
23
- client,
24
- } = context;
25
-
26
- if (skill === "create") {
27
- const group = await createGroup(
28
- client,
29
- sender.address,
30
- client.accountAddress,
31
- );
32
-
33
- await context.send(
34
- `Group created!\n- ID: ${group?.id}\n- Group Frame URL: https://converse.xyz/group/${group?.id}: \n- This url will deelink to the group inside Converse\n- Once in the other group you can share the invite with your friends.`,
35
- );
36
- return;
37
- } else {
38
- await context.send(
39
- "👋 Welcome to the Gated Bot Group!\nTo get started, type /create to set up a new group. 🚀\nThis example will check if the user has a particular nft and add them to the group if they do.\nOnce your group is created, you'll receive a unique Group ID and URL.\nShare the URL with friends to invite them to join your group!",
40
- );
41
- }
42
- }
43
-
44
- export function startGatedGroupServer(client: V3Client) {
45
- async function addWalletToGroup(
46
- walletAddress: string,
47
- groupId: string,
48
- ): Promise<string> {
49
- const verified = true; //await checkNft(walletAddress, "XMTPeople");
50
- if (!verified) {
51
- console.log("User cant be added to the group");
52
- return "not verified";
53
- } else {
54
- try {
55
- const added = await addToGroup(groupId, client, walletAddress);
56
- if (added.code === 200) {
57
- console.log(`Added wallet address: ${walletAddress} to the group`);
58
- return "success";
59
- } else {
60
- return added.message;
61
- }
62
- } catch (error: any) {
63
- console.log(error.message);
64
- return "error";
65
- }
66
- }
67
- }
68
-
69
- // Endpoint to add wallet address to a group from an external source
70
- const app = express();
71
- app.use(express.json());
72
- app.post("/add-wallet", async (req, res) => {
73
- try {
74
- const { walletAddress, groupId } = req.body;
75
- const result = await addWalletToGroup(walletAddress, groupId);
76
- res.status(200).send(result);
77
- } catch (error: any) {
78
- res.status(400).send(error.message);
79
- }
80
- });
81
- // Start the servfalcheer
82
- const PORT = process.env.PORT || 3000;
83
- const url = process.env.URL || `http://localhost:${PORT}`;
84
- app.listen(PORT, () => {
85
- console.warn(
86
- `Use this endpoint to add a wallet to a group indicated by the groupId\n${url}/add-wallet <body: {walletAddress, groupId}>`,
87
- );
88
- });
89
- }
@@ -1,80 +0,0 @@
1
- import { Resend } from "resend";
2
- import { XMTPContext } from "@xmtp/message-kit";
3
- import type { Skill } from "@xmtp/message-kit";
4
-
5
- const resend = new Resend(process.env.RESEND_API_KEY); // Replace with your Resend API key
6
-
7
- export const todo: Skill[] = [
8
- {
9
- skill: "/todo",
10
- handler: handler,
11
- examples: ["/todo"],
12
- description:
13
- "Summarize your TODOs and send an email with the summary. Receives no parameters.",
14
- params: {},
15
- },
16
- ];
17
-
18
- export async function handler(context: XMTPContext) {
19
- const {
20
- message: {
21
- content: { previousMsg },
22
- },
23
- } = context;
24
-
25
- let email = "";
26
- if (!previousMsg) {
27
- await context.send("You need to do it on a reply.");
28
- return;
29
- }
30
- let intents = 2;
31
- while (intents > 0) {
32
- const emailResponse = await context.awaitResponse(
33
- "Please provide your email address to receive the to-dos summary:",
34
- );
35
- email = emailResponse;
36
-
37
- // Basic email validation
38
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
39
- if (!emailRegex.test(email)) {
40
- await context.send(
41
- "Invalid email format. Please try again with a valid email address.",
42
- );
43
- intents--;
44
- continue;
45
- }
46
- break;
47
- }
48
- if (intents == 0) {
49
- await context.send(
50
- "I couldn't get your email address. Please try again later.",
51
- );
52
- return;
53
- }
54
- try {
55
- let { reply } = await context.textGeneration(
56
- email,
57
- "Make this summary concise and to the point to be sent in an email.\n msg: " +
58
- previousMsg,
59
- "You are an expert at summarizing to-dos. Return in format html and just the content inside the body tag. Dont return `html` or `body` tags",
60
- );
61
- if (typeof reply === "string") {
62
- let content = {
63
- from: "bot@mail.coin-toss.xyz",
64
- to: email,
65
- subject: "Your summary from Converse",
66
- html: `
67
- <h3>Your Converse Summary</h3>
68
- <p>${reply}</p>
69
- `,
70
- };
71
- await resend.emails.send(content);
72
- await context.send(`✅ Summary sent successfully to ${email}`);
73
- } else {
74
- await context.send("❌ Message not found.");
75
- }
76
- } catch (error) {
77
- await context.send("❌ Failed to send email. Please try again later.");
78
- console.error("Error sending email:", error);
79
- }
80
- }
@@ -1,57 +0,0 @@
1
- import { XMTPContext } from "@xmtp/message-kit";
2
- import type { Skill } from "@xmtp/message-kit";
3
-
4
- export const token: Skill[] = [
5
- {
6
- skill: "/token [symbol]",
7
- handler: handler,
8
- examples: ["/token bitcoin", "/token ethereum"],
9
- description: "Get real time price of a any token.",
10
- params: {
11
- symbol: {
12
- type: "string",
13
- },
14
- },
15
- },
16
- ];
17
- export async function handler(context: XMTPContext) {
18
- const {
19
- message: {
20
- content: {
21
- params: { symbol },
22
- },
23
- },
24
- } = context;
25
- const response = await fetch(
26
- `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${symbol}`,
27
- );
28
- if (!response.ok) {
29
- context.send("Token not found");
30
- context.send("try with its full name, instead of btc it would be bitcoin");
31
- return;
32
- }
33
- const data = (await response.json()) as any;
34
- const token = data[0];
35
-
36
- const tokenInfo = {
37
- name: token.name,
38
- symbol: token.symbol.toUpperCase(),
39
- price: token.current_price,
40
- image: token.image,
41
- link: `https://www.coingecko.com/en/coins/${token.id}`,
42
- };
43
-
44
- let frame = {
45
- title: tokenInfo.name,
46
- buttons: [
47
- { content: "Buy", action: "link", target: tokenInfo.link },
48
- {
49
- content: `Price (${tokenInfo.price})`,
50
- action: "link",
51
- target: tokenInfo.link,
52
- },
53
- ],
54
- image: tokenInfo.image,
55
- };
56
- await context.sendCustomFrame(frame);
57
- }
@@ -1,97 +0,0 @@
1
- import { XMTPContext } from "@xmtp/message-kit";
2
- import type { Skill } from "@xmtp/message-kit";
3
-
4
- export const wordle: Skill[] = [
5
- {
6
- skill: "/wordle",
7
- handler: handler,
8
- examples: ["/wordle"],
9
- description: "Play wordle.",
10
- params: {},
11
- },
12
- {
13
- skill: "/arena [word count] [audience size]",
14
- examples: ["/arena 3 15"],
15
- handler: handler,
16
- description: "Play arena.",
17
- params: {
18
- wordCount: {
19
- default: 3,
20
- type: "number",
21
- },
22
- audienceSize: {
23
- default: 15,
24
- type: "number",
25
- },
26
- },
27
- },
28
- ];
29
-
30
- async function handler(context: XMTPContext) {
31
- const {
32
- message: {
33
- content: { skill },
34
- },
35
- } = context;
36
-
37
- if (skill === "arena") {
38
- await handleArenaMessage(context);
39
- } else if (skill === "wordle") {
40
- await context.send("https://framedl.xyz");
41
- } else if (skill === "help") {
42
- await context.send(
43
- "For using this bot you can use the following commands:\n\n" +
44
- "/wordle, @wordle, 🔍, 🔎 - To start the game\n" +
45
- "/arena <word count> <audience size> - To start the arena game\n" +
46
- "/help - To see commands",
47
- );
48
- }
49
- }
50
- async function handleArenaMessage(context: XMTPContext) {
51
- const {
52
- message: {
53
- content: { text },
54
- },
55
- members,
56
- } = context;
57
-
58
- const apiKey = process.env.FRAMEDL_API_KEY;
59
- if (!apiKey) {
60
- console.log("FRAMEDL_API_KEY is not set");
61
- await context.send("https://www.framedl.xyz/games/arena/create");
62
- return;
63
- }
64
- const participantCount = members && members.length ? members.length - 1 : 0;
65
- const args = text?.split(" ") ?? [];
66
- const wordCountArg = args[1] ? parseInt(args[1], 10) : 3;
67
- const audienceSizeArg = args[2] ? parseInt(args[2], 10) : participantCount;
68
- if (isNaN(wordCountArg) || isNaN(audienceSizeArg)) {
69
- await context.send(
70
- "usage: /arena <word count> <audience size>\n\n" +
71
- "word count: number of words in the arena (default: 3, min: 1, max: 9)\n" +
72
- "audience size: number of audience members (default: number of participants excluding wordle bot, min: 1, max: 15)",
73
- );
74
- return;
75
- }
76
-
77
- const audienceSize = Math.max(1, Math.min(15, audienceSizeArg));
78
- const wordCount = Math.max(1, Math.min(9, wordCountArg));
79
-
80
- try {
81
- const response = await fetch("https://www.framedl.xyz/api/arenas", {
82
- method: "POST",
83
- body: JSON.stringify({ wordCount, audienceSize }),
84
- headers: {
85
- "Content-Type": "application/json",
86
- "x-framedl-api-key": apiKey,
87
- },
88
- });
89
-
90
- const data = (await response.json()) as { arenaUrl: string };
91
-
92
- await context.send(data.arenaUrl);
93
- } catch (error) {
94
- console.error(error);
95
- await context.send("https://www.framedl.xyz/games/arena/create");
96
- }
97
- }