Skip to content

Commit

Permalink
Merge branch 'develop' into fix-plugin-thirdweb
Browse files Browse the repository at this point in the history
  • Loading branch information
AIFlowML authored Jan 27, 2025
2 parents 2de5105 + a7cefb8 commit 9a2233b
Show file tree
Hide file tree
Showing 93 changed files with 4,533 additions and 316 deletions.
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ DISCORD_VOICE_CHANNEL_ID= # The ID of the voice channel the bot should join (opt
# Devin Configuration
DEVIN_API_TOKEN= # Get your API key from docs.devin.ai/tutorials/api-integration

# Gelato Configuration
GELATO_RELAY_API_KEY= # Gelato API key

# Farcaster Neynar Configuration
FARCASTER_FID= # The FID associated with the account your are sending casts from
FARCASTER_NEYNAR_API_KEY= # Neynar API key: https://neynar.com/
Expand Down Expand Up @@ -517,8 +520,9 @@ APTOS_PRIVATE_KEY= # Aptos private key
APTOS_NETWORK= # Must be one of mainnet, testnet

# MultiversX
MVX_PRIVATE_KEY= # Multiversx private key
MVX_NETWORK= # must be one of mainnet, devnet, testnet
MVX_PRIVATE_KEY= # Multiversx private key
MVX_NETWORK= # must be one of mainnet, devnet, testnet
ACCESS_TOKEN_MANAGEMENT_TO=everyone # you can put an userid to limit token managament to one user only (use same id as in the database)

# NEAR
NEAR_WALLET_SECRET_KEY= # NEAR Wallet Secret Key
Expand Down
2 changes: 2 additions & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"@elizaos/plugin-initia": "workspace:*",
"@elizaos/plugin-image-generation": "workspace:*",
"@elizaos/plugin-lit": "workspace:*",
"@elizaos/plugin-gelato": "workspace:*",
"@elizaos/plugin-moralis": "workspace:*",
"@elizaos/plugin-mind-network": "workspace:*",
"@elizaos/plugin-movement": "workspace:*",
Expand Down Expand Up @@ -143,6 +144,7 @@
"@elizaos/plugin-dcap": "workspace:*",
"@elizaos/plugin-form": "workspace:*",
"@elizaos/plugin-ankr": "workspace:*",
"@elizaos/client-xmtp": "workspace:*",
"readline": "1.3.0",
"ws": "8.18.0",
"yargs": "17.7.2"
Expand Down
10 changes: 8 additions & 2 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import { MongoDBDatabaseAdapter } from "@elizaos/adapter-mongodb"
import { FarcasterClientInterface } from "@elizaos/client-farcaster"
import { OmniflixPlugin } from "@elizaos/plugin-omniflix"
import { JeeterClientInterface } from "@elizaos/client-simsai"

import { XmtpClientInterface } from "@elizaos/client-xmtp";
import { DirectClient } from "@elizaos/client-direct"
import { agentKitPlugin } from "@elizaos/plugin-agentkit"

import { gelatoPlugin } from "@elizaos/plugin-gelato";
import { PrimusAdapter } from "@elizaos/plugin-primus"
import { lightningPlugin } from "@elizaos/plugin-lightning"
import { elizaCodeinPlugin, onchainJson } from "@elizaos/plugin-iq6900"
Expand Down Expand Up @@ -627,6 +627,11 @@ export async function initializeClients(character: Character, runtime: IAgentRun
if (autoClient) clients.auto = autoClient
}

if (clientTypes.includes(Clients.XMTP)) {
const xmtpClient = await XmtpClientInterface.start(runtime);
if (xmtpClient) clients.xmtp = xmtpClient;
}

