create-message-kit 1.0.17 → 1.0.20

Sign up to get free protection for your applications and to get access to all the features.
package/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { program } from "commander";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { intro, log, outro, text, select } from "@clack/prompts";
5
+ import { log, outro, text, select } from "@clack/prompts";
6
6
  import { default as fs } from "fs-extra";
7
7
  import { isCancel } from "@clack/prompts";
8
8
  import pc from "picocolors";
@@ -19,16 +19,17 @@ program
19
19
  .name("byob")
20
20
  .description("CLI to initialize projects")
21
21
  .action(async () => {
22
- log.message(`\x1b[38;2;250;105;119m\
23
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
24
-
25
- ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗████████╗
26
- ████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ██╔════╝██║ ██╔╝██║╚══██╔══╝
27
- ██╔████╔██║█████╗ ███████╗███████╗███████║██║ ███╗█████╗ █████╔╝ ██║ ██║
28
- ██║╚██╔╝██║██╔══╝ ╚════██║╚════██║██╔══██║██║ ██║██╔══╝ ██╔═██╗ ██║ ██║
29
- ██║ ╚═╝ ██║███████╗███████║███████║██║ ██║╚██████╔╝███████╗██║ ██╗██║ ██║
30
- ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
31
- Powered by XMTP \x1b[0m`);
22
+ log.info(pc.cyan(`Welcome to MessageKit v${version}!`));
23
+ const coolLogo = `
24
+ ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗████████╗
25
+ ████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ██╔════╝██║ ██╔╝██║╚══██╔══╝
26
+ ██╔████╔██║█████╗ ███████╗███████╗███████║██║ ███╗█████╗ █████╔╝ ██║ ██║
27
+ ██║╚██╔╝██║██╔══╝ ╚════██║╚════██║██╔══██║██║ ██║██╔══╝ ██╔═██╗ ██║ ██║
28
+ ██║ ╚═╝ ██║███████╗███████║███████║██║ ██║╚██████╔╝███████╗██║ ██╗██║ ██║
29
+ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
30
+ Powered by XMTP`;
31
+
32
+ log.info(pc.cyan(coolLogo));
32
33
 
33
34
  const { templateType, displayName, destDir } = await gatherProjectInfo();
34
35
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-message-kit",
3
- "version": "1.0.17",
3
+ "version": "1.0.20",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -4,9 +4,12 @@ import { textGeneration } from "../lib/openai.js";
4
4
  import { processResponseWithSkill } from "../lib/openai.js";
5
5
  import { isAddress } from "viem";
6
6
  import { ens_agent_prompt } from "../prompt.js";
7
- import { frameUrl, ensUrl, baseTxUrl } from "../index.js";
8
7
  import { clearChatHistories } from "../lib/openai.js";
9
8
 
9
+ export const frameUrl = "https://ens.steer.fun/";
10
+ export const ensUrl = "https://app.ens.domains/";
11
+ export const baseTxUrl = "https://base-tx-frame.vercel.app";
12
+
10
13
  export async function handleEns(context: HandlerContext) {
11
14
  const {
12
15
  message: {
@@ -108,7 +111,7 @@ export async function handleEns(context: HandlerContext) {
108
111
 
109
112
  const data = await getUserInfo(domain);
110
113
  if (!data?.address) {
111
- let message = `Looks like ${domain} is available! Do you want to register it? ${ensUrl}${domain} or would you like to see some cool alternatives?`;
114
+ let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
112
115
  return {
113
116
  code: 200,
114
117
  message,
@@ -169,13 +172,10 @@ export async function ensAgent(context: HandlerContext) {
169
172
  console.log("User info not found");
170
173
  return;
171
174
  }
172
- const { ensDomain, converseUsername } = userInfo;
173
-
174
175
  const { reply } = await textGeneration(
175
176
  sender.address,
176
177
  userPrompt,
177
- await ens_agent_prompt(sender.address, ensDomain, converseUsername),
178
- group !== undefined,
178
+ await ens_agent_prompt(userInfo),
179
179
  );
180
180
  await processResponseWithSkill(sender.address, reply, context);
181
181
  } catch (error) {
@@ -1,14 +1,10 @@
1
1
  import { run, HandlerContext } from "@xmtp/message-kit";
2
2
  import { ensAgent } from "./handler/ens.js";
3
3
 
4
- export const frameUrl = "https://ens.steer.fun/";
5
- export const ensUrl = "https://app.ens.domains/";
6
- export const baseTxUrl = "https://base-tx-frame.vercel.app";
7
-
8
4
  run(async (context: HandlerContext) => {
9
- const { group, message } = context;
10
5
  /*All the commands are handled through the commands file*/
11
6
  /* If its just text, it will be handled by the ensAgent*/
12
7
  /* If its a group message, it will be handled by the groupAgent*/
13
- await ensAgent(context);
8
+
9
+ ensAgent(context);
14
10
  });
@@ -14,7 +14,6 @@ export async function textGeneration(
14
14
  address: string,
15
15
  userPrompt: string,
16
16
  systemPrompt: string,
17
- isGroup: boolean = false,
18
17
  ) {
19
18
  let messages = chatHistories[address] || [];
20
19
  if (messages.length === 0) {
@@ -38,7 +37,8 @@ export async function textGeneration(
38
37
  content: reply || "No response from OpenAI.",
39
38
  });
40
39
  const cleanedReply = responseParser(reply as string);
41
- if (!isGroup) chatHistories[address] = messages;
40
+ chatHistories[address] = messages;
41
+ console.log("messages.length", messages.length);
42
42
  return { reply: cleanedReply, history: messages };
43
43
  } catch (error) {
44
44
  console.error("Failed to fetch from OpenAI:", error);
@@ -100,6 +100,9 @@ export async function processResponseWithSkill(
100
100
  if (response && response.message) {
101
101
  let msg = responseParser(response.message);
102
102
 
103
+ if (!chatHistories[address]) {
104
+ chatHistories[address] = [];
105
+ }
103
106
  chatHistories[address].push({
104
107
  role: "system",
105
108
  content: msg,
@@ -1,11 +1,10 @@
1
- export async function ens_agent_prompt(
2
- address: string,
3
- domain?: string,
4
- name?: string,
5
- converseUsername?: string,
6
- txUrl?: string,
7
- ) {
8
- const systemPrompt = `You are a helpful and playful agent that lives inside a web3 messaging app called Converse.
1
+ import { skills } from "./skills.js";
2
+ import type { UserInfo } from "./lib/resolver.js";
3
+
4
+ export async function ens_agent_prompt(userInfo: UserInfo) {
5
+ let { address, ensDomain, converseUsername } = userInfo;
6
+
7
+ const systemPrompt = `You are a helpful and playful agent called @ens that lives inside a web3 messaging app called Converse.
9
8
  - You can respond with multiple messages if needed. Each message should be separated by a newline character.
10
9
  - You can trigger commands by only sending the command in a newline message.
11
10
  - Never announce actions without using a command separated by a newline character.
@@ -16,8 +15,8 @@ export async function ens_agent_prompt(
16
15
 
17
16
  User context:
18
17
  - Users address is: ${address}
19
- ${domain != undefined ? `- User ENS domain is: ${domain}` : ""}
20
- ${name != undefined ? `- Converse username is: ${name}` : ""}
18
+ ${ensDomain != undefined ? `- User ENS domain is: ${ensDomain}` : ""}
19
+ ${converseUsername != undefined ? `- Converse username is: ${converseUsername}` : ""}
21
20
 
22
21
  ## Task
23
22
  - Start by fetch their domain from or Convese username
@@ -25,57 +24,48 @@ ${name != undefined ? `- Converse username is: ${name}` : ""}
25
24
  - Ask for a name (if they don't have one) so you can suggest domains.
26
25
 
27
26
  Commands:
28
- - "/info [domain]": To get information about a domain use this command.
29
- - "/check [domain]": To check to see if a domain is available use this command.
30
- - "/register [domain]": To register a domain use this command. This will return a url pointing to the registration page.
31
- - "/renew [domain]": To trigger renewal of a domain use this command. This will return a url with a button to renew the domain.
32
- - "/tip [address]": To tip a domain or address use this command. This will return a url with a button to send the tip
33
- - "/cool [domain]": To get cool alternatives for a .eth domain use this command.
27
+ ${skills.map((skill) => skill.skills.map((s) => s.command).join("\n")).join("\n")}
34
28
 
35
29
  Examples:
36
- - /check ${domain}
37
- - /info nick.eth
38
- - /register vitalik.eth
39
- - /renew fabri.base.eth
40
- - /tip 0xf0EA7663233F99D0c12370671abBb6Cca980a490
41
- - /cool vitalik.eth
30
+ ${skills.map((skill) => skill.skills.map((s) => s.example).join("\n")).join("\n")}
31
+
42
32
 
43
- ## Example response:
33
+ ## Example responses:
44
34
 
45
35
  1. Check if the user does not have a ENS domain
46
- Hey ${name}! it looks like you don't have a ENS domain yet! \n\Let me start by checking your Converse username ${converseUsername}.eth\n/check ${converseUsername}.eth
36
+ Hey ${converseUsername}! it looks like you don't have a ENS domain yet! \n\Let me start by checking your Converse username with the .eth suffix\n/check ${converseUsername}.eth
47
37
 
48
38
  2. If the user has a ENS domain
49
- Hello ${domain} ! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${domain}. Give me a moment.\n/check ${domain}
39
+ Hello ${ensDomain} ! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/check ${ensDomain}
50
40
 
51
41
  3. Check if the ENS domain is available
52
- Hello! I'll help you get your domain.\n Let's start by checking your ENS domain ${domain}. Give me a moment.\n/check ${domain}
42
+ Hello! I'll help you get your domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/check ${ensDomain}
53
43
 
54
44
  4. If the ENS domain is available,
55
- Looks like ${domain} is available! Would you like to register it?\n/register ${domain}\n or I can suggest some cool alternatives? Le me know!
45
+ Looks like ${ensDomain} is available! Here you can register it:\n/register ${ensDomain}\n or I can suggest some cool alternatives? Le me know!
56
46
 
57
47
  5. If the ENS domain is already registered, let me suggest 5 cool alternatives
58
- Looks like ${domain} is already registered!\n What about these cool alternatives?\n/cool ${domain}
48
+ Looks like ${ensDomain} is already registered!\n What about these cool alternatives?\n/cool ${ensDomain}
59
49
 
60
50
  6. If the user wants to register a ENS domain, use the command "/register [domain]"
61
- Looks like ${domain} is available! Let me help you register it\n/register ${domain}
51
+ Looks like ${ensDomain} is available! Let me help you register it\n/register ${ensDomain}
62
52
 
63
53
  7. If the user wants to directly to tip to the ENS domain owner, use directly the command "/tip [domain]", this will return a url but a button to send the tip
64
- Here is the url to send the tip:\n/tip ${domain}
54
+ Here is the url to send the tip:\n/tip ${ensDomain}
65
55
 
66
56
  8. If the user wants to get information about the ENS domain, use the command "/info [domain]"
67
- Hello! I'll help you get info about ${domain}.\n Give me a moment.\n/info ${domain}
57
+ Hello! I'll help you get info about ${ensDomain}.\n Give me a moment.\n/info ${ensDomain}
68
58
 
69
59
  9. If the user wants to renew their domain, use the command "/renew [domain]"
70
- Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${domain}. Give me a moment.\n/renew ${domain}
60
+ Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/renew ${ensDomain}
71
61
 
72
62
  10. If the user wants cool suggestions about a domain, use the command "/cool [domain]"
73
- Here are some cool suggestions for your domain.\n/cool ${domain}
63
+ Here are some cool suggestions for your domain.\n/cool ${ensDomain}
74
64
 
75
65
  ## Most common bug
76
- Some times you will say something like: "Looks like vitalik.eth is registered! What about these cool alternatives?"
77
- But you forgot to add the command at the end of the message.
78
- You should have said something like: "Looks like vitalik.eth is registered! What about these cool alternatives?\n/cool vitalik.eth
66
+ Some times you will say something like: "Looks like vitalik.eth is registered! What about these cool alternatives?"
67
+ But you forgot to add the command at the end of the message.
68
+ You should have said something like: "Looks like vitalik.eth is registered! What about these cool alternatives?\n/cool vitalik.eth
79
69
  `;
80
70
  return systemPrompt;
81
71
  }
@@ -1,14 +1,16 @@
1
+ import { handleEns, ensAgent } from "./handler/ens.js";
1
2
  import type { SkillGroup } from "@xmtp/message-kit";
2
- import { handleEns } from "./handler/ens.js";
3
3
 
4
4
  export const skills: SkillGroup[] = [
5
5
  {
6
6
  name: "Ens Domain Bot",
7
+ tag: "@ens",
8
+ tagHandler: ensAgent,
7
9
  description: "Register ENS domains.",
8
10
  skills: [
9
11
  {
10
12
  command: "/register [domain]",
11
- triggers: ["/register", "@ensbot"],
13
+ triggers: ["/register"],
12
14
  handler: handleEns,
13
15
  description:
14
16
  "Register a new ENS domain. Returns a URL to complete the registration process.",
@@ -21,7 +23,7 @@ export const skills: SkillGroup[] = [
21
23
  },
22
24
  {
23
25
  command: "/info [domain]",
24
- triggers: ["/info", "@ensbot"],
26
+ triggers: ["/info"],
25
27
  handler: handleEns,
26
28
  description:
27
29
  "Get detailed information about an ENS domain including owner, expiry date, and resolver.",
@@ -34,7 +36,7 @@ export const skills: SkillGroup[] = [
34
36
  },
35
37
  {
36
38
  command: "/renew [domain]",
37
- triggers: ["/renew", "@ensbot"],
39
+ triggers: ["/renew"],
38
40
  handler: handleEns,
39
41
  description:
40
42
  "Extend the registration period of your ENS domain. Returns a URL to complete the renewal.",
@@ -14,7 +14,6 @@ export async function textGeneration(
14
14
  address: string,
15
15
  userPrompt: string,
16
16
  systemPrompt: string,
17
- isGroup: boolean = false,
18
17
  ) {
19
18
  let messages = chatHistories[address] || [];
20
19
  if (messages.length === 0) {
@@ -38,7 +37,7 @@ export async function textGeneration(
38
37
  content: reply || "No response from OpenAI.",
39
38
  });
40
39
  const cleanedReply = responseParser(reply as string);
41
- if (!isGroup) chatHistories[address] = messages;
40
+ chatHistories[address] = messages;
42
41
  return { reply: cleanedReply, history: messages };
43
42
  } catch (error) {
44
43
  console.error("Failed to fetch from OpenAI:", error);
@@ -83,7 +82,7 @@ export async function vision(imageData: Uint8Array, systemPrompt: string) {
83
82
  }
84
83
  }
85
84
 
86
- export async function processResponseWithskill(
85
+ export async function processResponseWithSkill(
87
86
  address: string,
88
87
  reply: string,
89
88
  context: any,
@@ -100,6 +99,9 @@ export async function processResponseWithskill(
100
99
  if (response && response.message) {
101
100
  let msg = responseParser(response.message);
102
101
 
102
+ if (!chatHistories[address]) {
103
+ chatHistories[address] = [];
104
+ }
103
105
  chatHistories[address].push({
104
106
  role: "system",
105
107
  content: msg,
@@ -1,10 +1,10 @@
1
- import type { SkillGroup } from "@xmtp/message-kit";
2
1
  import { handler as tipping } from "./handler/tipping.js";
3
2
  import { handler as agent } from "./handler/agent.js";
4
3
  import { handler as transaction } from "./handler/transaction.js";
5
4
  import { handler as games } from "./handler/game.js";
6
5
  import { handler as loyalty } from "./handler/loyalty.js";
7
6
  import { helpHandler } from "./index.js";
7
+ import type { SkillGroup } from "@xmtp/message-kit";
8
8
 
9
9
  export const skills: SkillGroup[] = [
10
10
  {