create-message-kit 1.1.7-beta.8 → 1.1.8
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +2 -2
- package/index.js +60 -50
- package/package.json +1 -1
- package/templates/agent/src/handler/ens.ts +14 -12
- package/templates/agent/src/index.ts +2 -10
- package/templates/agent/src/prompt.ts +28 -22
- package/templates/agent/src/skills.ts +8 -9
- package/templates/gm/.env.example +1 -1
- package/templates/gm/src/index.ts +1 -5
- package/templates/group/.env.example +2 -3
- package/templates/group/src/handler/game.ts +4 -5
- package/templates/group/src/handler/helpers.ts +10 -6
- package/templates/group/src/handler/payment.ts +29 -0
- package/templates/group/src/handler/tipping.ts +17 -35
- package/templates/group/src/index.ts +23 -26
- package/templates/group/src/prompt.ts +45 -0
- package/templates/group/src/skills.ts +17 -107
- package/templates/agent/package.json +0 -22
- package/templates/agent/src/lib/gpt.ts +0 -161
- package/templates/agent/src/lib/openai.ts +0 -174
- package/templates/agent/src/lib/resolver.ts +0 -151
- package/templates/gm/package.json +0 -21
- package/templates/group/package.json +0 -23
- package/templates/group/src/handler/agent.ts +0 -67
- package/templates/group/src/handler/group.ts +0 -24
- package/templates/group/src/handler/loyalty.ts +0 -46
- package/templates/group/src/handler/splitpayment.ts +0 -65
- package/templates/group/src/handler/transaction.ts +0 -50
- package/templates/group/src/lib/gpt.ts +0 -161
- package/templates/group/src/lib/openai.ts +0 -174
- package/templates/group/src/lib/resolver.ts +0 -151
- package/templates/group/src/lib/stack.ts +0 -18
- package/templates/group/src/lib/vision.ts +0 -42
package/README.md
CHANGED
@@ -9,7 +9,7 @@ bun create message-kit
|
|
9
9
|
```
|
10
10
|
|
11
11
|
```bash
|
12
|
-
npx create-message-kit
|
12
|
+
npx create-message-kit
|
13
13
|
```
|
14
14
|
|
15
15
|
```bash
|
@@ -17,5 +17,5 @@ yarn create message-kit
|
|
17
17
|
```
|
18
18
|
|
19
19
|
```bash [npm]
|
20
|
-
npm init message-kit
|
20
|
+
npm init message-kit
|
21
21
|
```
|
package/index.js
CHANGED
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
|
5
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
|
+
import { detect } from "detect-package-manager";
|
8
9
|
import pc from "picocolors";
|
9
10
|
|
10
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
@@ -15,9 +16,14 @@ const packageJson = JSON.parse(
|
|
15
16
|
);
|
16
17
|
const version = packageJson.version;
|
17
18
|
program
|
18
|
-
.name("
|
19
|
+
.name("message-kit")
|
19
20
|
.description("CLI to initialize projects")
|
20
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
|
+
|
21
27
|
log.info(pc.cyan(`Welcome to MessageKit CLI v${version}!`));
|
22
28
|
const coolLogo = `
|
23
29
|
███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗████████╗
|
@@ -32,9 +38,6 @@ Powered by XMTP`;
|
|
32
38
|
|
33
39
|
const { templateType, displayName, destDir } = await gatherProjectInfo();
|
34
40
|
|
35
|
-
// Replace dot files
|
36
|
-
//replaceDotfiles(destDir);
|
37
|
-
|
38
41
|
// Create .gitignore
|
39
42
|
createGitignore(destDir);
|
40
43
|
|
@@ -44,13 +47,11 @@ Powered by XMTP`;
|
|
44
47
|
// Create tsconfig.json file
|
45
48
|
createTsconfig(destDir);
|
46
49
|
|
47
|
-
// Replace package.json properties
|
48
|
-
updatePackageJson(destDir, displayName);
|
49
|
-
|
50
50
|
// Wrap up
|
51
51
|
log.success(`Project launched in ${pc.red(destDir)}!`);
|
52
52
|
|
53
|
-
|
53
|
+
// Add package.json
|
54
|
+
addPackagejson(destDir, displayName, pkgManager);
|
54
55
|
|
55
56
|
// Create README.md file
|
56
57
|
createReadme(destDir, templateType, displayName, pkgManager);
|
@@ -63,6 +64,39 @@ Powered by XMTP`;
|
|
63
64
|
|
64
65
|
program.parse(process.argv);
|
65
66
|
|
67
|
+
async function addPackagejson(destDir, name, pkgManager) {
|
68
|
+
// Create package.json based on the template
|
69
|
+
let packageTemplate = {
|
70
|
+
name: name,
|
71
|
+
private: true,
|
72
|
+
type: "module",
|
73
|
+
scripts: {
|
74
|
+
build: "tsc",
|
75
|
+
dev: "tsc -w & sleep 1 && node --watch dist/index.js",
|
76
|
+
start: "node dist/index.js",
|
77
|
+
postinstall: "tsc",
|
78
|
+
},
|
79
|
+
dependencies: {
|
80
|
+
"@xmtp/message-kit": "latest",
|
81
|
+
},
|
82
|
+
engines: {
|
83
|
+
node: ">=20",
|
84
|
+
},
|
85
|
+
};
|
86
|
+
|
87
|
+
if (pkgManager.startsWith("yarn")) {
|
88
|
+
packageTemplate.packageManager = `${pkgManager}`;
|
89
|
+
// Add .yarnrc.yml to disable PnP mode
|
90
|
+
fs.writeFileSync(
|
91
|
+
resolve(destDir, ".yarnrc.yml"),
|
92
|
+
"nodeLinker: node-modules\n",
|
93
|
+
);
|
94
|
+
}
|
95
|
+
fs.writeJsonSync(resolve(destDir, "package.json"), packageTemplate, {
|
96
|
+
spaces: 2,
|
97
|
+
});
|
98
|
+
}
|
99
|
+
|
66
100
|
async function gatherProjectInfo() {
|
67
101
|
const templateOptions = [
|
68
102
|
{ value: "gm", label: "GM" },
|
@@ -108,24 +142,6 @@ async function gatherProjectInfo() {
|
|
108
142
|
return { templateType, displayName, destDir, templateDir };
|
109
143
|
}
|
110
144
|
|
111
|
-
function updateDependenciesToLatest(pkgJson) {
|
112
|
-
const updateToLatest = (deps) => {
|
113
|
-
for (const key in deps) {
|
114
|
-
if (deps[key].startsWith("workspace:")) {
|
115
|
-
deps[key] = "latest";
|
116
|
-
}
|
117
|
-
}
|
118
|
-
};
|
119
|
-
|
120
|
-
if (pkgJson.dependencies) {
|
121
|
-
updateToLatest(pkgJson.dependencies);
|
122
|
-
}
|
123
|
-
|
124
|
-
if (pkgJson.devDependencies) {
|
125
|
-
updateToLatest(pkgJson.devDependencies);
|
126
|
-
}
|
127
|
-
}
|
128
|
-
|
129
145
|
function createTsconfig(destDir) {
|
130
146
|
const tsconfigContent = {
|
131
147
|
include: ["src/**/*"],
|
@@ -151,22 +167,6 @@ function createTsconfig(destDir) {
|
|
151
167
|
spaces: 2,
|
152
168
|
});
|
153
169
|
}
|
154
|
-
function replaceDotfiles(destDir) {
|
155
|
-
for (const file of fs.readdirSync(destDir)) {
|
156
|
-
if (!file.startsWith("_")) continue;
|
157
|
-
fs.renameSync(
|
158
|
-
resolve(destDir, file),
|
159
|
-
resolve(destDir, `.${file.slice(1)}`),
|
160
|
-
);
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
function updatePackageJson(destDir, name) {
|
165
|
-
const pkgJson = fs.readJsonSync(resolve(destDir, "package.json"));
|
166
|
-
pkgJson.name = name;
|
167
|
-
updateDependenciesToLatest(pkgJson);
|
168
|
-
fs.writeJsonSync(resolve(destDir, "package.json"), pkgJson, { spaces: 2 });
|
169
|
-
}
|
170
170
|
|
171
171
|
function logNextSteps(name) {
|
172
172
|
log.message("Next steps:");
|
@@ -202,14 +202,24 @@ yarn-error.log*
|
|
202
202
|
fs.writeFileSync(resolve(destDir, ".gitignore"), gitignoreContent.trim());
|
203
203
|
}
|
204
204
|
|
205
|
-
function detectPackageManager() {
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
205
|
+
async function detectPackageManager() {
|
206
|
+
try {
|
207
|
+
const pkgManager = await detect();
|
208
|
+
const userAgent = process.env.npm_config_user_agent;
|
209
|
+
let version = "";
|
210
|
+
|
211
|
+
if (userAgent && pkgManager === "yarn") {
|
212
|
+
const parts = userAgent.split(" ")[0]?.split("/");
|
213
|
+
if (parts && parts.length > 1) {
|
214
|
+
version = `@${parts[1]}`;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
return pkgManager + version;
|
219
|
+
} catch (error) {
|
220
|
+
// Fallback to npm if detection fails
|
221
|
+
return "npm";
|
222
|
+
}
|
213
223
|
}
|
214
224
|
|
215
225
|
function kebabcase(str) {
|
package/package.json
CHANGED
@@ -9,17 +9,19 @@ export const baseTxUrl = "https://base-tx-frame.vercel.app";
|
|
9
9
|
|
10
10
|
export async function handleEns(
|
11
11
|
context: HandlerContext,
|
12
|
-
): Promise<SkillResponse> {
|
12
|
+
): Promise<SkillResponse | undefined> {
|
13
13
|
const {
|
14
14
|
message: {
|
15
|
-
|
15
|
+
sender,
|
16
|
+
content: { skill, params },
|
16
17
|
},
|
17
18
|
} = context;
|
18
|
-
|
19
|
+
|
20
|
+
if (skill == "reset") {
|
19
21
|
clearMemory();
|
20
22
|
return { code: 200, message: "Conversation reset." };
|
21
|
-
} else if (
|
22
|
-
// Destructure and validate parameters for the ens
|
23
|
+
} else if (skill == "renew") {
|
24
|
+
// Destructure and validate parameters for the ens
|
23
25
|
const { domain } = params;
|
24
26
|
// Check if the user holds the domain
|
25
27
|
if (!domain) {
|
@@ -42,8 +44,8 @@ export async function handleEns(
|
|
42
44
|
// Generate URL for the ens
|
43
45
|
let url_ens = frameUrl + "frames/manage?name=" + domain;
|
44
46
|
return { code: 200, message: `${url_ens}` };
|
45
|
-
} else if (
|
46
|
-
// Destructure and validate parameters for the ens
|
47
|
+
} else if (skill == "register") {
|
48
|
+
// Destructure and validate parameters for the ens
|
47
49
|
const { domain } = params;
|
48
50
|
|
49
51
|
if (!domain) {
|
@@ -55,7 +57,7 @@ export async function handleEns(
|
|
55
57
|
// Generate URL for the ens
|
56
58
|
let url_ens = ensUrl + domain;
|
57
59
|
return { code: 200, message: `${url_ens}` };
|
58
|
-
} else if (
|
60
|
+
} else if (skill == "info") {
|
59
61
|
const { domain } = params;
|
60
62
|
|
61
63
|
const data = await getUserInfo(domain);
|
@@ -92,7 +94,7 @@ export async function handleEns(
|
|
92
94
|
);
|
93
95
|
}
|
94
96
|
return { code: 200, message };
|
95
|
-
} else if (
|
97
|
+
} else if (skill == "check") {
|
96
98
|
const { domain } = params;
|
97
99
|
|
98
100
|
if (!domain) {
|
@@ -117,7 +119,7 @@ export async function handleEns(
|
|
117
119
|
message,
|
118
120
|
};
|
119
121
|
}
|
120
|
-
} else if (
|
122
|
+
} else if (skill == "tip") {
|
121
123
|
const { address } = params;
|
122
124
|
if (!address) {
|
123
125
|
return {
|
@@ -134,7 +136,7 @@ export async function handleEns(
|
|
134
136
|
code: 200,
|
135
137
|
message: txUrl,
|
136
138
|
};
|
137
|
-
} else if (
|
139
|
+
} else if (skill == "cool") {
|
138
140
|
const { domain } = params;
|
139
141
|
//What about these cool alternatives?\
|
140
142
|
return {
|
@@ -142,7 +144,7 @@ export async function handleEns(
|
|
142
144
|
message: `${generateCoolAlternatives(domain)}`,
|
143
145
|
};
|
144
146
|
} else {
|
145
|
-
return { code: 400, message: "
|
147
|
+
return { code: 400, message: "Skill not found." };
|
146
148
|
}
|
147
149
|
}
|
148
150
|
|
@@ -4,23 +4,15 @@ import { agent_prompt } from "./prompt.js";
|
|
4
4
|
import { getUserInfo } from "@xmtp/message-kit";
|
5
5
|
|
6
6
|
run(async (context: HandlerContext) => {
|
7
|
-
/*All the skills are handled through the skills file*/
|
8
|
-
/* If its just text, it will be handled by the ensAgent*/
|
9
|
-
/* If its a group message, it will be handled by the groupAgent*/
|
10
|
-
if (!process?.env?.OPEN_AI_API_KEY) {
|
11
|
-
console.warn("No OPEN_AI_API_KEY found in .env");
|
12
|
-
return;
|
13
|
-
}
|
14
|
-
|
15
7
|
const {
|
16
8
|
message: {
|
17
|
-
content: {
|
9
|
+
content: { text, params },
|
18
10
|
sender,
|
19
11
|
},
|
20
12
|
} = context;
|
21
13
|
|
22
14
|
try {
|
23
|
-
let userPrompt = params?.prompt ??
|
15
|
+
let userPrompt = params?.prompt ?? text;
|
24
16
|
const userInfo = await getUserInfo(sender.address);
|
25
17
|
if (!userInfo) {
|
26
18
|
console.log("User info not found");
|
@@ -1,57 +1,51 @@
|
|
1
1
|
import { skills } from "./skills.js";
|
2
2
|
import {
|
3
|
-
getUserInfo,
|
4
3
|
UserInfo,
|
5
4
|
PROMPT_USER_CONTENT,
|
6
5
|
PROMPT_RULES,
|
7
6
|
PROMPT_SKILLS_AND_EXAMPLES,
|
7
|
+
PROMPT_REPLACE_VARIABLES,
|
8
8
|
} from "@xmtp/message-kit";
|
9
9
|
|
10
10
|
export async function agent_prompt(userInfo: UserInfo) {
|
11
|
-
let
|
11
|
+
let systemPrompt =
|
12
|
+
PROMPT_RULES +
|
13
|
+
PROMPT_USER_CONTENT(userInfo) +
|
14
|
+
PROMPT_SKILLS_AND_EXAMPLES(skills, "@ens");
|
12
15
|
|
13
|
-
|
14
|
-
let systemPrompt = PROMPT_RULES.replace("{NAME}", skills?.[0]?.tag ?? "@ens");
|
15
|
-
|
16
|
-
//Add user context to the prompt
|
17
|
-
systemPrompt += PROMPT_USER_CONTENT(userInfo);
|
18
|
-
|
19
|
-
//Add skills and examples to the prompt
|
20
|
-
systemPrompt += PROMPT_SKILLS_AND_EXAMPLES(skills, "@ens");
|
21
|
-
|
22
|
-
systemPrompt += `
|
16
|
+
let fineTunning = `
|
23
17
|
|
24
18
|
## Example responses:
|
25
19
|
|
26
20
|
1. Check if the user does not have a ENS domain
|
27
|
-
Hey
|
21
|
+
Hey {PREFERRED_NAME}! 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 {CONVERSE_USERNAME}.eth
|
28
22
|
|
29
23
|
2. If the user has a ENS domain
|
30
|
-
Hello
|
24
|
+
Hello {PREFERRED_NAME} ! I'll help you get your ENS domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/check {ENS_DOMAIN}
|
31
25
|
|
32
26
|
3. Check if the ENS domain is available
|
33
|
-
Hello! I'll help you get your domain.\n Let's start by checking your ENS domain
|
27
|
+
Hello! I'll help you get your domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/check {ENS_DOMAIN}
|
34
28
|
|
35
29
|
4. If the ENS domain is available,
|
36
|
-
Looks like
|
30
|
+
Looks like {ENS_DOMAIN} is available! Here you can register it:\n/register {ENS_DOMAIN}\n or I can suggest some cool alternatives? Le me know!
|
37
31
|
|
38
32
|
5. If the ENS domain is already registered, let me suggest 5 cool alternatives
|
39
|
-
Looks like
|
33
|
+
Looks like {ENS_DOMAIN} is already registered!\n What about these cool alternatives?\n/cool {ENS_DOMAIN}
|
40
34
|
|
41
35
|
6. If the user wants to register a ENS domain, use the command "/register [domain]"
|
42
|
-
Looks like
|
36
|
+
Looks like {ENS_DOMAIN} is available! Let me help you register it\n/register {ENS_DOMAIN}
|
43
37
|
|
44
38
|
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
|
45
|
-
Here is the url to send the tip:\n/tip
|
39
|
+
Here is the url to send the tip:\n/tip {ENS_DOMAIN}
|
46
40
|
|
47
41
|
8. If the user wants to get information about the ENS domain, use the command "/info [domain]"
|
48
|
-
Hello! I'll help you get info about
|
42
|
+
Hello! I'll help you get info about {ENS_DOMAIN}.\n Give me a moment.\n/info {ENS_DOMAIN}
|
49
43
|
|
50
44
|
9. If the user wants to renew their domain, use the command "/renew [domain]"
|
51
|
-
Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain
|
45
|
+
Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/renew {ENS_DOMAIN}
|
52
46
|
|
53
47
|
10. If the user wants cool suggestions about a domain, use the command "/cool [domain]"
|
54
|
-
Here are some cool suggestions for your domain.\n/cool
|
48
|
+
Here are some cool suggestions for your domain.\n/cool {ENS_DOMAIN}
|
55
49
|
|
56
50
|
## Most common bugs
|
57
51
|
|
@@ -59,5 +53,17 @@ export async function agent_prompt(userInfo: UserInfo) {
|
|
59
53
|
But you forgot to add the command at the end of the message.
|
60
54
|
You should have said something like: "Looks like vitalik.eth is registered! What about these cool alternatives?\n/cool vitalik.eth
|
61
55
|
`;
|
56
|
+
|
57
|
+
// Add the fine tuning to the system prompt
|
58
|
+
systemPrompt += fineTunning;
|
59
|
+
|
60
|
+
// Replace the variables in the system prompt
|
61
|
+
systemPrompt = PROMPT_REPLACE_VARIABLES(
|
62
|
+
systemPrompt,
|
63
|
+
userInfo?.address ?? "",
|
64
|
+
userInfo,
|
65
|
+
"@ens",
|
66
|
+
);
|
67
|
+
// console.log(systemPrompt);
|
62
68
|
return systemPrompt;
|
63
69
|
}
|
@@ -8,7 +8,7 @@ export const skills: SkillGroup[] = [
|
|
8
8
|
description: "Register ENS domains.",
|
9
9
|
skills: [
|
10
10
|
{
|
11
|
-
|
11
|
+
skill: "/register [domain]",
|
12
12
|
triggers: ["/register"],
|
13
13
|
handler: handleEns,
|
14
14
|
description:
|
@@ -21,8 +21,7 @@ export const skills: SkillGroup[] = [
|
|
21
21
|
},
|
22
22
|
},
|
23
23
|
{
|
24
|
-
|
25
|
-
adminOnly: true,
|
24
|
+
skill: "/exists",
|
26
25
|
examples: ["/exists"],
|
27
26
|
handler: handleEns,
|
28
27
|
triggers: ["/exists"],
|
@@ -34,7 +33,7 @@ export const skills: SkillGroup[] = [
|
|
34
33
|
},
|
35
34
|
},
|
36
35
|
{
|
37
|
-
|
36
|
+
skill: "/info [domain]",
|
38
37
|
triggers: ["/info"],
|
39
38
|
handler: handleEns,
|
40
39
|
description:
|
@@ -47,7 +46,7 @@ export const skills: SkillGroup[] = [
|
|
47
46
|
},
|
48
47
|
},
|
49
48
|
{
|
50
|
-
|
49
|
+
skill: "/renew [domain]",
|
51
50
|
triggers: ["/renew"],
|
52
51
|
handler: handleEns,
|
53
52
|
description:
|
@@ -60,7 +59,7 @@ export const skills: SkillGroup[] = [
|
|
60
59
|
},
|
61
60
|
},
|
62
61
|
{
|
63
|
-
|
62
|
+
skill: "/check [domain]",
|
64
63
|
triggers: ["/check"],
|
65
64
|
handler: handleEns,
|
66
65
|
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
@@ -72,7 +71,7 @@ export const skills: SkillGroup[] = [
|
|
72
71
|
},
|
73
72
|
},
|
74
73
|
{
|
75
|
-
|
74
|
+
skill: "/cool [domain]",
|
76
75
|
triggers: ["/cool"],
|
77
76
|
examples: ["/cool vitalik.eth"],
|
78
77
|
handler: handleEns,
|
@@ -84,7 +83,7 @@ export const skills: SkillGroup[] = [
|
|
84
83
|
},
|
85
84
|
},
|
86
85
|
{
|
87
|
-
|
86
|
+
skill: "/reset",
|
88
87
|
triggers: ["/reset"],
|
89
88
|
examples: ["/reset"],
|
90
89
|
handler: handleEns,
|
@@ -92,7 +91,7 @@ export const skills: SkillGroup[] = [
|
|
92
91
|
params: {},
|
93
92
|
},
|
94
93
|
{
|
95
|
-
|
94
|
+
skill: "/tip [address]",
|
96
95
|
description: "Show a URL for tipping a domain owner.",
|
97
96
|
triggers: ["/tip"],
|
98
97
|
handler: handleEns,
|
@@ -1 +1 @@
|
|
1
|
-
KEY= # the private key of the
|
1
|
+
KEY= # the private key of the agent wallet
|
@@ -1,9 +1,5 @@
|
|
1
1
|
import { run, HandlerContext } from "@xmtp/message-kit";
|
2
2
|
|
3
3
|
run(async (context: HandlerContext) => {
|
4
|
-
|
5
|
-
const { content, sender } = context.message;
|
6
|
-
|
7
|
-
// To reply, just call `reply` on the HandlerContext
|
8
|
-
await context.send(`gm`);
|
4
|
+
context.send("gm");
|
9
5
|
});
|
@@ -1,3 +1,2 @@
|
|
1
|
-
KEY= # the private key of the
|
2
|
-
OPEN_AI_API_KEY= # openai api key
|
3
|
-
STACK_API_KEY= # stack api key
|
1
|
+
KEY= # the private key of the agent wallet
|
2
|
+
OPEN_AI_API_KEY= # openai api key
|
@@ -1,14 +1,13 @@
|
|
1
1
|
import { HandlerContext } from "@xmtp/message-kit";
|
2
2
|
|
3
|
-
// Handler function to process game-related
|
3
|
+
// Handler function to process game-related
|
4
4
|
export async function handler(context: HandlerContext) {
|
5
5
|
const {
|
6
6
|
message: {
|
7
|
-
content: {
|
7
|
+
content: { skill, params, text },
|
8
8
|
},
|
9
9
|
} = context;
|
10
|
-
if (!
|
11
|
-
const { content: text } = context?.message?.content;
|
10
|
+
if (!skill) {
|
12
11
|
if (text === "🔎" || text === "🔍") {
|
13
12
|
// Send the URL for the requested game
|
14
13
|
context.reply("https://framedl.xyz/");
|
@@ -36,7 +35,7 @@ export async function handler(context: HandlerContext) {
|
|
36
35
|
default:
|
37
36
|
// Inform the user about unrecognized skills and provide available options
|
38
37
|
context.send(
|
39
|
-
"
|
38
|
+
"Skill not recognized. Available games: wordle, slot, or help.",
|
40
39
|
);
|
41
40
|
}
|
42
41
|
}
|
@@ -3,22 +3,26 @@ import { HandlerContext } from "@xmtp/message-kit";
|
|
3
3
|
export async function handler(context: HandlerContext) {
|
4
4
|
const {
|
5
5
|
skills,
|
6
|
-
group,
|
7
6
|
message: {
|
8
|
-
content: {
|
7
|
+
content: { skill },
|
9
8
|
},
|
9
|
+
group,
|
10
10
|
} = context;
|
11
11
|
|
12
|
-
if (
|
12
|
+
if (skill == "help") {
|
13
13
|
const intro =
|
14
14
|
"Available experiences:\n" +
|
15
15
|
skills
|
16
16
|
?.flatMap((app) => app.skills)
|
17
|
-
.map((skill) => `${skill.
|
17
|
+
.map((skill) => `${skill.skill} - ${skill.description}`)
|
18
18
|
.join("\n") +
|
19
19
|
"\nUse these skills to interact with specific apps.";
|
20
20
|
context.send(intro);
|
21
|
-
} else if (
|
22
|
-
|
21
|
+
} else if (skill == "id") {
|
22
|
+
if (!group?.id) {
|
23
|
+
context.send("This skill only works in group chats.");
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
context.send(group?.id);
|
23
27
|
}
|
24
28
|
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { getUserInfo, HandlerContext } from "@xmtp/message-kit";
|
2
|
+
|
3
|
+
export async function handler(context: HandlerContext) {
|
4
|
+
const {
|
5
|
+
message: {
|
6
|
+
content: { skill, params },
|
7
|
+
},
|
8
|
+
} = context;
|
9
|
+
const baseUrl = "https://txpay.vercel.app";
|
10
|
+
|
11
|
+
if (skill === "pay") {
|
12
|
+
const { amount: amountSend, token: tokenSend, username } = params; // [!code hl] // [!code focus]
|
13
|
+
console.log("username", username);
|
14
|
+
let senderInfo = await getUserInfo(username);
|
15
|
+
if (!amountSend || !tokenSend || !senderInfo) {
|
16
|
+
context.reply(
|
17
|
+
"Missing required parameters. Please provide amount, token, and username.",
|
18
|
+
);
|
19
|
+
return {
|
20
|
+
code: 400,
|
21
|
+
message:
|
22
|
+
"Missing required parameters. Please provide amount, token, and username.",
|
23
|
+
};
|
24
|
+
}
|
25
|
+
|
26
|
+
let sendUrl = `${baseUrl}/?&amount=${amountSend}&token=${tokenSend}&receiver=${senderInfo.address}`;
|
27
|
+
await context.send(`${sendUrl}`);
|
28
|
+
}
|
29
|
+
}
|
@@ -1,49 +1,31 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
HandlerContext,
|
3
|
+
AbstractedMember,
|
4
|
+
SkillResponse,
|
5
|
+
} from "@xmtp/message-kit";
|
2
6
|
import { getUserInfo } from "@xmtp/message-kit";
|
3
7
|
|
4
8
|
export async function handler(context: HandlerContext) {
|
5
9
|
const {
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
message: {
|
11
|
+
content: {
|
12
|
+
skill,
|
13
|
+
params: { amount, username },
|
14
|
+
},
|
15
|
+
sender,
|
16
|
+
},
|
9
17
|
} = context;
|
10
|
-
|
11
|
-
const replyReceiver = members?.find(
|
12
|
-
(member) => member.inboxId === msg?.senderInboxId,
|
13
|
-
);
|
14
|
-
let amount: number = 0,
|
15
|
-
receivers: AbstractedMember[] = [];
|
16
|
-
// Handle different types of messages
|
17
|
-
if (typeId === "reply" && replyReceiver) {
|
18
|
-
const { content: reply } = content;
|
19
|
-
|
20
|
-
if (reply.includes("degen")) {
|
21
|
-
receivers = [replyReceiver];
|
22
|
-
const match = reply.match(/(\d+)/);
|
23
|
-
if (match)
|
24
|
-
amount = parseInt(match[0]); // Extract amount from reply
|
25
|
-
else amount = 10;
|
26
|
-
}
|
27
|
-
} else if (typeId === "text") {
|
28
|
-
const { content: text, params } = content;
|
29
|
-
if (text.startsWith("/tip") && params) {
|
30
|
-
// Process text skills starting with "/tip"
|
31
|
-
const {
|
32
|
-
params: { amount: extractedAmount, username },
|
33
|
-
} = content;
|
34
|
-
amount = extractedAmount || 10; // Default amount if not specified
|
18
|
+
let receivers: AbstractedMember[] = [];
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
)
|
39
|
-
|
20
|
+
if (skill === "tip") {
|
21
|
+
receivers = await Promise.all(
|
22
|
+
username.map((username: string) => getUserInfo(username)),
|
23
|
+
);
|
40
24
|
}
|
41
25
|
if (!sender || receivers.length === 0 || amount === 0) {
|
42
26
|
context.reply("Sender or receiver or amount not found.");
|
43
|
-
return;
|
44
27
|
}
|
45
28
|
const receiverAddresses = receivers.map((receiver) => receiver.address);
|
46
|
-
// Process sending tokens to each receiver
|
47
29
|
|
48
30
|
context.sendTo(
|
49
31
|
`You received ${amount} tokens from ${sender.address}.`,
|