Skip to content

Commit

Permalink
feature: discord v0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
caillef committed Jan 27, 2025
1 parent 6f29044 commit 0b2d5c8
Show file tree
Hide file tree
Showing 7 changed files with 521 additions and 54 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ STARKNET_PRIVATE_KEY=
# This is the current GraphQL to make the examples work
GRAPHQL_URL=https://api.cartridge.gg/x/sepolia-rc-18/torii

DRY_RUN=1
DRY_RUN=1

DISCORD_TOKEN=
171 changes: 171 additions & 0 deletions examples/example-discord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/**
* Example demonstrating a Discord bot using the Daydreams package.
* This bot can:
* - Reply to DMs
*/

import { Orchestrator } from "../packages/core/src/core/orchestrator";
import { HandlerRole } from "../packages/core/src/core/types";
import { DiscordClient } from "../packages/core/src/core/io/discord";
import { RoomManager } from "../packages/core/src/core/room-manager";
import { ChromaVectorDB } from "../packages/core/src/core/vector-db";
import { MessageProcessor } from "../packages/core/src/core/processors/message-processor";
import { LLMClient } from "../packages/core/src/core/llm-client";
import { env } from "../packages/core/src/core/env";
import { LogLevel } from "../packages/core/src/core/types";
import chalk from "chalk";
import { defaultCharacter } from "../packages/core/src/core/character";
import { z } from "zod";
import readline from "readline";
import { MongoDb } from "../packages/core/src/core/mongo-db";

async function main() {
const loglevel = LogLevel.DEBUG;

// Initialize core dependencies
const vectorDb = new ChromaVectorDB("discord_agent", {
chromaUrl: "http://localhost:8000",
logLevel: loglevel,
});

await vectorDb.purge(); // Clear previous session data

const roomManager = new RoomManager(vectorDb);

const llmClient = new LLMClient({
model: "anthropic/claude-3-5-sonnet-latest", // Using a known supported model
temperature: 0.3,
});

// Initialize processor with default character personality
const processor = new MessageProcessor(
llmClient,
defaultCharacter,
loglevel
);

// Initialize core system
const scheduledTaskDb = new MongoDb(
"mongodb://localhost:27017",
"myApp",
"scheduled_tasks"
);

await scheduledTaskDb.connect();
console.log(chalk.green("✅ Scheduled task database connected"));

await scheduledTaskDb.deleteAll();

// Initialize core system
const core = new Orchestrator(
roomManager,
vectorDb,
[processor],
scheduledTaskDb,
{
level: loglevel,
enableColors: true,
enableTimestamp: true,
}
);

function messageCreate(bot: any, message: any) {
const isMention =
message.mentions.users.findKey(
(user: any) => user.id === bot.id
) !== undefined;
if (isMention) {
core.dispatchToInput(
"discord_mention",
{
content: message.content,
sentBy: message.author.id,
channelId: message.channelId,
},
message.author.id
);
}
}

// Set up Twitter client with credentials
const discord = new DiscordClient(
{
discord_token: env.DISCORD_TOKEN,
},
loglevel,
{
messageCreate,
}
);

// Register input handler for Twitter mentions
core.registerIOHandler({
name: "discord_mention",
role: HandlerRole.INPUT,
handler: async (data: unknown) => {
const message = data as { content: string; sentBy: string };
console.log(chalk.blue("🔍 Received Discord mention..."));

return [message];
},
schema: z.object({
type: z.string(),
content: z.string(),
metadata: z.record(z.any()),
}),
});

// Register output handler for Twitter replies
core.registerIOHandler({
name: "discord_reply",
role: HandlerRole.OUTPUT,
handler: async (data: unknown) => {
const messageData = data as {
content: string;
channelId: string;
};
return discord.createMessageOutput().handler(messageData);
},
schema: z
.object({
content: z.string(),
channelId: z
.string()
.optional()
.describe("The channel ID of the message"),
})
.describe(
"If you have been tagged or mentioned in Discord, use this. This is for replying to a message."
),
});

// Set up readline interface
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

// Start the prompt loop
console.log(chalk.cyan("🤖 Bot is now running and monitoring Discord..."));
console.log(chalk.cyan("You can type messages in the console."));
console.log(chalk.cyan('Type "exit" to quit'));

// Handle graceful shutdown
process.on("SIGINT", async () => {
console.log(chalk.yellow("\n\nShutting down..."));

// Clean up resources
core.removeIOHandler("discord_mention");
core.removeIOHandler("discord_reply");
rl.close();

console.log(chalk.green("✅ Shutdown complete"));
process.exit(0);
});
}