if (clientTypes.includes(Clients.DISCORD)) {
const discordClient = await DiscordClientInterface.start(runtime)
if (discordClient) clients.discord = discordClient
Expand Down Expand Up @@ -905,6 +910,7 @@ export async function createAgent(character: Character, db: IDatabaseAdapter, ca
getSecret(character, "ANKR_WALLET") ? ankrPlugin : null,
getSecret(character, "DCAP_EVM_PRIVATE_KEY") && getSecret(character, "DCAP_MODE") ? dcapPlugin : null,
getSecret(character, "QUICKINTEL_API_KEY") ? quickIntelPlugin : null,
getSecret(character, "GELATO_RELAY_API_KEY") ? gelatoPlugin : null,
].flat().filter(Boolean),
providers: [],
managers: [],
Expand Down
8 changes: 6 additions & 2 deletions docs/docs/advanced/infrastructure.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ const supabaseConfig = {
The memory system uses vector embeddings for semantic search:

```typescript
import { embed } from "@elizaos/core";

async function storeMemory(runtime: IAgentRuntime, content: string) {
const embedding = await runtime.embed(content);
const embedding = await embed(runtime, message.content.text);

await runtime.databaseAdapter.createMemory({
type: "message",
Expand All @@ -136,8 +138,10 @@ async function storeMemory(runtime: IAgentRuntime, content: string) {
### Memory Retrieval

```typescript
import { embed } from "@elizaos/core";

async function searchMemories(runtime: IAgentRuntime, query: string) {
const embedding = await runtime.embed(query);
const embedding = await embed(runtime, query);

return runtime.databaseAdapter.searchMemoriesByEmbedding(embedding, {
match_threshold: 0.8,
Expand Down
4 changes: 4 additions & 0 deletions docs/docs/packages/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ export async function initializeClients(
if (clientTypes.includes(Clients.DIRECT)) {
clients.push(await AutoClientInterface.start(runtime));
}
if (clientTypes.includes(Clients.XMTP)) {
const xmtpClient = await XmtpClientInterface.start(runtime);
if (xmtpClient) clients.xmtp = xmtpClient;
}

return clients;
}
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
"@0glabs/0g-ts-sdk": "0.2.1",
"@coinbase/coinbase-sdk": "0.10.0",
"@deepgram/sdk": "^3.9.0",
"@okxweb3/coin-bitcoin": "1.2.0",
"@okxweb3/crypto-lib": "1.0.10",
"@injectivelabs/sdk-ts": "^1.14.33",
"@vitest/eslint-plugin": "1.0.1",
"amqplib": "0.10.5",
Expand All @@ -74,7 +76,9 @@
"pnpm": "9.14.4",
"sharp": "0.33.5",
"tslog": "4.9.3",
"bs58": "4.0.0"
"bs58": "4.0.0",
"tiny-secp256k1": "2.2.3",
"tslog": "4.9.3"
},
"packageManager": "[email protected]+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee",
"workspaces": [
Expand Down
102 changes: 102 additions & 0 deletions packages/client-discord/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# @elizaos/client-discord

A Discord client implementation for ElizaOS, enabling rich integration with Discord servers for managing interactions, voice, and message handling.

## Features

- Handle server join events and manage initial configurations.
- Voice event management via the voice manager.
- Manage and process new messages with the message manager.
- Slash command registration and interaction handling.
- Disconnect websocket and unbind all listeners when required.
- Robust permissions management for bot functionality.

## Installation

As this is a workspace package, it's installed as part of the ElizaOS monorepo:

```bash
pnpm install
```

## Configuration

The client requires the following environment variables:

```bash
# Discord API Credentials
DISCORD_APPLICATION_ID=your_application_id
DISCORD_API_TOKEN=your_api_token

# Optional Settings (add any additional details here if necessary)
```

## Usage

### Basic Initialization

```typescript
import { DiscordClientInterface } from '@elizaos/client-discord';

// Initialize the client
const discordManager = await DiscordClientInterface.start(runtime);
```

### Slash Command Registration

To register slash commands:

```typescript
await discordManager.command.registerCommands([
{
name: 'example',
description: 'An example slash command',
options: []
}
]);
```

### Handling Messages

```typescript
// Listen for new messages
await discordManager.message.handleNewMessage({
channelId: 'channel-id',
content: 'Hello Discord!'
});
```

### Managing Voice Events

```typescript
// Join a voice channel
await discordManager.voice.joinChannel('channel-id');

// Handle voice interactions
await discordManager.voice.handleInteraction({
userId: 'user-id',
action: 'speak'
});
```

## Key Components

1. **ClientBase**
- Handles authentication and session management.
- Manages websocket connections.

2. **MessageManager**
- Processes incoming messages and responses.
- Supports message formatting and templating.

3. **VoiceManager**
- Manages voice interactions and events.
- Handles joining and leaving voice channels.

4. **CommandManager**
- Registers and processes slash commands.
- Ensures permissions are validated.

## Notes

Ensure that your `.env` file includes the required environment variables for proper functionality. Additional features or modules can be extended as part of the ElizaOS framework.
37 changes: 18 additions & 19 deletions packages/client-discord/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function getWavHeader(
audioLength: number,
sampleRate: number,
channelCount = 1,
bitsPerSample = 16
bitsPerSample = 16,
): Buffer {
const wavHeader = Buffer.alloc(44);
wavHeader.write("RIFF", 0);
Expand All @@ -31,7 +31,7 @@ export function getWavHeader(
wavHeader.writeUInt32LE(sampleRate, 24); // Sample rate
wavHeader.writeUInt32LE(
(sampleRate * bitsPerSample * channelCount) / 8,
28
28,
); // Byte rate
wavHeader.writeUInt16LE((bitsPerSample * channelCount) / 8, 32); // Block align ((BitsPerSample * Channels) / 8)
wavHeader.writeUInt16LE(bitsPerSample, 34); // Bits per sample
Expand All @@ -44,7 +44,7 @@ const MAX_MESSAGE_LENGTH = 1900;

export async function generateSummary(
runtime: IAgentRuntime,
text: string
text: string,
): Promise<{ title: string; description: string }> {
// make sure text is under 128k characters
text = await trimTokens(text, 100000, runtime);
Expand All @@ -71,7 +71,7 @@ export async function generateSummary(

const parsedResponse = parseJSONObjectFromText(response);

if (parsedResponse) {
if (parsedResponse.title && parsedResponse.summary) {
return {
title: parsedResponse.title,
description: parsedResponse.summary,
Expand All @@ -88,7 +88,7 @@ export async function sendMessageInChunks(
channel: TextChannel,
content: string,
inReplyTo: string,
files: any[]
files: any[],
): Promise<DiscordMessage[]> {
const sentMessages: DiscordMessage[] = [];
const messages = splitMessage(content);
Expand Down Expand Up @@ -132,16 +132,15 @@ function splitMessage(content: string): string[] {

const rawLines = content?.split("\n") || [];
// split all lines into MAX_MESSAGE_LENGTH chunks so any long lines are split
const lines = rawLines
.flatMap((line) => {
const chunks = [];
while (line.length > MAX_MESSAGE_LENGTH) {
chunks.push(line.slice(0, MAX_MESSAGE_LENGTH));
line = line.slice(MAX_MESSAGE_LENGTH);
}
chunks.push(line);
return chunks;
});
const lines = rawLines.flatMap((line) => {
const chunks = [];
while (line.length > MAX_MESSAGE_LENGTH) {
chunks.push(line.slice(0, MAX_MESSAGE_LENGTH));
line = line.slice(MAX_MESSAGE_LENGTH);
}
chunks.push(line);
return chunks;
});

for (const line of lines) {
if (currentMessage.length + line.length + 1 > MAX_MESSAGE_LENGTH) {
Expand Down Expand Up @@ -192,7 +191,7 @@ export function canSendMessage(channel) {
// Add thread-specific permission if it's a thread
if (channel instanceof ThreadChannel) {
requiredPermissions.push(
PermissionsBitField.Flags.SendMessagesInThreads
PermissionsBitField.Flags.SendMessagesInThreads,
);
}

Expand All @@ -208,7 +207,7 @@ export function canSendMessage(channel) {

// Check each required permission
const missingPermissions = requiredPermissions.filter(
(perm) => !permissions.has(perm)
(perm) => !permissions.has(perm),
);

return {
Expand All @@ -224,7 +223,7 @@ export function canSendMessage(channel) {
export function cosineSimilarity(
text1: string,
text2: string,
text3?: string
text3?: string,
): number {
const preprocessText = (text: string) =>
text
Expand Down Expand Up @@ -306,7 +305,7 @@ export function cosineSimilarity(
const maxMagnitude = Math.max(
magnitude1 * magnitude2,
magnitude2 * magnitude3,
magnitude1 * magnitude3
magnitude1 * magnitude3,
);

return dotProduct / maxMagnitude;
Expand Down
2 changes: 1 addition & 1 deletion packages/client-farcaster/src/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export class FarcasterInteractionManager {
await this.handleInteractions();
} catch (error) {
elizaLogger.error(error);
return;
}

// Always set up next check, even if there was an error
this.timeout = setTimeout(
handleInteractionsLoop,
Number(this.client.farcasterConfig?.FARCASTER_POLL_INTERVAL ?? 120) *
Expand Down
Loading

0 comments on commit 9a2233b

Please sign in to comment.