create-message-kit 1.2.3 → 1.2.7

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 (32) hide show
  1. package/index.js +40 -27
  2. package/package.json +1 -1
  3. package/templates/agent/.cursorrules +227 -0
  4. package/templates/agent/src/index.ts +19 -26
  5. package/templates/agent/src/prompt.ts +1 -1
  6. package/templates/agent/src/{handlers → skills}/check.ts +5 -4
  7. package/templates/agent/src/{handlers → skills}/cool.ts +1 -1
  8. package/templates/agent/src/{handlers → skills}/game.ts +1 -1
  9. package/templates/agent/src/{handlers → skills}/info.ts +6 -5
  10. package/templates/agent/src/{handlers → skills}/pay.ts +20 -5
  11. package/templates/agent/src/{handlers → skills}/register.ts +2 -3
  12. package/templates/agent/src/{handlers → skills}/renew.ts +5 -4
  13. package/templates/agent/src/skills/reset.ts +26 -0
  14. package/templates/experimental/.cursorrules +227 -0
  15. package/templates/experimental/.env.example +2 -0
  16. package/templates/{gated → experimental}/package.json +5 -4
  17. package/templates/experimental/src/index.ts +41 -0
  18. package/templates/{gated/src/lib/nft.ts → experimental/src/lib/alchemy.ts} +4 -10
  19. package/templates/experimental/src/lib/xmtp.ts +138 -0
  20. package/templates/experimental/src/prompt.ts +24 -0
  21. package/templates/experimental/src/skills/broadcast.ts +38 -0
  22. package/templates/experimental/src/skills/gated.ts +100 -0
  23. package/templates/{agent/src/handlers → experimental/src/skills}/todo.ts +12 -8
  24. package/templates/{agent/src/handlers → experimental/src/skills}/token.ts +1 -1
  25. package/templates/gpt/.cursorrules +227 -0
  26. package/templates/gpt/src/index.ts +1 -0
  27. package/templates/agent/src/handlers/reset.ts +0 -19
  28. package/templates/gated/.env.example +0 -3
  29. package/templates/gated/src/index.ts +0 -64
  30. package/templates/gated/src/lib/gated.ts +0 -51
  31. package/templates/gated/src/skills.ts +0 -23
  32. /package/templates/{gated → experimental}/.yarnrc.yml +0 -0
package/index.js CHANGED
@@ -7,7 +7,7 @@ import { default as fs } from "fs-extra";
7
7
  import { isCancel } from "@clack/prompts";
8
8
  import { detect } from "detect-package-manager";
9
9
  import pc from "picocolors";
10
-
10
+ const defVersion = "1.2.7";
11
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
12
12
 
13
13
  // Read package.json to get the version
@@ -19,13 +19,21 @@ program
19
19
  .name("message-kit")
20
20
  .description("CLI to initialize projects")