// Run the example
main().catch((error) => {
console.error(chalk.red("Fatal error:"), error);
process.exit(1);
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"task": "bun run examples/example-basic.ts",
"twitter": "bun run examples/example-twitter.ts",
"server": "bun run examples/example-server.ts",
"discord": "bun run examples/example-discord.ts",
"api": "bun run examples/example-api.ts",
"ui": "pnpm --dir clients/example-ui run dev",
"test": "bun run packages/core",
Expand All @@ -21,6 +22,7 @@
"chalk": "^5.4.1",
"cors": "^2.8.5",
"express": "^4.21.2",
"discord.js": "^14.17.3",
"lerna": "^8.1.9",
"mongodb": "^6.12.0",
"prettier": "^3.4.2",
Expand Down
79 changes: 39 additions & 40 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,49 @@
"version": "0.0.2",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
"@types/bun": "latest"
},
"scripts": {
"start": "bun run src/main.ts",
"test": "vitest",
"build": "tsup --dts-resolve"
"start": "bun run src/main.ts",
"test": "vitest",
"build": "tsup --dts-resolve"
},
"peerDependencies": {
"typescript": "^5.0.0"
"typescript": "^5.0.0"
},
"dependencies": {
"@ai-sdk/amazon-bedrock": "^1.1.1",
"@ai-sdk/anthropic": "^1.1.1",
"@ai-sdk/azure": "^1.1.1",
"@ai-sdk/cerebras": "^0.1.1",
"@ai-sdk/cohere": "^1.1.1",
"@ai-sdk/deepinfra": "^0.1.1",
"@ai-sdk/deepseek": "^0.1.1",
"@ai-sdk/fireworks": "^0.1.1",
"@ai-sdk/google": "^1.1.1",
"@ai-sdk/google-vertex": "^2.1.1",
"@ai-sdk/groq": "^1.1.1",
"@ai-sdk/mistral": "^1.1.1",
"@ai-sdk/openai": "^1.1.1",
"@ai-sdk/togetherai": "^0.1.1",
"@ai-sdk/xai": "^1.1.1",
"@langchain/core": "^0.3.33",
"@langchain/textsplitters": "^0.1.0",
"@openrouter/ai-sdk-provider": "^0.0.6",
"@solana/web3.js": "^1.98.0",
"agent-twitter-client": "^0.0.16",
"ai": "^4.1.0",
"ajv": "^8.17.1",
"bs58": "^6.0.0",
"chromadb": "^1.9.4",
"chromadb-default-embed": "^2.13.2",
"ethers": "^6.13.5",
"mongodb": "^6.12.0",
"openai": "^4.76.0",
"starknet": "^6.11.0",
"tsup": "^8.3.5",
"vitest": "^2.1.8",
"zod": "^3.24.1",
"zod-to-json-schema": "^3.24.1"
"@ai-sdk/amazon-bedrock": "^1.1.1",
"@ai-sdk/anthropic": "^1.1.1",
"@ai-sdk/azure": "^1.1.1",
"@ai-sdk/cerebras": "^0.1.1",
"@ai-sdk/cohere": "^1.1.1",
"@ai-sdk/deepinfra": "^0.1.1",
"@ai-sdk/deepseek": "^0.1.1",
"@ai-sdk/fireworks": "^0.1.1",
"@ai-sdk/google": "^1.1.1",
"@ai-sdk/google-vertex": "^2.1.1",
"@ai-sdk/groq": "^1.1.1",
"@ai-sdk/mistral": "^1.1.1",
"@ai-sdk/openai": "^1.1.1",
"@ai-sdk/togetherai": "^0.1.1",
"@ai-sdk/xai": "^1.1.1",
"@langchain/core": "^0.3.33",
"@langchain/textsplitters": "^0.1.0",
"@openrouter/ai-sdk-provider": "^0.0.6",
"@solana/web3.js": "^1.98.0",
"agent-twitter-client": "^0.0.16",
"ai": "^4.1.0",
"ajv": "^8.17.1",
"bs58": "^6.0.0",
"chromadb": "^1.10.4",
"chromadb-default-embed": "^2.13.2",
"ethers": "^6.13.5",
"mongodb": "^6.12.0",
"openai": "^4.76.0",
"starknet": "^6.11.0",
"tsup": "^8.3.5",
"vitest": "^2.1.8",
"zod": "^3.24.1",
"zod-to-json-schema": "^3.24.1"
}
}

}
1 change: 1 addition & 0 deletions packages/core/src/core/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const envSchema = z.object({
STARKNET_PRIVATE_KEY: z.string(),
OPENROUTER_API_KEY: z.string(),
GRAPHQL_URL: z.string(),
DISCORD_TOKEN: z.string(),
WEBSOCKET_URL: z.string().default("ws://localhost:8080"),
DRY_RUN: z
.preprocess((val) => val === "1" || val === "true", z.boolean())
Expand Down
Loading

0 comments on commit 0b2d5c8

Please sign in to comment.