create-message-kit 1.2.3 → 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
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
+ }