create-message-kit 1.0.16 → 1.0.19

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.
@@ -6,12 +6,16 @@ const openai = new OpenAI({
6
6
  apiKey: process.env.OPEN_AI_API_KEY,
7
7
  });
8
8
 
9
+ export type ChatHistoryEntry = { role: string; content: string };
10
+ export type ChatHistories = Record<string, ChatHistoryEntry[]>;
11
+
12
+ let chatHistories: ChatHistories = {};
9
13
  export async function textGeneration(
14
+ address: string,
10
15
  userPrompt: string,
11
16
  systemPrompt: string,
12
- chatHistory?: any[],
13
17
  ) {
14
- let messages = chatHistory ? [...chatHistory] : []; // Start with existing chat history
18
+ let messages = chatHistories[address] || [];
15
19
  if (messages.length === 0) {
16
20
  messages.push({
17
21
  role: "system",
@@ -33,7 +37,7 @@ export async function textGeneration(
33
37
  content: reply || "No response from OpenAI.",
34
38
  });
35
39
  const cleanedReply = responseParser(reply as string);
36
-
40
+ chatHistories[address] = messages;
37
41
  return { reply: cleanedReply, history: messages };
38
42
  } catch (error) {
39
43
  console.error("Failed to fetch from OpenAI:", error);
@@ -78,6 +82,38 @@ export async function vision(imageData: Uint8Array, systemPrompt: string) {
78
82
  }
79
83
  }
80
84
 
85
+ export async function processResponseWithSkill(
86
+ address: string,
87
+ reply: string,
88
+ context: any,
89
+ ) {
90
+ let messages = reply
91
+ .split("\n")
92
+ .map((message: string) => responseParser(message))
93
+ .filter((message): message is string => message.length > 0);
94
+
95
+ console.log(messages);
96
+ for (const message of messages) {
97
+ if (message.startsWith("/")) {
98
+ const response = await context.skill(message);
99
+ if (response && response.message) {
100
+ let msg = responseParser(response.message);
101
+
102
+ if (!chatHistories[address]) {
103
+ chatHistories[address] = [];
104
+ }
105
+ chatHistories[address].push({
106
+ role: "system",
107
+ content: msg,
108
+ });
109
+
110
+ await context.send(response.message);
111
+ }
112
+ } else {
113
+ await context.send(message);
114
+ }
115
+ }
116
+ }
81
117
  export function responseParser(message: string) {
82
118
  let trimmedMessage = message;
83
119
  // Remove bold and underline markdown
@@ -94,5 +130,10 @@ export function responseParser(message: string) {
94
130
  trimmedMessage = trimmedMessage?.replace(/^\s+|\s+$/g, "");
95
131
  // Remove any remaining leading or trailing whitespace
96
132
  trimmedMessage = trimmedMessage.trim();
133
+
97
134
  return trimmedMessage;
98
135
  }
136
+
137
+ export const clearChatHistories = () => {
138
+ chatHistories = {};
139
+ };
@@ -0,0 +1,126 @@
1
+ import { Client } from "@xmtp/xmtp-js";
2
+ import { isAddress } from "viem";
3
+
4
+ export const converseEndpointURL =
5
+ "https://converse-website-git-endpoit-ephemerahq.vercel.app";
6
+ //export const converseEndpointURL = "http://localhost:3000";
7
+
8
+ export type InfoCache = Map<string, UserInfo>;
9
+ export type ConverseProfile = {
10
+ address: string | null;
11
+ onXmtp: boolean;
12
+ avatar: string | null;
13
+ formattedName: string | null;
14
+ name: string | null;
15
+ };
16
+ export type UserInfo = {
17
+ ensDomain?: string | undefined;
18
+ address?: string | undefined;
19
+ converseUsername?: string | undefined;
20
+ ensInfo?: EnsData | undefined;
21
+ avatar?: string | undefined;
22
+ };
23
+ export interface EnsData {
24
+ address?: string;
25
+ avatar?: string;
26
+ avatar_small?: string;
27
+ converse?: string;
28
+ avatar_url?: string;
29
+ contentHash?: string;
30
+ description?: string;
31
+ ens?: string;
32
+ ens_primary?: string;
33
+ github?: string;
34
+ resolverAddress?: string;
35
+ twitter?: string;
36
+ url?: string;
37
+ wallets?: {
38
+ eth?: string;
39
+ };
40
+ }
41
+
42
+ let infoCache: InfoCache = new Map();
43
+
44
+ export const clearInfoCache = () => {
45
+ infoCache.clear();
46
+ };
47
+ export const getUserInfo = async (
48
+ key: string,
49
+ clientAddress?: string,
50
+ ): Promise<UserInfo | null> => {
51
+ let data: UserInfo = infoCache.get(key) || {
52
+ ensDomain: undefined,
53
+ address: undefined,
54
+ converseUsername: undefined,
55
+ ensInfo: undefined,
56
+ };
57
+ //console.log("Getting user info", key, clientAddress);
58
+ if (isAddress(clientAddress || "")) {
59
+ data.address = clientAddress;
60
+ } else if (isAddress(key || "")) {
61
+ data.address = key;
62
+ } else if (key.includes(".eth")) {
63
+ data.ensDomain = key;
64
+ } else if (key == "@user" || key == "@me" || key == "@bot") {
65
+ data.address = clientAddress;
66
+ data.ensDomain = key.replace("@", "") + ".eth";
67
+ data.converseUsername = key.replace("@", "");
68
+ } else if (key == "@alix") {
69
+ data.address = "0x3a044b218BaE80E5b9E16609443A192129A67BeA";
70
+ data.converseUsername = "alix";
71
+ } else if (key == "@bo") {
72
+ data.address = "0xbc3246461ab5e1682baE48fa95172CDf0689201a";
73
+ data.converseUsername = "bo";
74
+ } else {
75
+ data.converseUsername = key;
76
+ }
77
+
78
+ let keyToUse = data.address || data.ensDomain || data.converseUsername;
79
+ let cacheData = keyToUse && infoCache.get(keyToUse);
80
+ if (cacheData) {
81
+ //console.log("Getting user info", keyToUse, cacheData);
82
+ return cacheData;
83
+ } else {
84
+ //console.log("Getting user info", keyToUse, data);
85
+ }
86
+
87
+ if (keyToUse?.includes(".eth")) {
88
+ const response = await fetch(`https://ensdata.net/${keyToUse}`);
89
+ const ensData: EnsData = (await response.json()) as EnsData;
90
+ //console.log("Ens data", ensData);
91
+ if (ensData) {
92
+ data.ensInfo = ensData;
93
+ data.ensDomain = ensData?.ens;
94
+ data.address = ensData?.address;
95
+ }
96
+ } else if (keyToUse) {
97
+ keyToUse = keyToUse.replace("@", "");
98
+ const response = await fetch(`${converseEndpointURL}/profile/${keyToUse}`, {
99
+ method: "POST",
100
+ headers: {
101
+ "Content-Type": "application/json",
102
+ Accept: "application/json",
103
+ },
104
+ body: JSON.stringify({
105
+ peer: keyToUse,
106
+ }),
107
+ });
108
+ const converseData = (await response.json()) as ConverseProfile;
109
+ if (process.env.MSG_LOG)
110
+ console.log("Converse data", keyToUse, converseData);
111
+ data.converseUsername =
112
+ converseData?.formattedName || converseData?.name || undefined;
113
+ data.address = converseData?.address || undefined;
114
+ data.avatar = converseData?.avatar || undefined;
115
+ }
116
+ if (data.address) infoCache.set(data.address, data);
117
+ return data;
118
+ };
119
+ export const isOnXMTP = async (
120
+ client: Client,
121
+ domain: string | undefined,
122
+ address: string | undefined,
123
+ ) => {
124
+ if (domain == "fabri.eth") return false;
125
+ if (address) return (await client.canMessage([address])).length > 0;
126
+ };
@@ -1,24 +1,25 @@
1
- import type { CommandGroup } 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
- export const commands: CommandGroup[] = [
9
+ export const skills: SkillGroup[] = [
10
10
  {
11
11
  name: "Tipping",
12
12
  description: "Tip tokens via emoji, replies or command.",
13
- commands: [
13
+ skills: [
14
14
  {
15
- command: "/tip [@users] [amount] [token]",
16
- triggers: ["/tip", "🎩", "@tip"],
15
+ command: "/tip [@usernames] [amount] [token]",
16
+ triggers: ["/tip"],
17
17
  description: "Tip users in a specified token.",
18
18
  handler: tipping,
19
19
  params: {
20
20
  username: {
21
21
  default: "",
22
+ plural: true,
22
23
  type: "username",
23
24
  },
24
25
  amount: {
@@ -32,10 +33,10 @@ export const commands: CommandGroup[] = [
32
33
  {
33
34
  name: "Transactions",
34
35
  description: "Multipurpose transaction frame built onbase.",
35
- commands: [
36
+ skills: [
36
37
  {
37
- command: "/send [amount] [token] [@username]",
38
- triggers: ["@send", "/send"],
38
+ command: "/send [amount] [token] [username]",
39
+ triggers: ["/send"],
39
40
  description:
40
41
  "Send a specified amount of a cryptocurrency to a destination address.",
41
42
  handler: transaction,
@@ -57,7 +58,7 @@ export const commands: CommandGroup[] = [
57
58
  },
58
59
  {
59
60
  command: "/swap [amount] [token_from] [token_to]",
60
- triggers: ["@swap", "/swap"],
61
+ triggers: ["/swap"],
61
62
  description: "Exchange one type of cryptocurrency for another.",
62
63
  handler: transaction,
63
64
  params: {
@@ -89,10 +90,10 @@ export const commands: CommandGroup[] = [
89
90
  {
90
91
  name: "Games",
91
92
  description: "Provides various gaming experiences.",
92
- commands: [
93
+ skills: [
93
94
  {
94
95
  command: "/game [game]",
95
- triggers: ["/game", "@game", "🔎", "🔍"],
96
+ triggers: ["/game", "🔎", "🔍"],
96
97
  handler: games,
97
98
  description: "Play a game.",
98
99
  params: {
@@ -108,17 +109,17 @@ export const commands: CommandGroup[] = [
108
109
  {
109
110
  name: "Loyalty",
110
111
  description: "Manage group members and metadata.",
111
- commands: [
112
+ skills: [
112
113
  {
113
114
  command: "/points",
114
- triggers: ["/points", "@points"],
115
+ triggers: ["/points"],
115
116
  handler: loyalty,
116
117
  description: "Check your points.",
117
118
  params: {},
118
119
  },
119
120
  {
120
121
  command: "/leaderboard",
121
- triggers: ["/leaderboard", "@leaderboard"],
122
+ triggers: ["/leaderboard"],
122
123
  adminOnly: true,
123
124
  handler: loyalty,
124
125
  description: "Check the points of a user.",
@@ -129,7 +130,7 @@ export const commands: CommandGroup[] = [
129
130
  {
130
131
  name: "Agent",
131
132
  description: "Manage agent commands.",
132
- commands: [
133
+ skills: [
133
134
  {
134
135
  command: "/agent [prompt]",
135
136
  triggers: ["/agent", "@agent", "@bot"],
@@ -147,7 +148,7 @@ export const commands: CommandGroup[] = [
147
148
  {
148
149
  name: "Help",
149
150
  description: "Get help with the bot.",
150
- commands: [
151
+ skills: [
151
152
  {
152
153
  command: "/help",
153
154
  triggers: ["/help"],
@@ -1,69 +0,0 @@
1
- import type { CommandGroup } from "@xmtp/message-kit";
2
- import { ensAgent, handleEns } from "./handler/ens.js";
3
-
4
- export const commands: CommandGroup[] = [
5
- {
6
- name: "Ens Domain Bot",
7
- description: "Register ENS domains.",
8
- commands: [
9
- {
10
- command: "/register [domain]",
11
- triggers: ["/register", "@ensbot"],
12
- handler: handleEns,
13
- description: "Register a domain.",
14
- params: {
15
- domain: {
16
- type: "string",
17
- },
18
- },
19
- },
20
- {
21
- command: "/info [domain]",
22
- triggers: ["/info", "@ensbot"],
23
- handler: handleEns,
24
- description: "Get information about a domain.",
25
- params: {
26
- domain: {
27
- type: "string",
28
- },
29
- },
30
- },
31
- {
32
- command: "/renew [domain]",
33
- triggers: ["/renew", "@ensbot"],
34
- handler: handleEns,
35
- description: "Renew a domain.",
36
- params: {
37
- domain: {
38
- type: "string",
39
- },
40
- },
41
- },
42
- {
43
- command: "/check [domain] [cool_alternatives]",
44
- triggers: ["/check"],
45
- handler: handleEns,
46
- description: "Check if a domain is available.",
47
- params: {
48
- domain: {
49
- type: "string",
50
- },
51
- cool_alternatives: {
52
- type: "quoted",
53
- },
54
- },
55
- },
56
- {
57
- command: "/tip [address]",
58
- description: "Show a URL for tipping a domain owner.",
59
- triggers: ["/tip"],
60
- handler: ensAgent,
61
- params: {
62
- address: {
63
- type: "address",
64
- },
65
- },
66
- },
67
- ],
68
- },
69
- ];
@@ -1,33 +0,0 @@
1
- export type chatHistories = Record<string, any[]>;
2
- export type ensDomain = Record<string, string | undefined>;
3
- export type converseUsername = Record<string, string | undefined>;
4
- export type tipAddress = Record<string, string | undefined>;
5
- export type tipDomain = Record<string, string | undefined>;
6
-
7
- export type InfoCache = {
8
- [key: string]: { info: EnsData };
9
- };
10
- export const frameUrl = "https://ens.steer.fun/";
11
- export const ensUrl = "https://app.ens.domains/";
12
- export const baseTxUrl = "https://base-tx-frame.vercel.app";
13
- export const endpointURL =
14
- "https://converse-website-git-endpoit-ephemerahq.vercel.app";
15
-
16
- export interface EnsData {
17
- address?: string;
18
- avatar?: string;
19
- avatar_small?: string;
20
- converse?: string;
21
- avatar_url?: string;
22
- contentHash?: string;
23
- description?: string;
24
- ens?: string;
25
- ens_primary?: string;
26
- github?: string;
27
- resolverAddress?: string;
28
- twitter?: string;
29
- url?: string;
30
- wallets?: {
31
- eth?: string;
32
- };
33
- }
@@ -1,18 +0,0 @@
1
- import { handler as handlerAll } from "./handler.js";
2
- import type { CommandGroup } from "@xmtp/message-kit";
3
-
4
- export const commands: CommandGroup[] = [
5
- {
6
- name: "Gm Commands",
7
- description: "Commands to send a gm.",
8
- commands: [
9
- {
10
- command: "/gm",
11
- triggers: ["/gm"],
12
- description: "Send a gm.",
13
- handler: handlerAll,
14
- params: {},
15
- },
16
- ],
17
- },
18
- ];
@@ -1,6 +0,0 @@
1
- import type { HandlerContext } from "@xmtp/message-kit";
2
-
3
- export const handler = async (context: HandlerContext) => {
4
- await context.send("gm2");
5
- await context.intent("/gm3");
6
- };