create-message-kit 1.0.17 → 1.0.20

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/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
  {