21
21
  .action(async () => {
22
- // Add Yarn 4 check at the start of the action
23
- const pkgManager = await detectPackageManager();
24
-
25
- log.info(pc.cyan(`pkgManager detected: ${pkgManager}`));
26
-
27
- log.info(pc.cyan(`Welcome to MessageKit CLI v${version}!`));
28
- const coolLogo = `
22
+ try {
23
+ // Add Yarn 4 check at the start of the action
24
+ const pkgManager = await detectPackageManager();
25
+
26
+ log.info(pc.cyan(`pkgManager detected: ${pkgManager}`));
27
+
28
+ log.info(pc.cyan(`Welcome to MessageKit CLI v${version}!`));
29
+ if (version !== defVersion) {
30
+ log.warn(
31
+ pc.red(
32
+ "You are using a version of the CLI that is not compatible with the latest MessageKit. Please update to the latest version.",
33
+ ),
34
+ );
35
+ }
36
+ const coolLogo = `
29
37
  ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗████████╗
30
38
  ████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ██╔════╝██║ ██╔╝██║╚══██╔══╝
31
39
  ██╔████╔██║█████╗ ███████╗███████╗███████║██║ ███╗█████╗ █████╔╝ ██║ ██║
@@ -34,32 +42,37 @@ program
34
42
  ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
35
43
  Powered by XMTP`;
36
44
 
37
- log.info(pc.red(coolLogo));
45
+ log.info(pc.red(coolLogo));
38
46
 
39
- const { templateType, displayName, destDir } = await gatherProjectInfo();
47
+ const { templateType, displayName, destDir } = await gatherProjectInfo();
40
48
 
41
- // Create .gitignore
42
- createGitignore(destDir);
49
+ // Create .gitignore
50
+ createGitignore(destDir);
43
51
 
44
- // Create .env file
45
- createEnvFile(destDir);
52
+ // Create .env file
53
+ createEnvFile(destDir);
46
54
 
47
- // Create tsconfig.json file
48
- createTsconfig(destDir);
55
+ // Create tsconfig.json file
56
+ createTsconfig(destDir);
49
57
 
50
- // Wrap up
51
- log.success(`Project launched in ${pc.red(destDir)}!`);
58
+ // Wrap up
59
+ log.success(`Project launched in ${pc.red(destDir)}!`);
52
60
 
53
- // Add package.json
54
- updatePackagejson(destDir, templateType);
61
+ // Add package.json
62
+ updatePackagejson(destDir, templateType);
55
63
 
56
- // Create README.md file
57
- createReadme(destDir, templateType, displayName, pkgManager);
64
+ // Create README.md file
65
+ createReadme(destDir, templateType, displayName, pkgManager);
58
66
 
59
- // Log next steps
60
- logNextSteps(displayName);
67
+ // Log next steps
68
+ logNextSteps(displayName);
61
69
 
62
- outro(pc.red("Made with ❤️ by Ephemera"));
70
+ outro(pc.red("Made with ❤️ by Ephemera"));
71
+ } catch (error) {
72
+ log.error(pc.red("An error occurred while creating your project:"));
73
+ log.error(error.message);
74
+ process.exit(1);
75
+ }
63
76
  });
64
77
 
65
78
  program.parse(process.argv);
@@ -83,9 +96,9 @@ async function updatePackagejson(destDir, templateType) {
83
96
 
84
97
  async function gatherProjectInfo() {
85
98
  const templateOptions = [
86
- { value: "agent", label: "Web3 Agent" },
87
99
  { value: "gpt", label: "Simple Gpt" },
88
- { value: "gated", label: "Gated Group" },
100
+ { value: "agent", label: "ENS Agent" },
101
+ { value: "experimental", label: "Experimental" },
89
102
  ];
90
103
 
91
104
  const templateType = await select({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-message-kit",
3
- "version": "1.2.3",
3
+ "version": "1.2.7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,227 @@
1
+ # MessageKit Skill Template
2
+
3
+ ## Examples
4
+
5
+ ### Check if a Domain is Available
6
+
7
+ ```typescript
8
+ import { ensUrl } from "../index.js";
9
+ import { XMTPContext } from "@xmtp/message-kit";
10
+ import type { Skill } from "@xmtp/message-kit";
11
+
12
+ // Define Skill
13
+ export const checkDomain: Skill[] = [
14
+ {
15
+ skill: "/check [domain]",
16
+ handler: handler,
17
+ examples: ["/check vitalik.eth", "/check fabri.base.eth"],
18
+ description: "Check if a domain is available.",
19
+ params: {
20
+ domain: {
21
+ type: "string",
22
+ },
23
+ },
24
+ },
25
+ ];
26
+
27
+ // Handler Implementation
28
+ export async function handler(context: XMTPContext) {
29
+ const {
30
+ message: {
31
+ content: {
32
+ params: { domain },
33
+ },
34
+ },
35
+ } = context;
36
+
37
+ const data = await context.getUserInfo(domain);
38
+
39
+ if (!data?.address) {
40
+ let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
41
+ return {
42
+ code: 200,
43
+ message,
44
+ };
45
+ } else {
46
+ let message = `Looks like ${domain} is already registered!`;
47
+ await context.executeSkill("/cool " + domain);
48
+ return {
49
+ code: 404,
50
+ message,
51
+ };
52
+ }
53
+ }
54
+
55
+ ### Generate a payment request
56
+
57
+ ```typescript
58
+ import { XMTPContext } from "@xmtp/message-kit";
59
+ import type { Skill } from "@xmtp/message-kit";
60
+
61
+ // Define Skill
62
+ export const paymentRequest: Skill[] = [
63
+ {
64
+ skill: "/pay [amount] [token] [username] [address]",
65
+ examples: [
66
+ "/pay 10 vitalik.eth",
67
+ "/pay 1 usdc to 0xc9925662D36DE3e1bF0fD64e779B2e5F0Aead964",
68
+ ],
69
+ description:
70
+ "Send a specified amount of a cryptocurrency to a destination address. \nWhen tipping, you can assume it's 1 USDC.",
71
+ handler: handler,
72
+ params: {
73
+ amount: {
74
+ default: 10,
75
+ type: "number",
76
+ },
77
+ token: {
78
+ default: "usdc",
79
+ type: "string",
80
+ values: ["eth", "dai", "usdc", "degen"], // Accepted tokens
81
+ },
82
+ username: {
83
+ default: "",
84
+ type: "username",
85
+ },
86
+ address: {
87
+ default: "",
88
+ type: "address",
89
+ },
90
+ },
91
+ },
92
+ ];
93
+
94
+ // Handler Implementation
95
+ export async function handler(context: XMTPContext) {
96
+ const {
97
+ message: {
98
+ content: {
99
+ params: { amount, token, username, address },
100
+ },
101
+ },
102
+ } = context;
103
+ let receiverAddress = address;
104
+ if (username) {
105
+ receiverAddress = (await context.getUserInfo(username))?.address;
106
+ }
107
+ if (address) {
108
+ // Prioritize address over username
109
+ receiverAddress = address;
110
+ }
111
+
112
+ await context.requestPayment(amount, token, receiverAddress);
113
+ }
114
+ ```
115
+
116
+
117
+ ## Types
118
+
119
+ ```typescript
120
+ import { XMTPContext } from "../lib/xmtp.js";
121
+ import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
122
+ import { ContentTypeId } from "@xmtp/content-type-primitives";
123
+
124
+ export type MessageAbstracted = {
125
+ id: string;
126
+ sent: Date;
127
+ content: {
128
+ text?: string | undefined;
129
+ reply?: string | undefined;
130
+ previousMsg?: string | undefined;
131
+ react?: string | undefined;
132
+ content?: any | undefined;
133
+ params?: any | undefined;
134
+ reference?: string | undefined;
135
+ skill?: string | undefined;
136
+ };
137
+ version: "v2" | "v3";
138
+ sender: AbstractedMember;
139
+ typeId: string;
140
+ };
141
+ export type GroupAbstracted = {
142
+ id: string;
143
+ sync: () => Promise<void>;
144
+ addMembers: (addresses: string[]) => Promise<void>;
145
+ addMembersByInboxId: (inboxIds: string[]) => Promise<void>;
146
+ send: (content: string, contentType?: ContentTypeId) => Promise<string>;
147
+ isAdmin: (inboxId: string) => boolean;
148
+ isSuperAdmin: (inboxId: string) => boolean;
149
+ admins: string[];
150
+ superAdmins: string[];
151
+ createdAt: Date;
152
+ members: GroupMember[];
153
+ };
154
+ export type SkillResponse = {
155
+ code: number;
156
+ message: string;
157
+ data?: any;
158
+ };
159
+
160
+ export type SkillHandler = (
161
+ context: XMTPContext,
162
+ ) => Promise<SkillResponse | void>;
163
+
164
+ export type Handler = (context: XMTPContext) => Promise<void>;
165
+
166
+ export type RunConfig = {
167
+ // client options from XMTP client
168
+ client?: ClientOptions;
169
+ // private key to be used for the client, if not, default from env
170
+ privateKey?: string;
171
+ // if true, the init log message with messagekit logo and stuff will be hidden
172
+ experimental?: boolean;
173
+ // hide the init log message with messagekit logo and stuff
174
+ hideInitLogMessage?: boolean;
175
+ // if true, attachments will be enabled
176
+ attachments?: boolean;
177
+ // if true, member changes will be enabled, like adding members to the group
178
+ memberChange?: boolean;
179
+ // skills to be used
180
+ agent?: Agent;
181
+ // model to be used
182
+ gptModel?: string;
183
+ };
184
+ export interface SkillParamConfig {
185
+ default?: string | number | boolean;
186
+ type:
187
+ | "number"
188
+ | "string"
189
+ | "username"
190
+ | "quoted"
191
+ | "address"
192
+ | "prompt"
193
+ | "url";
194
+ plural?: boolean;
195
+ values?: string[]; // Accepted values for the parameter
196
+ }
197
+
198
+ export interface Frame {
199
+ title: string;
200
+ buttons: { content: string; action: string; target: string }[];
201
+ image: string;
202
+ }
203
+ export interface Agent {
204
+ name: string;
205
+ description: string;
206
+ tag: string;
207
+ skills: Skill[];
208
+ }
209
+ export interface Skill {
210
+ skill: string;
211
+ handler?: SkillHandler | undefined;
212
+ adminOnly?: boolean;
213
+ description: string;
214
+ examples: string[];
215
+ params: Record<string, SkillParamConfig>;
216
+ }
217
+
218
+ export interface AbstractedMember {
219
+ inboxId: string;
220
+ address: string;
221
+ accountAddresses: string[];
222
+ installationIds?: string[];
223
+ }
224
+
225
+ export type MetadataValue = string | number | boolean;
226
+ export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
227
+ ```
@@ -6,37 +6,30 @@ import {
6
6
  Agent,
7
7
  } from "@xmtp/message-kit";
8
8
  import { systemPrompt } from "./prompt.js";
9
- import { registerSkill as checkSkill } from "./handlers/check.js";
10
- import { registerSkill as coolSkill } from "./handlers/cool.js";
11
- import { registerSkill as infoSkill } from "./handlers/info.js";
12
- import { registerSkill as registerSkill } from "./handlers/register.js";
13
- import { registerSkill as renewSkill } from "./handlers/renew.js";
14
- import { registerSkill as paySkill } from "./handlers/pay.js";
15
- import { registerSkill as resetSkill } from "./handlers/reset.js";
16
- import { registerSkill as tokenSkill } from "./handlers/token.js";
17
- import { registerSkill as gameSkill } from "./handlers/game.js";
18
- import { registerSkill as todoSkill } from "./handlers/todo.js";
9
+ import { checkDomain } from "./skills/check.js";
10
+ import { cool } from "./skills/cool.js";
11
+ import { info } from "./skills/info.js";
12
+ import { register } from "./skills/register.js";
13
+ import { renew } from "./skills/renew.js";
14
+ import { pay } from "./skills/pay.js";
15
+ import { reset } from "./skills/reset.js";
16
+ import { game } from "./skills/game.js";
19
17
  import fs from "fs";
20
18
 
21
- export const frameUrl = "https://ens.steer.fun/";
22
- export const ensUrl = "https://app.ens.domains/";
23
-
24
19
  // [!region skills]
25
20
  export const agent: Agent = {
26
- name: "Web3 Agent",
21
+ name: "Ens Agent",
27
22
  tag: "@bot",
28
- description: "A web3 agent with a lot of skills.",
23
+ description: "A ens agent with a lot of skills.",
29
24
  skills: [
30
- ...checkSkill,
31
- ...coolSkill,
32
- ...infoSkill,
33
- ...registerSkill,
34
- ...renewSkill,
35
- ...resetSkill,
36
- ...paySkill,
37
- ...tokenSkill,
38
- ...gameSkill,
39
- ...todoSkill,
25
+ ...checkDomain,
26
+ ...cool,
27
+ ...info,
28
+ ...register,
29
+ ...renew,
30
+ ...reset,
31
+ ...pay,
32
+ ...game,
40
33
  ],
41
34
  };
42
35
  // [!endregion skills]
@@ -56,7 +49,7 @@ run(
56
49
  // [!region run2]
57
50
  await agentReply(context, prompt);
58
51
  },
59
- { agent},
52
+ { agent },
60
53
  );
61
54
 
62
55
  // [!endregion run2]
@@ -1,5 +1,5 @@
1
1
  export const systemPrompt = `
2
- Your are helpful and playful web3 agent called {agent_name} that lives inside a messaging app called Converse.
2
+ Your are helpful and playful ens agent called {agent_name} that lives inside a messaging app called Converse.
3
3
 
4
4
  {rules}
5
5
 
@@ -1,9 +1,10 @@
1
- import { ensUrl } from "../index.js";
2
- import { XMTPContext, getUserInfo } from "@xmtp/message-kit";
1
+ import { XMTPContext } from "@xmtp/message-kit";
3
2
  import type { Skill } from "@xmtp/message-kit";
4
3
 
4
+ const ensUrl = "https://app.ens.domains/";
5
+
5
6
  // [!region define]
6
- export const registerSkill: Skill[] = [
7
+ export const checkDomain: Skill[] = [
7
8
  {
8
9
  skill: "/check [domain]",
9
10
  handler: handler,
@@ -28,7 +29,7 @@ export async function handler(context: XMTPContext) {
28
29
  },
29
30
  } = context;
30
31
 
31
- const data = await getUserInfo(domain);
32
+ const data = await context.getUserInfo(domain);
32
33
 
33
34
  if (!data?.address) {
34
35
  let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
@@ -2,7 +2,7 @@ import { XMTPContext } from "@xmtp/message-kit";
2
2
 
3
3
  import type { Skill } from "@xmtp/message-kit";
4
4
 
5
- export const registerSkill: Skill[] = [
5
+ export const cool: Skill[] = [
6
6
  {
7
7
  skill: "/cool [domain]",
8
8
  examples: ["/cool vitalik.eth"],
@@ -1,7 +1,7 @@
1
1
  import { XMTPContext } from "@xmtp/message-kit";
2
2
  import type { Skill } from "@xmtp/message-kit";
3
3
 
4
- export const registerSkill: Skill[] = [
4
+ export const game: Skill[] = [
5
5
  {
6
6
  skill: "/game [game]",
7
7
  handler: handler,
@@ -1,9 +1,8 @@
1
- import { ensUrl } from "../index.js";
2
- import { XMTPContext, getUserInfo, isOnXMTP } from "@xmtp/message-kit";
1
+ import { XMTPContext } from "@xmtp/message-kit";
3
2
 
4
3
  import type { Skill } from "@xmtp/message-kit";
5
4
 
6
- export const registerSkill: Skill[] = [
5
+ export const info: Skill[] = [
7
6
  {
8
7
  skill: "/info [domain]",
9
8
  handler: handler,
@@ -28,7 +27,7 @@ export async function handler(context: XMTPContext) {
28
27
  },
29
28
  } = context;
30
29
 
31
- const data = await getUserInfo(domain);
30
+ const data = await context.getUserInfo(domain);
32
31
  if (!data?.ensDomain) {
33
32
  return {
34
33
  code: 404,
@@ -49,7 +48,9 @@ export async function handler(context: XMTPContext) {
49
48
  message += `\n\nWould you like to tip the domain owner for getting there first 🤣?`;
50
49
  message = message.trim();
51
50
 
52
- if (await isOnXMTP(context.client, context.v2client, sender?.address)) {
51
+ if (
52
+ await context.isOnXMTP(context.client, context.v2client, sender?.address)
53
+ ) {
53
54
  await context.send(
54
55
  `Ah, this domains is in XMTP, you can message it directly`,
55
56
  );
@@ -1,10 +1,13 @@
1
1
  import { XMTPContext } from "@xmtp/message-kit";
2
2
  import type { Skill } from "@xmtp/message-kit";
3
3
 
4
- export const registerSkill: Skill[] = [
4
+ export const pay: Skill[] = [
5
5
  {
6
- skill: "/pay [amount] [token] [username]",
7
- examples: ["/pay 10 vitalik.eth"],
6
+ skill: "/pay [amount] [token] [username] [address]",
7
+ examples: [
8
+ "/pay 10 vitalik.eth",
9
+ "/pay 1 usdc to 0xc9925662D36DE3e1bF0fD64e779B2e5F0Aead964",
10
+ ],
8
11
  description:
9
12
  "Send a specified amount of a cryptocurrency to a destination address. \nWhen tipping, you can asume its 1 usdc.",
10
13
  handler: handler,
@@ -22,6 +25,10 @@ export const registerSkill: Skill[] = [
22
25
  default: "",
23
26
  type: "username",
24
27
  },
28
+ address: {
29
+ default: "",
30
+ type: "address",
31
+ },
25
32
  },
26
33
  },
27
34
  ];
@@ -29,10 +36,18 @@ export async function handler(context: XMTPContext) {
29
36
  const {
30
37
  message: {
31
38
  content: {
32
- params: { address },
39
+ params: { amount, token, username, address },
33
40
  },
34
41
  },
35
42
  } = context;
43
+ let receiverAddress = address;
44
+ if (username) {
45
+ receiverAddress = (await context.getUserInfo(username))?.address;
46
+ }
47
+ if (address) {
48
+ //Prioritize address over username
49
+ receiverAddress = address;
50
+ }
36
51
 
37
- await context.requestPayment(1, "USDC", address);
52
+ await context.requestPayment(amount, token, receiverAddress);
38
53
  }
@@ -1,9 +1,9 @@
1
- import { ensUrl } from "../index.js";
2
1
  import { XMTPContext } from "@xmtp/message-kit";
3
2
 
3
+ const ensUrl = "https://app.ens.domains/";
4
4
  import type { Skill } from "@xmtp/message-kit";
5
5
 
6
- export const registerSkill: Skill[] = [
6
+ export const register: Skill[] = [
7
7
  {
8
8
  skill: "/register [domain]",
9
9
  handler: handler,
@@ -37,4 +37,3 @@ export async function handler(context: XMTPContext) {
37
37
  let url_ens = ensUrl + domain;
38
38
  return { code: 200, message: `${url_ens}` };
39
39
  }
40
-
@@ -1,9 +1,10 @@
1
- import { frameUrl } from "../index.js";
2
- import { getUserInfo, XMTPContext } from "@xmtp/message-kit";
1
+ import { XMTPContext } from "@xmtp/message-kit";
3
2
 
4
3
  import type { Skill } from "@xmtp/message-kit";
5
4
 
6
- export const registerSkill: Skill[] = [
5
+ const frameUrl = "https://ens.steer.fun/";
6
+
7
+ export const renew: Skill[] = [
7
8
  {
8
9
  skill: "/renew [domain]",
9
10
  handler: handler,
@@ -36,7 +37,7 @@ export async function handler(context: XMTPContext) {
36
37
  };
37
38
  }
38
39
 
39
- const data = await getUserInfo(domain);
40
+ const data = await context.getUserInfo(domain);
40
41
 
41
42
  if (!data?.address || data?.address !== sender?.address) {
42
43
  return {
@@ -0,0 +1,26 @@
1
+ import { clearInfoCache, clearMemory } from "@xmtp/message-kit";
2
+ import { XMTPContext } from "@xmtp/message-kit";
3
+
4
+ import type { Skill } from "@xmtp/message-kit";
5
+
6
+ export const reset: Skill[] = [
7
+ {
8
+ skill: "/reset",
9
+ examples: ["/reset"],
10
+ handler: handler,
11
+ description: "Reset the conversation clearing memory and usernames cache.",
12
+ params: {},
13
+ },
14
+ ];
15
+ export async function handler(context: XMTPContext) {
16
+ const {
17
+ message: { sender },
18
+ } = context;
19
+ try {
20
+ clearMemory(sender.address);
21
+ clearInfoCache(sender.address);
22
+ return { code: 200, message: "Memory and usernames cache cleared." };
23
+ } catch (error) {
24
+ return { code: 500, message: "Error clearing memory and usernames cache." };
25
+ }
26
+ }