From fbf843f33394c00f9b26688e2c956cecc750e28a Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:16:24 -0300 Subject: [PATCH 01/12] grok --- README.md | 6 ++ examples/gpt/index.ts | 2 +- integrations/grok/.env.example | 5 ++ integrations/grok/README.md | 147 +++++++++++++++++++++++++++++++++ integrations/grok/index.ts | 114 +++++++++++++++++++++++++ integrations/grok/package.json | 27 ++++++ package.json | 7 +- yarn.lock | 33 +++++--- 8 files changed, 327 insertions(+), 14 deletions(-) create mode 100644 integrations/grok/.env.example create mode 100644 integrations/grok/README.md create mode 100644 integrations/grok/index.ts create mode 100644 integrations/grok/package.json diff --git a/README.md b/README.md index 9f2b26d..09aeda9 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,12 @@ yarn gen:keys > See all the available [examples](/examples/). +## Integrations + +Examples integrating XMTP with external libraries from the ecosystem + +- [grok](/integrations/grok/): Integration to Grok API + ## Web inbox Interact with the XMTP network using [xmtp.chat](https://xmtp.chat), the official web inbox for developers. diff --git a/examples/gpt/index.ts b/examples/gpt/index.ts index c02fc3f..44c400e 100644 --- a/examples/gpt/index.ts +++ b/examples/gpt/index.ts @@ -47,7 +47,7 @@ async function main() { await client.conversations.sync(); console.log( - `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`, + `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}?env=${env}`, ); console.log("Waiting for messages..."); diff --git a/integrations/grok/.env.example b/integrations/grok/.env.example new file mode 100644 index 0000000..9eeda7f --- /dev/null +++ b/integrations/grok/.env.example @@ -0,0 +1,5 @@ +WALLET_KEY= # the private key of the wallet +ENCRYPTION_KEY= # a second random 32 bytes encryption key for local db encryption + +# grok api key +GROK_API_KEY= # the API key for the Grok API diff --git a/integrations/grok/README.md b/integrations/grok/README.md new file mode 100644 index 0000000..3d55015 --- /dev/null +++ b/integrations/grok/README.md @@ -0,0 +1,147 @@ +# GPT agent example + +This example uses the [OpenAI](https://openai.com) API for GPT-based responses and [XMTP](https://xmtp.org) for secure messaging. You can test your agent on [xmtp.chat](https://xmtp.chat) or any other XMTP-compatible client. + +## Environment variables + +Add the following keys to a `.env` file: + +```bash +WALLET_KEY= # the private key of the wallet +ENCRYPTION_KEY= # a second random 32 bytes encryption key for local db encryption +GROK_API_KEY= # the API key for the Grok API +``` + +You can generate random keys with the following command: + +```bash +yarn gen:keys +``` + +> [!WARNING] +> Running the `gen:keys` script will overwrite the existing `.env` file. + +## Usage + +```tsx +import { Client, type XmtpEnv } from "@xmtp/node-sdk"; +import OpenAI from "openai"; +import { createSigner, getEncryptionKeyFromHex } from "@/helpers"; + +const { WALLET_KEY, ENCRYPTION_KEY, OPENAI_API_KEY, GROK_API_KEY } = + process.env; + +if (!WALLET_KEY) { + throw new Error("WALLET_KEY must be set"); +} + +if (!ENCRYPTION_KEY) { + throw new Error("ENCRYPTION_KEY must be set"); +} + +if (!OPENAI_API_KEY) { + throw new Error("OPENAI_API_KEY must be set"); +} + +const signer = createSigner(WALLET_KEY); +const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY); +const openai = new OpenAI({ apiKey: OPENAI_API_KEY }); + +/* Set the environment to dev or production */ +const env: XmtpEnv = "dev"; + +async function main() { + console.log(`Creating client on the '${env}' network...`); + const client = await Client.create(signer, encryptionKey, { + env, + }); + + console.log("Syncing conversations..."); + /* Sync the conversations from the network to update the local db */ + await client.conversations.sync(); + + console.log( + `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`, + ); + + console.log("Waiting for messages..."); + const stream = client.conversations.streamAllMessages(); + + for await (const message of await stream) { + /* Ignore messages from the same agent or non-text messages */ + if ( + message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() || + message?.contentType?.typeId !== "text" + ) { + continue; + } + + console.log( + `Received message: ${message.content as string} by ${message.senderInboxId}`, + ); + + const conversation = client.conversations.getConversationById( + message.conversationId, + ); + + if (!conversation) { + console.log("Unable to find conversation, skipping"); + continue; + } + + try { + // Use Grok API to get AI response + const response = await fetch("https://api.x.ai/v1/chat/completions", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${GROK_API_KEY}`, + }, + body: JSON.stringify({ + messages: [ + { role: "system", content: "You are a test assistant." }, + { role: "user", content: message.content as string }, + ], + model: "grok-2-latest", + stream: false, + temperature: 0, + }), + }).then( + (res) => + res.json() as Promise<{ + choices: { message: { content: string } }[]; + }>, + ); + const aiResponse = response.choices[0]?.message?.content || ""; + console.log(`Sending AI response: ${aiResponse}`); + await conversation.send(aiResponse); + } catch (error) { + console.error("Error getting AI response:", error); + await conversation.send( + "Sorry, I encountered an error processing your message.", + ); + } + + console.log("Waiting for messages..."); + } +} + +main().catch(console.error); +``` + +## Run the agent + +```bash +# git clone repo +git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git +# go to the folder +cd xmtp-agent-examples +cd integrations +cd grok +# install packages +yarn +# generate random keys (optional) +yarn gen:keys +# run the example +yarn examples:gpt +``` diff --git a/integrations/grok/index.ts b/integrations/grok/index.ts new file mode 100644 index 0000000..cbac903 --- /dev/null +++ b/integrations/grok/index.ts @@ -0,0 +1,114 @@ +import { Client, type XmtpEnv } from "@xmtp/node-sdk"; +import { createSigner, getEncryptionKeyFromHex } from "@/helpers"; + +/* Get the wallet key associated to the public key of + * the agent and the encryption key for the local db + * that stores your agent's messages */ +const { WALLET_KEY, ENCRYPTION_KEY, GROK_API_KEY } = process.env; + +/* Check if the environment variables are set */ +if (!WALLET_KEY) { + throw new Error("WALLET_KEY must be set"); +} + +/* Check if the encryption key is set */ +if (!ENCRYPTION_KEY) { + throw new Error("ENCRYPTION_KEY must be set"); +} + +/* Check if the Grok API key is set */ +if (!GROK_API_KEY) { + throw new Error("GROK_API_KEY must be set"); +} + +/* Create the signer using viem and parse the encryption key for the local db */ +const signer = createSigner(WALLET_KEY); +const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY); + +/* Set the environment to dev or production */ +const env: XmtpEnv = "dev"; + +/** + * Main function to run the agent + */ +async function main() { + console.log(`Creating client on the '${env}' network...`); + /* Initialize the xmtp client */ + const client = await Client.create(signer, encryptionKey, { + env, + }); + + console.log("Syncing conversations..."); + /* Sync the conversations from the network to update the local db */ + await client.conversations.sync(); + + console.log( + `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}?env=${env}`, + ); + console.log("Waiting for messages..."); + /* Stream all messages from the network */ + const stream = client.conversations.streamAllMessages(); + + for await (const message of await stream) { + /* Ignore messages from the same agent or non-text messages */ + if ( + message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() || + message?.contentType?.typeId !== "text" + ) { + continue; + } + + console.log( + `Received message: ${message.content as string} by ${message.senderInboxId}`, + ); + + /* Get the conversation from the local db */ + const conversation = client.conversations.getConversationById( + message.conversationId, + ); + + /* If the conversation is not found, skip the message */ + if (!conversation) { + console.log("Unable to find conversation, skipping"); + continue; + } + + try { + /* Get the AI response from Grok */ + const response = await fetch("https://api.x.ai/v1/chat/completions", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${GROK_API_KEY}`, // Use the same API key variable + }, + body: JSON.stringify({ + messages: [ + { role: "system", content: "You are a test assistant." }, + { role: "user", content: message.content as string }, + ], + model: "grok-2-latest", + stream: false, + temperature: 0, + }), + }).then( + (res) => + res.json() as Promise<{ + choices: { message: { content: string } }[]; + }>, + ); + const aiResponse = response.choices[0]?.message?.content || ""; + console.log(`Sending AI response: ${aiResponse}`); + /* Send the AI response to the conversation */ + await conversation.send(aiResponse); + } catch (error) { + console.error("Error getting AI response:", error); + await conversation.send( + "Sorry, I encountered an error processing your message.", + ); + } + + console.log("Waiting for messages..."); + } +} + +main().catch(console.error); diff --git a/integrations/grok/package.json b/integrations/grok/package.json new file mode 100644 index 0000000..f1679b1 --- /dev/null +++ b/integrations/grok/package.json @@ -0,0 +1,27 @@ +{ + "name": "@integrations/gpt", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "clean": "rimraf node_modules && yarn clean:dbs", + "clean:dbs": "rimraf *.db3* ||:", + "dev": "tsx --env-file=.env index.ts", + "format": "prettier -w .", + "format:check": "prettier -c .", + "gen:keys": "tsx ../../scripts/generateKeys.ts", + "lint": "eslint .", + "typecheck": "tsc" + }, + "dependencies": { + "@xmtp/node-sdk": "0.0.42", + "openai": "latest", + "tsx": "^4.19.2", + "uint8arrays": "^5.1.0", + "viem": "^2.22.17" + }, + "packageManager": "yarn@4.6.0", + "engines": { + "node": ">=20" + } +} diff --git a/package.json b/package.json index 2ee4d6d..c963392 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,10 @@ "version": "0.0.0", "private": true, "type": "module", + "workspaces": [ + "examples/*", + "integrations/*" + ], "scripts": { "clean": "rimraf node_modules && yarn clean:dbs", "clean:dbs": "rimraf *.db3* ||:", @@ -16,8 +20,7 @@ "typecheck": "tsc" }, "dependencies": { - "@xmtp/content-type-text": "^2.0.0", - "@xmtp/node-sdk": "0.0.40", + "@xmtp/node-sdk": "0.0.42", "alchemy-sdk": "^3.0.0", "openai": "latest", "tsx": "^4.19.2", diff --git a/yarn.lock b/yarn.lock index f1a0992..39bc6b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -808,6 +808,18 @@ __metadata: languageName: node linkType: hard +"@integrations/gpt@workspace:integrations/grok": + version: 0.0.0-use.local + resolution: "@integrations/gpt@workspace:integrations/grok" + dependencies: + "@xmtp/node-sdk": "npm:0.0.42" + openai: "npm:latest" + tsx: "npm:^4.19.2" + uint8arrays: "npm:^5.1.0" + viem: "npm:^2.22.17" + languageName: unknown + linkType: soft + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -1263,23 +1275,23 @@ __metadata: languageName: node linkType: hard -"@xmtp/node-bindings@npm:^0.0.34": - version: 0.0.34 - resolution: "@xmtp/node-bindings@npm:0.0.34" - checksum: 10/4f5314d40dc1f07e303e52a4be1d4517f1199089b4ac1677fabb11f64a6b4f57a989b25849b31036d6d228e9de494a8326d2b53386067146ee47e28691bba999 +"@xmtp/node-bindings@npm:^0.0.37": + version: 0.0.37 + resolution: "@xmtp/node-bindings@npm:0.0.37" + checksum: 10/06d12ee27f306a2ad767b75eedf3ceb0457cab3f574a545f44e487cbb39d07a3866c81277954a4937dc1f048a75c10b34b5ffa5de4fc43eaf9b1310a1c4dce8a languageName: node linkType: hard -"@xmtp/node-sdk@npm:0.0.40": - version: 0.0.40 - resolution: "@xmtp/node-sdk@npm:0.0.40" +"@xmtp/node-sdk@npm:0.0.42": + version: 0.0.42 + resolution: "@xmtp/node-sdk@npm:0.0.42" dependencies: "@xmtp/content-type-group-updated": "npm:^2.0.0" "@xmtp/content-type-primitives": "npm:^2.0.0" "@xmtp/content-type-text": "npm:^2.0.0" - "@xmtp/node-bindings": "npm:^0.0.34" + "@xmtp/node-bindings": "npm:^0.0.37" "@xmtp/proto": "npm:^3.72.3" - checksum: 10/eeed6072513dbf1c5ed7f0cfb9d5876c086d648b3fe93d757f0fefa87d03312a8aa5b3f3256b27339b37bbddf75c604eade1480a643909e04dc3865903915b2f + checksum: 10/6163ede6d9cd7bc36b3a237d9a63a8be0041a11a1eefc6f56fefbf7cb8b8cc02c817c4696996a29a4f296d7545fd3172d8ebf8f85e1aeb23dcff917719dfcd10 languageName: node linkType: hard @@ -3820,8 +3832,7 @@ __metadata: "@ianvs/prettier-plugin-sort-imports": "npm:^4.4.1" "@types/eslint__js": "npm:^8.42.3" "@types/node": "npm:^22.13.0" - "@xmtp/content-type-text": "npm:^2.0.0" - "@xmtp/node-sdk": "npm:0.0.40" + "@xmtp/node-sdk": "npm:0.0.42" alchemy-sdk: "npm:^3.0.0" eslint: "npm:^9.19.0" eslint-config-prettier: "npm:^10.0.1" From cfabf41c74f8b37cdc79c56a6753d9351f312cf7 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:23:52 -0300 Subject: [PATCH 02/12] gen keys --- scripts/generateKeys.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/generateKeys.ts b/scripts/generateKeys.ts index 6396c02..e1d4ae2 100644 --- a/scripts/generateKeys.ts +++ b/scripts/generateKeys.ts @@ -11,13 +11,14 @@ console.log("Generating keys..."); const walletKey = generatePrivateKey(); const encryptionKeyHex = generateEncryptionKeyHex(); -const envFilePath = join(__dirname, "../.env"); +const targetDir = process.argv[2] || "."; +const filePath = join(targetDir, ".env"); await writeFile( - envFilePath, + filePath, `WALLET_KEY=${walletKey} ENCRYPTION_KEY=${encryptionKeyHex} `, ); -console.log(`Keys written to ${envFilePath}`); +console.log(`Keys written to ${filePath}`); From 1a95a86ac462eed78fe7a9c149008d5e2adc3d5a Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:24:13 -0300 Subject: [PATCH 03/12] yarn dev --- integrations/grok/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/grok/README.md b/integrations/grok/README.md index 3d55015..e158f1c 100644 --- a/integrations/grok/README.md +++ b/integrations/grok/README.md @@ -143,5 +143,5 @@ yarn # generate random keys (optional) yarn gen:keys # run the example -yarn examples:gpt +yarn dev ``` From 63e9bc8f600fa5e0754c452ee1db8090760965d1 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:27:30 -0300 Subject: [PATCH 04/12] grok details --- integrations/grok/README.md | 145 +++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 10 deletions(-) diff --git a/integrations/grok/README.md b/integrations/grok/README.md index e158f1c..53ea237 100644 --- a/integrations/grok/README.md +++ b/integrations/grok/README.md @@ -1,6 +1,6 @@ # GPT agent example -This example uses the [OpenAI](https://openai.com) API for GPT-based responses and [XMTP](https://xmtp.org) for secure messaging. You can test your agent on [xmtp.chat](https://xmtp.chat) or any other XMTP-compatible client. +This example uses the [Grok](https://x.ai/api) API for responses and [XMTP](https://xmtp.org) for secure messaging. You can test your agent on [xmtp.chat](https://xmtp.chat) or any other XMTP-compatible client. ## Environment variables @@ -25,33 +25,41 @@ yarn gen:keys ```tsx import { Client, type XmtpEnv } from "@xmtp/node-sdk"; -import OpenAI from "openai"; import { createSigner, getEncryptionKeyFromHex } from "@/helpers"; -const { WALLET_KEY, ENCRYPTION_KEY, OPENAI_API_KEY, GROK_API_KEY } = - process.env; +/* Get the wallet key associated to the public key of + * the agent and the encryption key for the local db + * that stores your agent's messages */ +const { WALLET_KEY, ENCRYPTION_KEY, GROK_API_KEY } = process.env; +/* Check if the environment variables are set */ if (!WALLET_KEY) { throw new Error("WALLET_KEY must be set"); } +/* Check if the encryption key is set */ if (!ENCRYPTION_KEY) { throw new Error("ENCRYPTION_KEY must be set"); } -if (!OPENAI_API_KEY) { - throw new Error("OPENAI_API_KEY must be set"); +/* Check if the Grok API key is set */ +if (!GROK_API_KEY) { + throw new Error("GROK_API_KEY must be set"); } +/* Create the signer using viem and parse the encryption key for the local db */ const signer = createSigner(WALLET_KEY); const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY); -const openai = new OpenAI({ apiKey: OPENAI_API_KEY }); /* Set the environment to dev or production */ const env: XmtpEnv = "dev"; +/** + * Main function to run the agent + */ async function main() { console.log(`Creating client on the '${env}' network...`); + /* Initialize the xmtp client */ const client = await Client.create(signer, encryptionKey, { env, }); @@ -61,10 +69,124 @@ async function main() { await client.conversations.sync(); console.log( - `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`, + `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}?env=${env}`, ); + console.log("Waiting for messages..."); + /* Stream all messages from the network */ + const stream = client.conversations.streamAllMessages(); + + for await (const message of await stream) { + /* Ignore messages from the same agent or non-text messages */ + if ( + message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() || + message?.contentType?.typeId !== "text" + ) { + continue; + } + + console.log( + `Received message: ${message.content as string} by ${message.senderInboxId}`, + ); + + /* Get the conversation from the local db */ + const conversation = client.conversations.getConversationById( + message.conversationId, + ); + + /* If the conversation is not found, skip the message */ + if (!conversation) { + console.log("Unable to find conversation, skipping"); + continue; + } + + try { + /* Get the AI response from Grok */ + const response = await fetch("https://api.x.ai/v1/chat/completions", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${GROK_API_KEY}`, // Use the same API key variable + }, + body: JSON.stringify({ + messages: [ + { role: "system", content: "You are a test assistant." }, + { role: "user", content: message.content as string }, + ], + model: "grok-2-latest", + stream: false, + temperature: 0, + }), + }).then( + (res) => + res.json() as Promise<{ + choices: { message: { content: string } }[]; + }>, + ); + const aiResponse = response.choices[0]?.message?.content || ""; + console.log(`Sending AI response: ${aiResponse}`); + /* Send the AI response to the conversation */ + await conversation.send(aiResponse); + } catch (error) { + console.error("Error getting AI response:", error); + await conversation.send( + "Sorry, I encountered an error processing your message.", + ); + } + + console.log("Waiting for messages..."); + } +} + +main().catch(console.error); +import { Client, type XmtpEnv } from "@xmtp/node-sdk"; +import { createSigner, getEncryptionKeyFromHex } from "@/helpers"; + +/* Get the wallet key associated to the public key of + * the agent and the encryption key for the local db + * that stores your agent's messages */ +const { WALLET_KEY, ENCRYPTION_KEY, GROK_API_KEY } = process.env; + +/* Check if the environment variables are set */ +if (!WALLET_KEY) { + throw new Error("WALLET_KEY must be set"); +} + +/* Check if the encryption key is set */ +if (!ENCRYPTION_KEY) { + throw new Error("ENCRYPTION_KEY must be set"); +} + +/* Check if the Grok API key is set */ +if (!GROK_API_KEY) { + throw new Error("GROK_API_KEY must be set"); +} + +/* Create the signer using viem and parse the encryption key for the local db */ +const signer = createSigner(WALLET_KEY); +const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY); + +/* Set the environment to dev or production */ +const env: XmtpEnv = "dev"; +/** + * Main function to run the agent + */ +async function main() { + console.log(`Creating client on the '${env}' network...`); + /* Initialize the xmtp client */ + const client = await Client.create(signer, encryptionKey, { + env, + }); + + console.log("Syncing conversations..."); + /* Sync the conversations from the network to update the local db */ + await client.conversations.sync(); + + console.log( + `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}?env=${env}`, + ); console.log("Waiting for messages..."); + /* Stream all messages from the network */ const stream = client.conversations.streamAllMessages(); for await (const message of await stream) { @@ -80,22 +202,24 @@ async function main() { `Received message: ${message.content as string} by ${message.senderInboxId}`, ); + /* Get the conversation from the local db */ const conversation = client.conversations.getConversationById( message.conversationId, ); + /* If the conversation is not found, skip the message */ if (!conversation) { console.log("Unable to find conversation, skipping"); continue; } try { - // Use Grok API to get AI response + /* Get the AI response from Grok */ const response = await fetch("https://api.x.ai/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${GROK_API_KEY}`, + Authorization: `Bearer ${GROK_API_KEY}`, // Use the same API key variable }, body: JSON.stringify({ messages: [ @@ -114,6 +238,7 @@ async function main() { ); const aiResponse = response.choices[0]?.message?.content || ""; console.log(`Sending AI response: ${aiResponse}`); + /* Send the AI response to the conversation */ await conversation.send(aiResponse); } catch (error) { console.error("Error getting AI response:", error); From f938abb751352a51330b995984e25a42698782dd Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:29:53 -0300 Subject: [PATCH 05/12] fix openai --- integrations/grok/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/grok/README.md b/integrations/grok/README.md index 53ea237..f7411ea 100644 --- a/integrations/grok/README.md +++ b/integrations/grok/README.md @@ -1,4 +1,4 @@ -# GPT agent example +# Grok agent example This example uses the [Grok](https://x.ai/api) API for responses and [XMTP](https://xmtp.org) for secure messaging. You can test your agent on [xmtp.chat](https://xmtp.chat) or any other XMTP-compatible client. From e67e58cd2f17cd08698a9b4359ce8f587991a800 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:31:48 -0300 Subject: [PATCH 06/12] fix gen keys --- scripts/generateKeys.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/generateKeys.ts b/scripts/generateKeys.ts index e1d4ae2..a027360 100644 --- a/scripts/generateKeys.ts +++ b/scripts/generateKeys.ts @@ -11,8 +11,7 @@ console.log("Generating keys..."); const walletKey = generatePrivateKey(); const encryptionKeyHex = generateEncryptionKeyHex(); -const targetDir = process.argv[2] || "."; -const filePath = join(targetDir, ".env"); +const filePath = join(".", ".env"); await writeFile( filePath, From 1e83ddfa0b9083e2de343de27088a737e0532866 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:32:23 -0300 Subject: [PATCH 07/12] fix readme --- integrations/grok/README.md | 114 ------------------------------------ 1 file changed, 114 deletions(-) diff --git a/integrations/grok/README.md b/integrations/grok/README.md index f7411ea..87c8797 100644 --- a/integrations/grok/README.md +++ b/integrations/grok/README.md @@ -137,120 +137,6 @@ async function main() { } } -main().catch(console.error); -import { Client, type XmtpEnv } from "@xmtp/node-sdk"; -import { createSigner, getEncryptionKeyFromHex } from "@/helpers"; - -/* Get the wallet key associated to the public key of - * the agent and the encryption key for the local db - * that stores your agent's messages */ -const { WALLET_KEY, ENCRYPTION_KEY, GROK_API_KEY } = process.env; - -/* Check if the environment variables are set */ -if (!WALLET_KEY) { - throw new Error("WALLET_KEY must be set"); -} - -/* Check if the encryption key is set */ -if (!ENCRYPTION_KEY) { - throw new Error("ENCRYPTION_KEY must be set"); -} - -/* Check if the Grok API key is set */ -if (!GROK_API_KEY) { - throw new Error("GROK_API_KEY must be set"); -} - -/* Create the signer using viem and parse the encryption key for the local db */ -const signer = createSigner(WALLET_KEY); -const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY); - -/* Set the environment to dev or production */ -const env: XmtpEnv = "dev"; - -/** - * Main function to run the agent - */ -async function main() { - console.log(`Creating client on the '${env}' network...`); - /* Initialize the xmtp client */ - const client = await Client.create(signer, encryptionKey, { - env, - }); - - console.log("Syncing conversations..."); - /* Sync the conversations from the network to update the local db */ - await client.conversations.sync(); - - console.log( - `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}?env=${env}`, - ); - console.log("Waiting for messages..."); - /* Stream all messages from the network */ - const stream = client.conversations.streamAllMessages(); - - for await (const message of await stream) { - /* Ignore messages from the same agent or non-text messages */ - if ( - message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() || - message?.contentType?.typeId !== "text" - ) { - continue; - } - - console.log( - `Received message: ${message.content as string} by ${message.senderInboxId}`, - ); - - /* Get the conversation from the local db */ - const conversation = client.conversations.getConversationById( - message.conversationId, - ); - - /* If the conversation is not found, skip the message */ - if (!conversation) { - console.log("Unable to find conversation, skipping"); - continue; - } - - try { - /* Get the AI response from Grok */ - const response = await fetch("https://api.x.ai/v1/chat/completions", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${GROK_API_KEY}`, // Use the same API key variable - }, - body: JSON.stringify({ - messages: [ - { role: "system", content: "You are a test assistant." }, - { role: "user", content: message.content as string }, - ], - model: "grok-2-latest", - stream: false, - temperature: 0, - }), - }).then( - (res) => - res.json() as Promise<{ - choices: { message: { content: string } }[]; - }>, - ); - const aiResponse = response.choices[0]?.message?.content || ""; - console.log(`Sending AI response: ${aiResponse}`); - /* Send the AI response to the conversation */ - await conversation.send(aiResponse); - } catch (error) { - console.error("Error getting AI response:", error); - await conversation.send( - "Sorry, I encountered an error processing your message.", - ); - } - - console.log("Waiting for messages..."); - } -} - main().catch(console.error); ``` From d9982061a933fe9fb90f271fba92969c9c675b29 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:34:04 -0300 Subject: [PATCH 08/12] fix gen keys --- scripts/generateKeys.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/generateKeys.ts b/scripts/generateKeys.ts index a027360..d49280a 100644 --- a/scripts/generateKeys.ts +++ b/scripts/generateKeys.ts @@ -1,17 +1,14 @@ import { writeFile } from "node:fs/promises"; -import { dirname, join } from "node:path"; -import { fileURLToPath } from "node:url"; +import { join } from "node:path"; import { generatePrivateKey } from "viem/accounts"; import { generateEncryptionKeyHex } from "@/helpers"; -const __dirname = dirname(fileURLToPath(import.meta.url)); - console.log("Generating keys..."); const walletKey = generatePrivateKey(); const encryptionKeyHex = generateEncryptionKeyHex(); -const filePath = join(".", ".env"); +const filePath = join(process.cwd(), ".env"); await writeFile( filePath, From 091b3fe5f957c2acd9e7f57eee6f4a3dbd5ea1c5 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:38:50 -0300 Subject: [PATCH 09/12] removed scripts --- integrations/grok/package.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/integrations/grok/package.json b/integrations/grok/package.json index f1679b1..f1de7e0 100644 --- a/integrations/grok/package.json +++ b/integrations/grok/package.json @@ -4,18 +4,11 @@ "private": true, "type": "module", "scripts": { - "clean": "rimraf node_modules && yarn clean:dbs", - "clean:dbs": "rimraf *.db3* ||:", "dev": "tsx --env-file=.env index.ts", - "format": "prettier -w .", - "format:check": "prettier -c .", - "gen:keys": "tsx ../../scripts/generateKeys.ts", - "lint": "eslint .", - "typecheck": "tsc" + "gen:keys": "tsx ../../scripts/generateKeys.ts" }, "dependencies": { "@xmtp/node-sdk": "0.0.42", - "openai": "latest", "tsx": "^4.19.2", "uint8arrays": "^5.1.0", "viem": "^2.22.17" From d90372785c7111bcaaf356141c0fe5a1673e9a73 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:40:52 -0300 Subject: [PATCH 10/12] readme fix --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 09aeda9..40777ad 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,14 @@ yarn gen:keys > See all the available [examples](/examples/). -## Integrations +### Integrations Examples integrating XMTP with external libraries from the ecosystem - [grok](/integrations/grok/): Integration to Grok API +> See all the available [examples](/integrations/). + ## Web inbox Interact with the XMTP network using [xmtp.chat](https://xmtp.chat), the official web inbox for developers. From aa26803ec110c503e69488610d774ee5b7403d30 Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:41:23 -0300 Subject: [PATCH 11/12] grok api readme fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 40777ad..d64b9a2 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ yarn gen:keys Examples integrating XMTP with external libraries from the ecosystem -- [grok](/integrations/grok/): Integration to Grok API +- [grok](/integrations/grok/): Integrate XMTP to the Grok API > See all the available [examples](/integrations/). From 29d2b00e81c0385adb1d65e57c808b9a2f4cef5f Mon Sep 17 00:00:00 2001 From: fabri Date: Wed, 19 Feb 2025 14:42:13 -0300 Subject: [PATCH 12/12] lock --- yarn.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 39bc6b7..6f159de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -813,7 +813,6 @@ __metadata: resolution: "@integrations/gpt@workspace:integrations/grok" dependencies: "@xmtp/node-sdk": "npm:0.0.42" - openai: "npm:latest" tsx: "npm:^4.19.2" uint8arrays: "npm:^5.1.0" viem: "npm:^2.22.17"