From 1417f0b485ab5940aa4e30064e08e2ea9537bdd5 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sat, 2 Nov 2024 19:37:05 +1100
Subject: [PATCH 01/23] mods

---
 core/src/clients/discord/index.ts    | 9 +++++++--
 core/src/clients/twitter/generate.ts | 2 +-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/core/src/clients/discord/index.ts b/core/src/clients/discord/index.ts
index a0a9f70d09a..bb2d5eabdca 100644
--- a/core/src/clients/discord/index.ts
+++ b/core/src/clients/discord/index.ts
@@ -37,7 +37,9 @@ export class DiscordClient extends EventEmitter {
 
     constructor(runtime: IAgentRuntime) {
         super();
-        this.apiToken = runtime.getSetting("DISCORD_API_TOKEN") as string;
+        this.apiToken = runtime.getSetting(
+            "DISCORD_API_TOKEN_" + runtime.character.name.toUpperCase()
+        ) as string;
         this.client = new Client({
             intents: [
                 GatewayIntentBits.Guilds,
@@ -120,7 +122,10 @@ export class DiscordClient extends EventEmitter {
             try {
                 await rest.put(
                     Routes.applicationCommands(
-                        this.runtime.getSetting("DISCORD_APPLICATION_ID")
+                        this.runtime.getSetting(
+                            "DISCORD_APPLICATION_ID_" +
+                                this.runtime.character.name.toUpperCase()
+                        )
                     ),
                     { body: commands }
                 );
diff --git a/core/src/clients/twitter/generate.ts b/core/src/clients/twitter/generate.ts
index af8148821fa..f2de43b9aa9 100644
--- a/core/src/clients/twitter/generate.ts
+++ b/core/src/clients/twitter/generate.ts
@@ -109,7 +109,7 @@ export class TwitterGenerationClient extends ClientBase {
             const newTweetContent = await generateText({
                 runtime: this.runtime,
                 context,
-                modelClass: ModelClass.LARGE,
+                modelClass: ModelClass.SMALL,
             });
             console.log("New Tweet:", newTweetContent);
             log_to_file(

From 46139a16568e58f85efd49e2acd21990647a6146 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sat, 2 Nov 2024 20:31:34 +1100
Subject: [PATCH 02/23] fix anthropic

---
 core/src/core/generation.ts | 128 ++++++++++++++++++------------------
 core/src/core/models.ts     |  12 ++--
 2 files changed, 69 insertions(+), 71 deletions(-)

diff --git a/core/src/core/generation.ts b/core/src/core/generation.ts
index 0191676978a..79bf2729778 100644
--- a/core/src/core/generation.ts
+++ b/core/src/core/generation.ts
@@ -13,7 +13,8 @@ import models from "./models.ts";
 
 import { generateText as aiGenerateText } from "ai";
 import { createAnthropicVertex } from "anthropic-vertex-ai";
-
+import Anthropic from "@anthropic-ai/sdk";
+import { createAnthropic } from "@ai-sdk/anthropic";
 /**
  * Send a message to the model for a text generateText - receive a string back and parse how you'd like
  * @param opts - The options for the generateText request.
@@ -68,64 +69,62 @@ export async function generateText({
 
         switch (provider) {
             case ModelProvider.OPENAI:
-            case ModelProvider.LLAMACLOUD:
-                {
-                    console.log("Initializing OpenAI model.");
-                    const openai = createOpenAI({ apiKey });
-
-                    const { text: openaiResponse } = await aiGenerateText({
-                        model: openai.languageModel(model),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = openaiResponse;
-                    console.log("Received response from OpenAI model.");
-                    break;
-                }
-
-            case ModelProvider.ANTHROPIC:
-                {
-                    console.log("Initializing Anthropic model.");
-                    const anthropicVertex = createAnthropicVertex();
-
-                    const { text: anthropicResponse } = await aiGenerateText({
-                        model: anthropicVertex(model),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = anthropicResponse;
-                    console.log("Received response from Anthropic model.");
-                    break;
-                }
-
-            case ModelProvider.GROK:
-                {
-                    console.log("Initializing Grok model.");
-                    const grok = createGroq({ apiKey });
-
-                    const { text: grokResponse } = await aiGenerateText({
-                        model: grok.languageModel(model, {
-                            parallelToolCalls: false,
-                        }),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = grokResponse;
-                    console.log("Received response from Grok model.");
-                    break;
-                }
+            case ModelProvider.LLAMACLOUD: {
+                console.log("Initializing OpenAI model.");
+                const openai = createOpenAI({ apiKey });
+
+                const { text: openaiResponse } = await aiGenerateText({
+                    model: openai.languageModel(model),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = openaiResponse;
+                console.log("Received response from OpenAI model.");
+                break;
+            }
+
+            case ModelProvider.ANTHROPIC: {
+                console.log("Initializing Anthropic model.");
+
+                const anthropic = createAnthropic({ apiKey });
+
+                const { text: anthropicResponse } = await aiGenerateText({
+                    model: anthropic.languageModel(model),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = anthropicResponse;
+                console.log("Received response from Anthropic model.");
+                break;
+            }
+
+            case ModelProvider.GROK: {
+                console.log("Initializing Grok model.");
+                const grok = createGroq({ apiKey });
+
+                const { text: grokResponse } = await aiGenerateText({
+                    model: grok.languageModel(model, {
+                        parallelToolCalls: false,
+                    }),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = grokResponse;
+                console.log("Received response from Grok model.");
+                break;
+            }
 
             case ModelProvider.LLAMALOCAL:
                 console.log("Using local Llama model for text completion.");
@@ -140,12 +139,11 @@ export async function generateText({
                 console.log("Received response from local Llama model.");
                 break;
 
-            default:
-                {
-                    const errorMessage = `Unsupported provider: ${provider}`;
-                    console.error(errorMessage);
-                    throw new Error(errorMessage);
-                }
+            default: {
+                const errorMessage = `Unsupported provider: ${provider}`;
+                console.error(errorMessage);
+                throw new Error(errorMessage);
+            }
         }
 
         return response;
diff --git a/core/src/core/models.ts b/core/src/core/models.ts
index 1c973bca07a..b04b8893b21 100644
--- a/core/src/core/models.ts
+++ b/core/src/core/models.ts
@@ -40,9 +40,9 @@ const models: Models = {
         },
         endpoint: "https://api.anthropic.com/v1",
         model: {
-            [ModelClass.SMALL]: "claude-3-haiku",
-            [ModelClass.MEDIUM]: "claude-3-5-sonnet",
-            [ModelClass.LARGE]: "claude-3-opus",
+            [ModelClass.SMALL]: "claude-3-5-sonnet-20241022",
+            [ModelClass.MEDIUM]: "claude-3-5-sonnet-20241022",
+            [ModelClass.LARGE]: "claude-3-opus-20240229",
         },
     },
     [ModelProvider.CLAUDE_VERTEX]: {
@@ -56,9 +56,9 @@ const models: Models = {
         },
         endpoint: "https://api.anthropic.com/v1", // TODO: check
         model: {
-            [ModelClass.SMALL]: "claude-3-haiku",
-            [ModelClass.MEDIUM]: "claude-3-5-sonnet",
-            [ModelClass.LARGE]: "claude-3-opus",
+            [ModelClass.SMALL]: "claude-3-5-sonnet-20241022",
+            [ModelClass.MEDIUM]: "claude-3-5-sonnet-20241022",
+            [ModelClass.LARGE]: "claude-3-opus-20240229",
         },
     },
     [ModelProvider.GROK]: {

From 5f8801377bee991523095fb5c038a2eda7368b17 Mon Sep 17 00:00:00 2001
From: moon <shawmakesmagic@gmail.com>
Date: Sat, 2 Nov 2024 05:44:27 -0700
Subject: [PATCH 03/23] fixes and summarize

---
 core/package.json                             |   2 +-
 core/src/adapters/postgres.ts                 |   4 +-
 core/src/adapters/sqlite.ts                   |   6 +-
 core/src/adapters/supabase.ts                 |   3 +-
 core/src/cli/index.ts                         |   2 +
 .../discord/actions/summarize_conversation.ts |   6 +-
 core/src/clients/discord/messages.ts          |  27 ++--
 core/src/clients/twitter/base.ts              |   7 +-
 core/src/core/generation.ts                   | 124 +++++++++---------
 core/src/core/models.ts                       |   2 +-
 core/src/core/runtime.ts                      |   7 +-
 core/src/services/speech.ts                   |   5 +-
 core/tsconfig.json                            |   1 -
 13 files changed, 97 insertions(+), 99 deletions(-)

diff --git a/core/package.json b/core/package.json
index d404e41d750..a79f14f72a6 100644
--- a/core/package.json
+++ b/core/package.json
@@ -20,7 +20,7 @@
         "start:degen": "node --loader ts-node/esm src/index.ts --characters=\"../characters/degenspartan.json\"",
         "start:service:all": "pm2 start npm --name=\"all\" --restart-delay=3000 --max-restarts=10 -- run start:degen",
         "stop:service:all": "pm2 stop all",
-        "start:all": "node --loader ts-node/esm src/index.ts --characters=\"../characters/degenspartan.json\",\"../characters/ruby.character.json\"",
+        "start:all": "node --loader ts-node/esm src/index.ts --characters=\"../characters/degenspartan.json\",\"../characters/ruby.character.json\",\"../characters/pmairca.character.json\"",
         "start:trump": "node --loader ts-node/esm src/index.ts --characters=\"../characters/trump.character.json\"",
         "start:service:tate": "pm2 start npm --name=\"tate\" --restart-delay=3000 --max-restarts=10 -- run start:tate",
         "stop:service:tate": "pm2 stop tate",
diff --git a/core/src/adapters/postgres.ts b/core/src/adapters/postgres.ts
index c2f6d154268..d7180c0a363 100644
--- a/core/src/adapters/postgres.ts
+++ b/core/src/adapters/postgres.ts
@@ -110,7 +110,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
             const placeholders = params.roomIds
                 .map((_, i) => `$${i + 2}`)
                 .join(", ");
-            
+
             let query = `SELECT * FROM memories WHERE type = $1 AND "roomId" IN (${placeholders})`;
             let queryParams = [params.tableName, ...params.roomIds];
 
@@ -635,7 +635,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
 
             if (params.unique) {
                 sql += ` AND "unique" = true`;
-                }
+            }
 
             // TODO: Test this
             if (params.agentId) {
diff --git a/core/src/adapters/sqlite.ts b/core/src/adapters/sqlite.ts
index 6889b2d6544..68afeb1afc6 100644
--- a/core/src/adapters/sqlite.ts
+++ b/core/src/adapters/sqlite.ts
@@ -160,7 +160,7 @@ export class SqliteDatabaseAdapter extends DatabaseAdapter {
         const placeholders = params.roomIds.map(() => "?").join(", ");
         let sql = `SELECT * FROM memories WHERE type = ? AND roomId IN (${placeholders})`;
         let queryParams = [params.tableName, ...params.roomIds];
-            
+
         if (params.agentId) {
             sql += ` AND userId = ?`;
             queryParams.push(params.agentId);
@@ -171,9 +171,9 @@ export class SqliteDatabaseAdapter extends DatabaseAdapter {
             content: string;
         })[];
 
-        return rows.map(row => ({
+        return rows.map((row) => ({
             ...row,
-            content: JSON.parse(row.content)
+            content: JSON.parse(row.content),
         }));
     }
 
diff --git a/core/src/adapters/supabase.ts b/core/src/adapters/supabase.ts
index 3efe5f2906b..0b97f895b05 100644
--- a/core/src/adapters/supabase.ts
+++ b/core/src/adapters/supabase.ts
@@ -318,7 +318,6 @@ export class SupabaseDatabaseAdapter extends DatabaseAdapter {
             tableName: string;
         }
     ): Promise<Memory[]> {
-
         const queryParams = {
             query_table_name: params.tableName,
             query_roomId: params.roomId,
@@ -326,7 +325,7 @@ export class SupabaseDatabaseAdapter extends DatabaseAdapter {
             query_match_threshold: params.match_threshold,
             query_match_count: params.count,
             query_unique: !!params.unique,
-        }
+        };
         if (params.agentId) {
             (queryParams as any).query_agentId = params.agentId;
         }
diff --git a/core/src/cli/index.ts b/core/src/cli/index.ts
index ad14b208c6a..90c5ef46d41 100644
--- a/core/src/cli/index.ts
+++ b/core/src/cli/index.ts
@@ -123,6 +123,8 @@ export async function createAgentRuntime(
     const actionConfigs = loadActionConfigs(configPath);
     const customActions = await loadCustomActions(actionConfigs);
 
+    console.log("Creating runtime for character", character.name);
+
     return new AgentRuntime({
         databaseAdapter: db,
         token,
diff --git a/core/src/clients/discord/actions/summarize_conversation.ts b/core/src/clients/discord/actions/summarize_conversation.ts
index 952b234b0f0..3247b177f37 100644
--- a/core/src/clients/discord/actions/summarize_conversation.ts
+++ b/core/src/clients/discord/actions/summarize_conversation.ts
@@ -145,7 +145,11 @@ const summarizeAction = {
         "CONVERSATION_SUMMARY",
     ],
     description: "Summarizes the conversation and attachments.",
-    validate: async (runtime: IAgentRuntime, message: Memory, _state: State) => {
+    validate: async (
+        runtime: IAgentRuntime,
+        message: Memory,
+        _state: State
+    ) => {
         if (message.content.source !== "discord") {
             return false;
         }
diff --git a/core/src/clients/discord/messages.ts b/core/src/clients/discord/messages.ts
index 20cdd4ac23d..ac3718cbe8b 100644
--- a/core/src/clients/discord/messages.ts
+++ b/core/src/clients/discord/messages.ts
@@ -1,4 +1,9 @@
-import { ChannelType, Client, Message as DiscordMessage, TextChannel } from "discord.js";
+import {
+    ChannelType,
+    Client,
+    Message as DiscordMessage,
+    TextChannel,
+} from "discord.js";
 import { composeContext } from "../../core/context.ts";
 import {
     generateMessageResponse,
@@ -153,17 +158,6 @@ export class MessageManager {
 
             const messageId = stringToUuid(message.id);
 
-            // Check if the message already exists in the cache or database
-            const existingMessage =
-                await this.runtime.messageManager.getMemoryById(messageId);
-
-            if (existingMessage) {
-                // If the message content is the same, return early
-                if (existingMessage.content.text === message.content) {
-                    return;
-                }
-            }
-
             let shouldIgnore = false;
             let shouldRespond = true;
 
@@ -271,10 +265,11 @@ export class MessageManager {
                 }
                 if (message.channel.type === ChannelType.GuildVoice) {
                     // For voice channels, use text-to-speech
-                    const audioStream = await this.runtime.speechService.generate(
-                        this.runtime,
-                        content.text
-                    );
+                    const audioStream =
+                        await this.runtime.speechService.generate(
+                            this.runtime,
+                            content.text
+                        );
                     await this.voiceManager.playAudioStream(
                         userId,
                         audioStream
diff --git a/core/src/clients/twitter/base.ts b/core/src/clients/twitter/base.ts
index be5cd05ff4d..2bc06e43d78 100644
--- a/core/src/clients/twitter/base.ts
+++ b/core/src/clients/twitter/base.ts
@@ -404,7 +404,8 @@ export class ClientBase extends EventEmitter {
                 // Save the missing tweets as memories
                 for (const tweet of tweetsToSave) {
                     const roomId = stringToUuid(
-                        tweet.conversationId ?? "default-room-" + this.runtime.agentId
+                        tweet.conversationId ??
+                            "default-room-" + this.runtime.agentId
                     );
                     const tweetuserId =
                         tweet.userId === this.twitterUserId
@@ -508,7 +509,9 @@ export class ClientBase extends EventEmitter {
 
         // Save the new tweets as memories
         for (const tweet of tweetsToSave) {
-            const roomId = stringToUuid(tweet.conversationId ?? "default-room-" + this.runtime.agentId);
+            const roomId = stringToUuid(
+                tweet.conversationId ?? "default-room-" + this.runtime.agentId
+            );
             const tweetuserId =
                 tweet.userId === this.twitterUserId
                     ? this.runtime.agentId
diff --git a/core/src/core/generation.ts b/core/src/core/generation.ts
index 0191676978a..db6eb85c206 100644
--- a/core/src/core/generation.ts
+++ b/core/src/core/generation.ts
@@ -68,64 +68,61 @@ export async function generateText({
 
         switch (provider) {
             case ModelProvider.OPENAI:
-            case ModelProvider.LLAMACLOUD:
-                {
-                    console.log("Initializing OpenAI model.");
-                    const openai = createOpenAI({ apiKey });
-
-                    const { text: openaiResponse } = await aiGenerateText({
-                        model: openai.languageModel(model),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = openaiResponse;
-                    console.log("Received response from OpenAI model.");
-                    break;
-                }
-
-            case ModelProvider.ANTHROPIC:
-                {
-                    console.log("Initializing Anthropic model.");
-                    const anthropicVertex = createAnthropicVertex();
-
-                    const { text: anthropicResponse } = await aiGenerateText({
-                        model: anthropicVertex(model),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = anthropicResponse;
-                    console.log("Received response from Anthropic model.");
-                    break;
-                }
-
-            case ModelProvider.GROK:
-                {
-                    console.log("Initializing Grok model.");
-                    const grok = createGroq({ apiKey });
-
-                    const { text: grokResponse } = await aiGenerateText({
-                        model: grok.languageModel(model, {
-                            parallelToolCalls: false,
-                        }),
-                        prompt: context,
-                        temperature: temperature,
-                        maxTokens: max_response_length,
-                        frequencyPenalty: frequency_penalty,
-                        presencePenalty: presence_penalty,
-                    });
-
-                    response = grokResponse;
-                    console.log("Received response from Grok model.");
-                    break;
-                }
+            case ModelProvider.LLAMACLOUD: {
+                console.log("Initializing OpenAI model.");
+                const openai = createOpenAI({ apiKey });
+
+                const { text: openaiResponse } = await aiGenerateText({
+                    model: openai.languageModel(model),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = openaiResponse;
+                console.log("Received response from OpenAI model.");
+                break;
+            }
+
+            case ModelProvider.ANTHROPIC: {
+                console.log("Initializing Anthropic model.");
+                const anthropicVertex = createAnthropicVertex();
+
+                const { text: anthropicResponse } = await aiGenerateText({
+                    model: anthropicVertex(model),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = anthropicResponse;
+                console.log("Received response from Anthropic model.");
+                break;
+            }
+
+            case ModelProvider.GROK: {
+                console.log("Initializing Grok model.");
+                const grok = createGroq({ apiKey });
+
+                const { text: grokResponse } = await aiGenerateText({
+                    model: grok.languageModel(model, {
+                        parallelToolCalls: false,
+                    }),
+                    prompt: context,
+                    temperature: temperature,
+                    maxTokens: max_response_length,
+                    frequencyPenalty: frequency_penalty,
+                    presencePenalty: presence_penalty,
+                });
+
+                response = grokResponse;
+                console.log("Received response from Grok model.");
+                break;
+            }
 
             case ModelProvider.LLAMALOCAL:
                 console.log("Using local Llama model for text completion.");
@@ -140,12 +137,11 @@ export async function generateText({
                 console.log("Received response from local Llama model.");
                 break;
 
-            default:
-                {
-                    const errorMessage = `Unsupported provider: ${provider}`;
-                    console.error(errorMessage);
-                    throw new Error(errorMessage);
-                }
+            default: {
+                const errorMessage = `Unsupported provider: ${provider}`;
+                console.error(errorMessage);
+                throw new Error(errorMessage);
+            }
         }
 
         return response;
diff --git a/core/src/core/models.ts b/core/src/core/models.ts
index 1c973bca07a..e4675209221 100644
--- a/core/src/core/models.ts
+++ b/core/src/core/models.ts
@@ -25,7 +25,7 @@ const models: Models = {
         model: {
             [ModelClass.SMALL]: "gpt-4o-mini",
             [ModelClass.MEDIUM]: "gpt-4o",
-            [ModelClass.LARGE]: "gpt-4-turbo",
+            [ModelClass.LARGE]: "gpt-4o",
             [ModelClass.EMBEDDING]: "text-embedding-3-small",
         },
     },
diff --git a/core/src/core/runtime.ts b/core/src/core/runtime.ts
index 0eb79542050..dce60d50c95 100644
--- a/core/src/core/runtime.ts
+++ b/core/src/core/runtime.ts
@@ -273,9 +273,12 @@ export class AgentRuntime implements IAgentRuntime {
             this.registerContextProvider(provider);
         });
 
-        if (!this.getSetting("OPENAI_API_KEY") && !this.llamaService) {
+        if (
+            this.modelProvider === ModelProvider.LLAMALOCAL &&
+            !this.llamaService
+        ) {
             console.log(
-                "No OpenAI key found, using LlamaLocal for agent",
+                "Initializing LlamaLocal service for agent",
                 this.agentId,
                 this.character.name
             );
diff --git a/core/src/services/speech.ts b/core/src/services/speech.ts
index b658cbf645e..94ae9787dc0 100644
--- a/core/src/services/speech.ts
+++ b/core/src/services/speech.ts
@@ -107,10 +107,7 @@ async function textToSpeech(runtime: IAgentRuntime, text: string) {
 }
 
 export class SpeechService implements ISpeechService {
-    async generate(
-        runtime: IAgentRuntime,
-        text: string
-    ): Promise<Readable> {
+    async generate(runtime: IAgentRuntime, text: string): Promise<Readable> {
         // check for elevenlabs API key
         if (runtime.getSetting("ELEVENLABS_XI_API_KEY")) {
             return textToSpeech(runtime, text);
diff --git a/core/tsconfig.json b/core/tsconfig.json
index 43b1ed20e5b..3527f3ee01e 100644
--- a/core/tsconfig.json
+++ b/core/tsconfig.json
@@ -3,7 +3,6 @@
         "target": "es2022",
         "module": "es2022",
         "lib": ["es2023", "dom"],
-        "types": ["node"],
         "moduleResolution": "bundler",
         "outDir": "./dist",
         "rootDir": "./src",

From 362470ad51a96ec2599a4a5496ce2e4754809133 Mon Sep 17 00:00:00 2001
From: MarcoMandar <malicemandar@gmail.com>
Date: Sat, 2 Nov 2024 14:55:10 +0200
Subject: [PATCH 04/23] update virtualConfidence

Signed-off-by: MarcoMandar <malicemandar@gmail.com>
---
 core/src/providers/trustScoreProvider.ts | 30 +++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/core/src/providers/trustScoreProvider.ts b/core/src/providers/trustScoreProvider.ts
index 0077d926f43..f1a4df47df2 100644
--- a/core/src/providers/trustScoreProvider.ts
+++ b/core/src/providers/trustScoreProvider.ts
@@ -7,7 +7,7 @@ import {
     // HolderData,
 } from "../types/token";
 import { Connection, PublicKey } from "@solana/web3.js";
-
+import { getAssociatedTokenAddress } from "@solana/spl-token";
 import { TokenProvider } from "./token";
 import WalletProvider from "./balances";
 import {
@@ -30,6 +30,8 @@ interface sellDetails {
 export class TrustScoreProvider {
     private tokenProvider: TokenProvider;
     private trustScoreDb: TrustScoreDatabase;
+    private connection: Connection = new Connection(process.env.RPC_URL!);
+    private baseMint: PublicKey = new PublicKey(process.env.BASE_MINT!);
 
     constructor(
         tokenProvider: TokenProvider,
@@ -38,6 +40,25 @@ export class TrustScoreProvider {
         this.tokenProvider = tokenProvider;
         this.trustScoreDb = trustScoreDb;
     }
+
+    //getRecommenederBalance
+    async getRecommenederBalance(recommenderWallet: string): Promise<number> {
+        try {
+            const tokenAta = await getAssociatedTokenAddress(
+                new PublicKey(recommenderWallet),
+                this.baseMint
+            );
+            const tokenBalInfo =
+                await this.connection.getTokenAccountBalance(tokenAta);
+            const tokenBalance = tokenBalInfo.value.amount;
+            const balance = parseFloat(tokenBalance);
+            return balance;
+        } catch (error) {
+            console.error("Error fetching balance", error);
+            return 0;
+        }
+    }
+
     /**
      * Generates and saves trust score based on processed token data and user recommendations.
      * @param tokenAddress The address of the token to analyze.
@@ -46,7 +67,8 @@ export class TrustScoreProvider {
      */
     async generateTrustScore(
         tokenAddress: string,
-        recommenderId: string
+        recommenderId: string,
+        recommenderWallet: string
     ): Promise<{
         tokenPerformance: TokenPerformance;
         recommenderMetrics: RecommenderMetrics;
@@ -61,6 +83,8 @@ export class TrustScoreProvider {
         const isRapidDump = await this.isRapidDump(tokenAddress);
         const sustainedGrowth = await this.sustainedGrowth(tokenAddress);
         const suspiciousVolume = await this.suspiciousVolume(tokenAddress);
+        const balance = await this.getRecommenederBalance(recommenderWallet);
+        const virtualConfidence = balance / 1000000; // TODO: create formula to calculate virtual confidence based on user balance
 
         return {
             tokenPerformance: {
@@ -93,7 +117,7 @@ export class TrustScoreProvider {
                 avgTokenPerformance: recommenderMetrics.avgTokenPerformance,
                 riskScore: recommenderMetrics.riskScore,
                 consistencyScore: recommenderMetrics.consistencyScore,
-                virtualConfidence: recommenderMetrics.virtualConfidence,
+                virtualConfidence: virtualConfidence,
                 lastUpdated: new Date(),
             },
         };

From 1c64b0ba3e07b230a19a69b6b36e11c8f5e4da3c Mon Sep 17 00:00:00 2001
From: moon <shawmakesmagic@gmail.com>
Date: Sat, 2 Nov 2024 05:57:24 -0700
Subject: [PATCH 05/23] chang to pnpm and add fix for start

---
 .vscode/launch.json |  4 ++--
 core/package.json   | 16 ++++++++--------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 73bb1792895..30a1891bdc1 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -7,8 +7,8 @@
         {
             "type": "node",
             "request": "launch",
-            "name": "Launch via npm",
-            "runtimeExecutable": "npm",
+            "name": "Launch via pnpm",
+            "runtimeExecutable": "pnpm",
             "runtimeArgs": ["run", "dev"],
             "skipFiles": ["<node_internals>/**"]
         }
diff --git a/core/package.json b/core/package.json
index a79f14f72a6..686a0228666 100644
--- a/core/package.json
+++ b/core/package.json
@@ -10,24 +10,24 @@
         "lint": "eslint . --fix",
         "start": "node --loader ts-node/esm src/index.ts",
         "start:arok": "node --loader ts-node/esm src/index.ts --characters=\"../characters/arok.character.json\"",
-        "start:service:ruby": "pm2 start npm --name=\"ruby\" --restart-delay=3000 --max-restarts=10 -- run start:ruby",
+        "start:service:ruby": "pm2 start pnpm --name=\"ruby\" --restart-delay=3000 --max-restarts=10 -- run start:ruby",
         "stop:service:ruby": "pm2 stop ruby",
         "start:ruby": "node --loader ts-node/esm src/index.ts --characters=\"../characters/ruby.character.json\"",
-        "start:service:trump": "pm2 start npm --name=\"trump\" --restart-delay=3000 --max-restarts=10 -- run start:trump",
+        "start:service:trump": "pm2 start pnpm --name=\"trump\" --restart-delay=3000 --max-restarts=10 -- run start:trump",
         "stop:service:trump": "pm2 stop trump",
-        "start:service:degen": "pm2 start npm --name=\"degen\" --restart-delay=3000 --max-restarts=10 -- run start:degen",
+        "start:service:degen": "pm2 start pnpm --name=\"degen\" --restart-delay=3000 --max-restarts=10 -- run start:degen",
         "stop:service:degen": "pm2 stop degen",
         "start:degen": "node --loader ts-node/esm src/index.ts --characters=\"../characters/degenspartan.json\"",
-        "start:service:all": "pm2 start npm --name=\"all\" --restart-delay=3000 --max-restarts=10 -- run start:degen",
+        "start:service:all": "pm2 start pnpm --name=\"all\" --restart-delay=3000 --max-restarts=10 -- run start:all",
         "stop:service:all": "pm2 stop all",
         "start:all": "node --loader ts-node/esm src/index.ts --characters=\"../characters/degenspartan.json\",\"../characters/ruby.character.json\",\"../characters/pmairca.character.json\"",
         "start:trump": "node --loader ts-node/esm src/index.ts --characters=\"../characters/trump.character.json\"",
-        "start:service:tate": "pm2 start npm --name=\"tate\" --restart-delay=3000 --max-restarts=10 -- run start:tate",
+        "start:service:tate": "pm2 start pnpm --name=\"tate\" --restart-delay=3000 --max-restarts=10 -- run start:tate",
         "stop:service:tate": "pm2 stop tate",
         "start:tate": "node --loader ts-node/esm src/index.ts --characters=\"../characters/tate.character.json\"",
         "watch": "tsc --watch",
         "dev": "tsc && nodemon",
-        "build:docs": "cd docs && npm run build",
+        "build:docs": "cd docs && pnpm run build",
         "postinstall": "npx playwright install-deps && npx playwright install",
         "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --runInBand --watch -f",
         "test:sqlite": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" TEST_DATABASE_CLIENT=sqlite jest --runInBand --watch -f",
@@ -59,7 +59,7 @@
         "itty-router": "5.0.18",
         "jest": "29.7.0",
         "lint-staged": "15.2.10",
-        "npm-run-all2": "7.0.1",
+        "pnpm-run-all2": "7.0.1",
         "prettier": "3.3.3",
         "rimraf": "6.0.1",
         "rollup": "2.79.2",
@@ -108,7 +108,7 @@
         "bignumber": "1.1.0",
         "bignumber.js": "9.1.2",
         "body-parser": "1.20.3",
-        "capsolver-npm": "2.0.2",
+        "capsolver-pnpm": "2.0.2",
         "cldr-segmentation": "2.2.1",
         "command-exists": "1.2.9",
         "commander": "12.1.0",

From 4818bb93d75697b96a18e15026552afbfbe00ca4 Mon Sep 17 00:00:00 2001
From: moon <shawmakesmagic@gmail.com>
Date: Sat, 2 Nov 2024 06:24:08 -0700
Subject: [PATCH 06/23] simpler local models for now

---
 core/src/core/models.ts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/core/src/core/models.ts b/core/src/core/models.ts
index e4675209221..a6903b9c8fb 100644
--- a/core/src/core/models.ts
+++ b/core/src/core/models.ts
@@ -104,13 +104,13 @@ const models: Models = {
             temperature: 0.3,
         },
         model: {
-            [ModelClass.SMALL]: "bartowski/Llama-3.2-3B-Instruct-GGUF",
+            [ModelClass.SMALL]: "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
             [ModelClass.MEDIUM]:
-                "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf", // TODO: ?download=true
+                "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true", // TODO: ?download=true
             [ModelClass.LARGE]:
-                "RichardErkhov/NousResearch_-_Meta-Llama-3.1-70B-gguf", // TODO: ?download=true
-            [ModelClass.EMBEDDING]:
-                "togethercomputer/m2-bert-80M-32k-retrieval",
+            "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
+                // "RichardErkhov/NousResearch_-_Meta-Llama-3.1-70B-gguf", // TODO: 
+            [ModelClass.EMBEDDING]: "togethercomputer/m2-bert-80M-32k-retrieval"
         },
     },
     [ModelProvider.GOOGLE]: {

From 0b820559064ca15a9a83790693aa9745bc5d2635 Mon Sep 17 00:00:00 2001
From: moon <shawmakesmagic@gmail.com>
Date: Sat, 2 Nov 2024 06:47:16 -0700
Subject: [PATCH 07/23] fix dumb

---
 core/package.json | 1 -
 1 file changed, 1 deletion(-)

diff --git a/core/package.json b/core/package.json
index 686a0228666..dcadd9b7378 100644
--- a/core/package.json
+++ b/core/package.json
@@ -59,7 +59,6 @@
         "itty-router": "5.0.18",
         "jest": "29.7.0",
         "lint-staged": "15.2.10",
-        "pnpm-run-all2": "7.0.1",
         "prettier": "3.3.3",
         "rimraf": "6.0.1",
         "rollup": "2.79.2",

From e580ac6ef9f5b27674993bee11c52fba96151c35 Mon Sep 17 00:00:00 2001
From: Jerad Bitner <sirkitree@gmail.com>
Date: Sat, 2 Nov 2024 08:43:51 -0700
Subject: [PATCH 08/23] fix typo in package name

---
 core/package.json |  3 +-
 pnpm-lock.yaml    | 93 +++++++++++------------------------------------
 2 files changed, 23 insertions(+), 73 deletions(-)

diff --git a/core/package.json b/core/package.json
index dcadd9b7378..f7fbe5f85ec 100644
--- a/core/package.json
+++ b/core/package.json
@@ -82,7 +82,6 @@
         "@anthropic-ai/sdk": "^0.30.1",
         "@cliqz/adblocker-playwright": "1.34.0",
         "@coral-xyz/anchor": "^0.30.1",
-        "@discordjs/opus": "github:discordjs/opus",
         "@discordjs/rest": "2.4.0",
         "@discordjs/voice": "0.17.0",
         "@echogarden/espeak-ng-emscripten": "0.3.0",
@@ -107,7 +106,7 @@
         "bignumber": "1.1.0",
         "bignumber.js": "9.1.2",
         "body-parser": "1.20.3",
-        "capsolver-pnpm": "2.0.2",
+        "capsolver-npm": "2.0.2",
         "cldr-segmentation": "2.2.1",
         "command-exists": "1.2.9",
         "commander": "12.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 714e216f3a6..c8c30affc79 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -50,15 +50,12 @@ importers:
       '@coral-xyz/anchor':
         specifier: ^0.30.1
         version: 0.30.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
-      '@discordjs/opus':
-        specifier: github:discordjs/opus
-        version: https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13)
       '@discordjs/rest':
         specifier: 2.4.0
         version: 2.4.0
       '@discordjs/voice':
         specifier: 0.17.0
-        version: 0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13))(bufferutil@4.0.8)(ffmpeg-static@5.2.0)(utf-8-validate@5.0.10)
+        version: 0.17.0(@discordjs/opus@0.9.0(encoding@0.1.13))(bufferutil@4.0.8)(ffmpeg-static@5.2.0)(utf-8-validate@5.0.10)
       '@echogarden/espeak-ng-emscripten':
         specifier: 0.3.0
         version: 0.3.0
@@ -250,7 +247,7 @@ importers:
         version: 5.4.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)
       prism-media:
         specifier: 1.3.5
-        version: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13))(ffmpeg-static@5.2.0)
+        version: 1.3.5(@discordjs/opus@0.9.0(encoding@0.1.13))(ffmpeg-static@5.2.0)
       pumpdotfun-sdk:
         specifier: 1.3.2
         version: 1.3.2(bufferutil@4.0.8)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(rollup@2.79.2)(typescript@5.6.3)(utf-8-validate@5.0.10)
@@ -384,9 +381,6 @@ importers:
       lint-staged:
         specifier: 15.2.10
         version: 15.2.10
-      npm-run-all2:
-        specifier: 7.0.1
-        version: 7.0.1
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -1443,9 +1437,8 @@ packages:
     resolution: {integrity: sha512-YJOVVZ545x24mHzANfYoy0BJX5PDyeZlpiJjDkUBM/V/Ao7TFX9lcUvCN4nr0tbr5ubeaXxtEBILUrHtTphVeQ==}
     hasBin: true
 
-  '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02':
-    resolution: {tarball: https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02}
-    version: 0.9.0
+  '@discordjs/opus@0.9.0':
+    resolution: {integrity: sha512-NEE76A96FtQ5YuoAVlOlB3ryMPrkXbUCTQICHGKb8ShtjXyubGicjRMouHtP1RpuDdm16cDa+oI3aAMo1zQRUQ==}
     engines: {node: '>=12.0.0'}
 
   '@discordjs/rest@2.4.0':
@@ -1458,7 +1451,6 @@ packages:
 
   '@discordjs/voice@0.17.0':
     resolution: {integrity: sha512-hArn9FF5ZYi1IkxdJEVnJi+OxlwLV0NJYWpKXsmNOojtGtAZHxmsELA+MZlu2KW1F/K1/nt7lFOfcMXNYweq9w==}
-    version: 0.17.0
     engines: {node: '>=16.11.0'}
 
   '@discordjs/ws@1.1.1':
@@ -6715,10 +6707,6 @@ packages:
     resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
-  json-parse-even-better-errors@4.0.0:
-    resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==}
-    engines: {node: ^18.17.0 || >=20.5.0}
-
   json-schema-traverse@0.4.1:
     resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
 
@@ -7139,10 +7127,6 @@ packages:
   memory-stream@1.0.0:
     resolution: {integrity: sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==}
 
-  memorystream@0.3.1:
-    resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
-    engines: {node: '>= 0.10.0'}
-
   meow@8.1.2:
     resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==}
     engines: {node: '>=10'}
@@ -7582,6 +7566,9 @@ packages:
     resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==}
     engines: {node: '>=10'}
 
+  node-addon-api@5.1.0:
+    resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
+
   node-addon-api@8.2.1:
     resolution: {integrity: sha512-vmEOvxwiH8tlOcv4SyE8RH34rI5/nWVaigUeAUPawC6f0+HoDthwI0vkMu4tbtsZrXq6QXFfrkhjofzKEs5tpA==}
     engines: {node: ^18 || ^20 || >= 21}
@@ -7720,10 +7707,6 @@ packages:
     resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
-  npm-normalize-package-bin@4.0.0:
-    resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==}
-    engines: {node: ^18.17.0 || >=20.5.0}
-
   npm-package-arg@11.0.2:
     resolution: {integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==}
     engines: {node: ^16.14.0 || >=18.0.0}
@@ -7740,11 +7723,6 @@ packages:
     resolution: {integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==}
     engines: {node: ^16.14.0 || >=18.0.0}
 
-  npm-run-all2@7.0.1:
-    resolution: {integrity: sha512-Adbv+bJQ8UTAM03rRODqrO5cx0YU5KCG2CvHtSURiadvdTjjgGJXdbc1oQ9CXBh9dnGfHSoSB1Web/0Dzp6kOQ==}
-    engines: {node: ^18.17.0 || >=20.5.0, npm: '>= 9'}
-    hasBin: true
-
   npm-run-path@4.0.1:
     resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
     engines: {node: '>=8'}
@@ -8597,7 +8575,6 @@ packages:
 
   prism-media@1.3.5:
     resolution: {integrity: sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==}
-    version: 1.3.5
     peerDependencies:
       '@discordjs/opus': '>=0.8.0 <1.0.0'
       ffmpeg-static: ^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0
@@ -8905,10 +8882,6 @@ packages:
     resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
-  read-package-json-fast@4.0.0:
-    resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==}
-    engines: {node: ^18.17.0 || >=20.5.0}
-
   read-pkg-up@3.0.0:
     resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==}
     engines: {node: '>=4'}
@@ -10459,11 +10432,6 @@ packages:
     engines: {node: ^16.13.0 || >=18.0.0}
     hasBin: true
 
-  which@5.0.0:
-    resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==}
-    engines: {node: ^18.17.0 || >=20.5.0}
-    hasBin: true
-
   whisper-turbo@0.11.0:
     resolution: {integrity: sha512-h2tGY1VwNAjFsEUkn2fE5NrpyNioHLQu8CSHF2s6N3mhkvPytYSNLhqUNER5OMr8s7bLtV6aQHt4jZkSmE5B6g==}
 
@@ -11952,14 +11920,16 @@ snapshots:
     transitivePeerDependencies:
       - encoding
       - supports-color
+    optional: true
 
-  '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13)':
+  '@discordjs/opus@0.9.0(encoding@0.1.13)':
     dependencies:
       '@discordjs/node-pre-gyp': 0.4.5(encoding@0.1.13)
-      node-addon-api: 8.2.1
+      node-addon-api: 5.1.0
     transitivePeerDependencies:
       - encoding
       - supports-color
+    optional: true
 
   '@discordjs/rest@2.4.0':
     dependencies:
@@ -11975,11 +11945,11 @@ snapshots:
 
   '@discordjs/util@1.1.1': {}
 
-  '@discordjs/voice@0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13))(bufferutil@4.0.8)(ffmpeg-static@5.2.0)(utf-8-validate@5.0.10)':
+  '@discordjs/voice@0.17.0(@discordjs/opus@0.9.0(encoding@0.1.13))(bufferutil@4.0.8)(ffmpeg-static@5.2.0)(utf-8-validate@5.0.10)':
     dependencies:
       '@types/ws': 8.5.12
       discord-api-types: 0.37.83
-      prism-media: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13))(ffmpeg-static@5.2.0)
+      prism-media: 1.3.5(@discordjs/opus@0.9.0(encoding@0.1.13))(ffmpeg-static@5.2.0)
       tslib: 2.8.0
       ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)
     transitivePeerDependencies:
@@ -15216,6 +15186,7 @@ snapshots:
     dependencies:
       delegates: 1.0.0
       readable-stream: 3.6.2
+    optional: true
 
   are-we-there-yet@3.0.1:
     dependencies:
@@ -18833,8 +18804,6 @@ snapshots:
 
   json-parse-even-better-errors@3.0.2: {}
 
-  json-parse-even-better-errors@4.0.0: {}
-
   json-schema-traverse@0.4.1: {}
 
   json-schema-traverse@1.0.0: {}
@@ -19241,6 +19210,7 @@ snapshots:
   make-dir@3.1.0:
     dependencies:
       semver: 6.3.1
+    optional: true
 
   make-dir@4.0.0:
     dependencies:
@@ -19502,8 +19472,6 @@ snapshots:
     dependencies:
       readable-stream: 3.6.2
 
-  memorystream@0.3.1: {}
-
   meow@8.1.2:
     dependencies:
       '@types/minimist': 1.2.5
@@ -20092,6 +20060,9 @@ snapshots:
     dependencies:
       semver: 7.6.3
 
+  node-addon-api@5.1.0:
+    optional: true
+
   node-addon-api@8.2.1: {}
 
   node-api-headers@1.3.0: {}
@@ -20224,6 +20195,7 @@ snapshots:
   nopt@5.0.0:
     dependencies:
       abbrev: 1.1.1
+    optional: true
 
   nopt@7.2.1:
     dependencies:
@@ -20267,8 +20239,6 @@ snapshots:
 
   npm-normalize-package-bin@3.0.1: {}
 
-  npm-normalize-package-bin@4.0.0: {}
-
   npm-package-arg@11.0.2:
     dependencies:
       hosted-git-info: 7.0.2
@@ -20300,17 +20270,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  npm-run-all2@7.0.1:
-    dependencies:
-      ansi-styles: 6.2.1
-      cross-spawn: 7.0.3
-      memorystream: 0.3.1
-      minimatch: 9.0.5
-      pidtree: 0.6.0
-      read-package-json-fast: 4.0.0
-      shell-quote: 1.8.1
-      which: 5.0.0
-
   npm-run-path@4.0.1:
     dependencies:
       path-key: 3.1.1
@@ -20325,6 +20284,7 @@ snapshots:
       console-control-strings: 1.1.0
       gauge: 3.0.2
       set-blocking: 2.0.0
+    optional: true
 
   npmlog@6.0.2:
     dependencies:
@@ -21262,9 +21222,9 @@ snapshots:
 
   printable-characters@1.0.42: {}
 
-  prism-media@1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13))(ffmpeg-static@5.2.0):
+  prism-media@1.3.5(@discordjs/opus@0.9.0(encoding@0.1.13))(ffmpeg-static@5.2.0):
     optionalDependencies:
-      '@discordjs/opus': https://codeload.github.com/discordjs/opus/tar.gz/31da49d8d2cc6c5a2ab1bfd332033ff7d5f9fb02(encoding@0.1.13)
+      '@discordjs/opus': 0.9.0(encoding@0.1.13)
       ffmpeg-static: 5.2.0
 
   prism-react-renderer@2.3.1(react@18.2.0):
@@ -21640,11 +21600,6 @@ snapshots:
       json-parse-even-better-errors: 3.0.2
       npm-normalize-package-bin: 3.0.1
 
-  read-package-json-fast@4.0.0:
-    dependencies:
-      json-parse-even-better-errors: 4.0.0
-      npm-normalize-package-bin: 4.0.0
-
   read-pkg-up@3.0.0:
     dependencies:
       find-up: 2.1.0
@@ -23469,10 +23424,6 @@ snapshots:
     dependencies:
       isexe: 3.1.1
 
-  which@5.0.0:
-    dependencies:
-      isexe: 3.1.1
-
   whisper-turbo@0.11.0:
     dependencies:
       comlink: 4.3.1

From 810f187784088023c597afa843210dec3bddafbe Mon Sep 17 00:00:00 2001
From: Jerad Bitner <sirkitree@gmail.com>
Date: Sat, 2 Nov 2024 09:30:17 -0700
Subject: [PATCH 09/23] adjusting test setup and adding a basic test which we
 can start to add to

---
 core/.env.test                        |  2 ++
 core/jest.config.js                   |  9 ++++-----
 core/package.json                     |  7 ++++---
 core/src/test_resources/basic.test.ts | 10 ++++++++++
 core/src/test_resources/testSetup.ts  |  8 ++++++++
 core/tsconfig.json                    |  8 ++++----
 pnpm-lock.yaml                        |  2 +-
 7 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 core/.env.test
 create mode 100644 core/src/test_resources/basic.test.ts
 create mode 100644 core/src/test_resources/testSetup.ts

diff --git a/core/.env.test b/core/.env.test
new file mode 100644
index 00000000000..3f383adc69f
--- /dev/null
+++ b/core/.env.test
@@ -0,0 +1,2 @@
+TEST_DATABASE_CLIENT=sqlite
+NODE_ENV=test
diff --git a/core/jest.config.js b/core/jest.config.js
index cc88ff8fef0..9d609fa6785 100644
--- a/core/jest.config.js
+++ b/core/jest.config.js
@@ -1,17 +1,16 @@
 /** @type {import('ts-jest').JestConfigWithTsJest} */
 export default {
     preset: "ts-jest",
-    testEnvironment: "jest-environment-node",
+    testEnvironment: "node",
     rootDir: "./src",
     testMatch: ["**/*.test.ts"],
+    setupFilesAfterEnv: ["<rootDir>/test_resources/testSetup.ts"],
+    testTimeout: 120000,
     globals: {
         __DEV__: true,
         __TEST__: true,
         __VERSION__: "0.0.1",
     },
-    // collectCoverage: true,
-    // collectCoverageFrom: ["**/*.{ts}", "!**/*.test.{ts}", "!**/node_modules/**", "!**/vendor/**"],
-    // coverageDirectory: "../coverage",
     transform: {
         "^.+\\.tsx?$": [
             "ts-jest",
@@ -24,4 +23,4 @@ export default {
         "^(\\.{1,2}/.*)\\.js$": "$1",
     },
     extensionsToTreatAsEsm: [".ts"],
-};
+}
diff --git a/core/package.json b/core/package.json
index f7fbe5f85ec..309d9d71880 100644
--- a/core/package.json
+++ b/core/package.json
@@ -29,9 +29,10 @@
         "dev": "tsc && nodemon",
         "build:docs": "cd docs && pnpm run build",
         "postinstall": "npx playwright install-deps && npx playwright install",
-        "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --runInBand --watch -f",
-        "test:sqlite": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" TEST_DATABASE_CLIENT=sqlite jest --runInBand --watch -f",
-        "test:sqljs": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" TEST_DATABASE_CLIENT=sqljs jest --runInBand --watch -f"
+        "test": "jest --runInBand",
+        "test:watch": "jest --runInBand --watch",
+        "test:sqlite": "cross-env TEST_DATABASE_CLIENT=sqlite jest --runInBand --watch",
+        "test:sqljs": "cross-env TEST_DATABASE_CLIENT=sqljs jest --runInBand --watch"
     },
     "author": "",
     "license": "MIT",
diff --git a/core/src/test_resources/basic.test.ts b/core/src/test_resources/basic.test.ts
new file mode 100644
index 00000000000..bc712869a14
--- /dev/null
+++ b/core/src/test_resources/basic.test.ts
@@ -0,0 +1,10 @@
+describe('Basic Test Suite', () => {
+    it('should run a basic test', () => {
+        expect(true).toBe(true);
+    });
+
+    it('should have access to environment variables', () => {
+        expect(process.env.NODE_ENV).toBe('test');
+        expect(process.env.TEST_DATABASE_CLIENT).toBe('sqlite');
+    });
+}); 
\ No newline at end of file
diff --git a/core/src/test_resources/testSetup.ts b/core/src/test_resources/testSetup.ts
new file mode 100644
index 00000000000..76497eb260e
--- /dev/null
+++ b/core/src/test_resources/testSetup.ts
@@ -0,0 +1,8 @@
+import dotenv from "dotenv";
+import path from 'path';
+
+// Load test environment variables
+dotenv.config({ path: '.env.test' });
+
+// Set longer timeout for tests
+jest.setTimeout(120000);
diff --git a/core/tsconfig.json b/core/tsconfig.json
index 3527f3ee01e..afba577e90f 100644
--- a/core/tsconfig.json
+++ b/core/tsconfig.json
@@ -1,9 +1,9 @@
 {
     "compilerOptions": {
-        "target": "es2022",
-        "module": "es2022",
-        "lib": ["es2023", "dom"],
-        "moduleResolution": "bundler",
+        "target": "ESNext",
+        "module": "NodeNext",
+        "lib": ["ESNext", "dom"],
+        "moduleResolution": "NodeNext",
         "outDir": "./dist",
         "rootDir": "./src",
         "strict": false,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c8c30affc79..e5b27b7ee7b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11911,7 +11911,7 @@ snapshots:
       detect-libc: 2.0.3
       https-proxy-agent: 5.0.1
       make-dir: 3.1.0
-      node-fetch: 2.6.7(encoding@0.1.13)
+      node-fetch: 2.7.0(encoding@0.1.13)
       nopt: 5.0.0
       npmlog: 5.0.1
       rimraf: 3.0.2

From a73d460b1b17371edef62eefd136da22ae6685b6 Mon Sep 17 00:00:00 2001
From: Jerad Bitner <sirkitree@gmail.com>
Date: Sat, 2 Nov 2024 09:35:31 -0700
Subject: [PATCH 10/23] add note to README about tests

---
 README.md | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/README.md b/README.md
index 0fffaea20af..c35d4fd431f 100644
--- a/README.md
+++ b/README.md
@@ -143,3 +143,28 @@ downloads the model from huggingface and queries it locally
 ## Discord Bot
 
 For help with setting up your Discord Bot, check out here: https://discordjs.guide/preparations/setting-up-a-bot-application.html
+
+# Development
+
+## Testing
+
+To run the test suite:
+
+```bash
+pnpm test           # Run tests once
+pnpm test:watch    # Run tests in watch mode
+```
+
+For database-specific tests:
+```bash
+pnpm test:sqlite   # Run tests with SQLite
+pnpm test:sqljs    # Run tests with SQL.js
+```
+
+Tests are written using Jest and can be found in `src/**/*.test.ts` files. The test environment is configured to:
+- Load environment variables from `.env.test`
+- Use a 2-minute timeout for long-running tests
+- Support ESM modules
+- Run tests in sequence (--runInBand)
+
+To create new tests, add a `.test.ts` file adjacent to the code you're testing.
\ No newline at end of file

From ba62135f17e07a1c3a4f73502fd5ac3a3ebc4120 Mon Sep 17 00:00:00 2001
From: Matthew Lam <minghinmatthew.lam@gmail.com>
Date: Sat, 2 Nov 2024 15:18:52 -0400
Subject: [PATCH 11/23] postgres updates

---
 core/src/adapters/postgres.ts | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/core/src/adapters/postgres.ts b/core/src/adapters/postgres.ts
index d7180c0a363..ceecb140982 100644
--- a/core/src/adapters/postgres.ts
+++ b/core/src/adapters/postgres.ts
@@ -107,6 +107,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
     }): Promise<Memory[]> {
         const client = await this.pool.connect();
         try {
+            if (params.roomIds.length === 0) return [];
             const placeholders = params.roomIds
                 .map((_, i) => `$${i + 2}`)
                 .join(", ");
@@ -304,7 +305,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
       `;
 
             if (params.unique) {
-                sql += " AND unique = true";
+                sql += ` AND "unique" = true`;
             }
 
             sql += ` AND 1 - (embedding <-> $3) >= $4
@@ -360,7 +361,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
             }
 
             if (params.unique) {
-                sql += " AND unique = true";
+                sql += ` AND "unique" = true`;
             }
 
             if (params.agentId) {
@@ -382,9 +383,9 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
             return rows.map((row) => ({
                 ...row,
                 content:
-                    typeof rows.content === "string"
-                        ? JSON.parse(rows.content)
-                        : rows.content,
+                    typeof row.content === "string"
+                        ? JSON.parse(row.content)
+                        : row.content,
             }));
         } finally {
             client.release();
@@ -759,7 +760,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
         try {
             let sql = `SELECT COUNT(*) as count FROM memories WHERE type = $1 AND "roomId" = $2`;
             if (unique) {
-                sql += " AND unique = true";
+                sql += ` AND "unique" = true`;
             }
 
             const { rows } = await client.query(sql, [tableName, roomId]);
@@ -796,7 +797,7 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
     async getRoomsForParticipants(userIds: UUID[]): Promise<UUID[]> {
         const client = await this.pool.connect();
         try {
-            const placeholders = userIds.map((_, i) => `${i + 1}`).join(", ");
+            const placeholders = userIds.map((_, i) => `$${i + 1}`).join(", ");
             const { rows } = await client.query(
                 `SELECT DISTINCT "roomId" FROM participants WHERE "userId" IN (${placeholders})`,
                 userIds

From 3b2d1295665ff8f34fa991f9f5fc6e3dfbf7a94e Mon Sep 17 00:00:00 2001
From: Matthew Lam <minghinmatthew.lam@gmail.com>
Date: Sat, 2 Nov 2024 15:21:55 -0400
Subject: [PATCH 12/23] fix timestamps

---
 core/src/adapters/postgres.ts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/core/src/adapters/postgres.ts b/core/src/adapters/postgres.ts
index ceecb140982..d3375eeb641 100644
--- a/core/src/adapters/postgres.ts
+++ b/core/src/adapters/postgres.ts
@@ -350,14 +350,14 @@ export class PostgresDatabaseAdapter extends DatabaseAdapter {
 
             if (params.start) {
                 paramCount++;
-                sql += ` AND "createdAt" >= to_timestamp($${paramCount / 1000})`;
-                values.push(params.start);
+                sql += ` AND "createdAt" >= to_timestamp($${paramCount})`;
+                values.push(params.start/1000);
             }
 
             if (params.end) {
                 paramCount++;
-                sql += ` AND "createdAt" <= to_timestamp($${paramCount / 1000})`;
-                values.push(params.end);
+                sql += ` AND "createdAt" <= to_timestamp($${paramCount})`;
+                values.push(params.end/1000);
             }
 
             if (params.unique) {

From c988337e69ef26a2ff7be198dfeaabd5475bac33 Mon Sep 17 00:00:00 2001
From: MarcoMandar <malicemandar@gmail.com>
Date: Sun, 3 Nov 2024 04:02:30 +0200
Subject: [PATCH 13/23] add last active and decay score, update token
 recommendations, add validation trust to token performance and add
 calculateValidationTrust

Signed-off-by: MarcoMandar <malicemandar@gmail.com>
---
 core/src/adapters/trustScoreDatabase.ts  | 48 +++++++++++++++++++++++-
 core/src/providers/trustScoreProvider.ts | 39 +++++++++++++++++--
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/core/src/adapters/trustScoreDatabase.ts b/core/src/adapters/trustScoreDatabase.ts
index 9ec19de29ac..b206fd1923e 100644
--- a/core/src/adapters/trustScoreDatabase.ts
+++ b/core/src/adapters/trustScoreDatabase.ts
@@ -24,6 +24,8 @@ export interface RecommenderMetrics {
     riskScore: number;
     consistencyScore: number;
     virtualConfidence: number;
+    lastActiveDate: Date;
+    trustDecay: number;
     lastUpdated: Date;
 }
 
@@ -41,6 +43,7 @@ export interface TokenPerformance {
     sustainedGrowth: boolean;
     rapidDump: boolean;
     suspiciousVolume: boolean;
+    validationTrust: number;
     lastUpdated: Date;
 }
 
@@ -63,6 +66,7 @@ export interface RecommenderMetricsHistory {
     riskScore: number;
     consistencyScore: number;
     virtualConfidence: number;
+    trustDecay: number;
     recordedAt: Date;
 }
 
@@ -100,6 +104,8 @@ interface RecommenderMetricsRow {
     risk_score: number;
     consistency_score: number;
     virtual_confidence: number;
+    last_active_date: Date;
+    trust_decay: number;
     last_updated: string;
 }
 
@@ -117,6 +123,7 @@ interface TokenPerformanceRow {
     sustained_growth: number;
     rapid_dump: number;
     suspicious_volume: number;
+    validation_trust: number;
     last_updated: string;
 }
 
@@ -165,6 +172,8 @@ export class TrustScoreDatabase {
                 risk_score REAL DEFAULT 0,
                 consistency_score REAL DEFAULT 0,
                 virtual_confidence REAL DEFAULT 0,
+                last_active_date DATETIME DEFAULT CURRENT_TIMESTAMP
+                trust_decay REAL DEFAULT 0,
                 last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
                 FOREIGN KEY (recommender_id) REFERENCES recommenders(id) ON DELETE CASCADE
             );
@@ -186,6 +195,7 @@ export class TrustScoreDatabase {
                 sustained_growth BOOLEAN DEFAULT FALSE,
                 rapid_dump BOOLEAN DEFAULT FALSE,
                 suspicious_volume BOOLEAN DEFAULT FALSE,
+                validation_trust REAL DEFAULT 0,
                 last_updated DATETIME DEFAULT CURRENT_TIMESTAMP
             );
         `);
@@ -378,6 +388,8 @@ export class TrustScoreDatabase {
             riskScore: row.risk_score,
             consistencyScore: row.consistency_score,
             virtualConfidence: row.virtual_confidence,
+            lastActiveDate: row.last_active_date,
+            trustDecay: row.trust_decay,
             lastUpdated: new Date(row.last_updated),
         };
     }
@@ -407,6 +419,7 @@ export class TrustScoreDatabase {
             riskScore: currentMetrics.riskScore,
             consistencyScore: currentMetrics.consistencyScore,
             virtualConfidence: currentMetrics.virtualConfidence,
+            trustDecay: currentMetrics.trustDecay,
             recordedAt: new Date(), // Current timestamp
         };
 
@@ -492,6 +505,10 @@ export class TrustScoreDatabase {
      * @param performance TokenPerformance object
      */
     upsertTokenPerformance(performance: TokenPerformance): boolean {
+        const validationTrust = this.calculateValidationTrust(
+            performance.tokenAddress
+        );
+
         const sql = `
             INSERT INTO token_performance (
                 token_address,
@@ -507,6 +524,7 @@ export class TrustScoreDatabase {
                 sustained_growth,
                 rapid_dump,
                 suspicious_volume,
+                validation_trust,
                 last_updated
             ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
             ON CONFLICT(token_address) DO UPDATE SET
@@ -522,6 +540,7 @@ export class TrustScoreDatabase {
                 sustained_growth = excluded.sustained_growth,
                 rapid_dump = excluded.rapid_dump,
                 suspicious_volume = excluded.suspicious_volume,
+                validation_trust = excluded.validation_trust,
                 last_updated = CURRENT_TIMESTAMP;
         `;
         try {
@@ -536,7 +555,8 @@ export class TrustScoreDatabase {
                 performance.marketCapChange24h,
                 performance.sustainedGrowth ? 1 : 0,
                 performance.rapidDump ? 1 : 0,
-                performance.suspiciousVolume ? 1 : 0
+                performance.suspiciousVolume ? 1 : 0,
+                validationTrust
             );
             console.log(
                 `Upserted token performance for ${performance.tokenAddress}`
@@ -574,12 +594,36 @@ export class TrustScoreDatabase {
             sustainedGrowth: row.sustained_growth === 1,
             rapidDump: row.rapid_dump === 1,
             suspiciousVolume: row.suspicious_volume === 1,
+            validationTrust: row.validation_trust,
             lastUpdated: new Date(row.last_updated),
         };
     }
 
     // ----- TokenRecommendations Methods -----
 
+    /**
+     * Calculates the average trust score of all recommenders who have recommended a specific token.
+     * @param tokenAddress The address of the token.
+     * @returns The average trust score (validationTrust).
+     */
+    calculateValidationTrust(tokenAddress: string): number {
+        const sql = `
+        SELECT rm.trust_score
+        FROM token_recommendations tr
+        JOIN recommender_metrics rm ON tr.recommender_id = rm.recommender_id
+        WHERE tr.token_address = ?;
+    `;
+        const rows = this.db.prepare(sql).all(tokenAddress) as Array<{
+            trust_score: number;
+        }>;
+
+        if (rows.length === 0) return 0; // No recommendations found
+
+        const totalTrust = rows.reduce((acc, row) => acc + row.trust_score, 0);
+        const averageTrust = totalTrust / rows.length;
+        return averageTrust;
+    }
+
     /**
      * Adds a new token recommendation.
      * @param recommendation TokenRecommendation object
@@ -735,6 +779,7 @@ export class TrustScoreDatabase {
             risk_score: number;
             consistency_score: number;
             virtual_confidence: number;
+            trust_decay: number;
             recorded_at: string;
         }>;
 
@@ -748,6 +793,7 @@ export class TrustScoreDatabase {
             riskScore: row.risk_score,
             consistencyScore: row.consistency_score,
             virtualConfidence: row.virtual_confidence,
+            trustDecay: row.trust_decay,
             recordedAt: new Date(row.recorded_at),
         }));
     }
diff --git a/core/src/providers/trustScoreProvider.ts b/core/src/providers/trustScoreProvider.ts
index f1a4df47df2..1932d9ba587 100644
--- a/core/src/providers/trustScoreProvider.ts
+++ b/core/src/providers/trustScoreProvider.ts
@@ -32,7 +32,8 @@ export class TrustScoreProvider {
     private trustScoreDb: TrustScoreDatabase;
     private connection: Connection = new Connection(process.env.RPC_URL!);
     private baseMint: PublicKey = new PublicKey(process.env.BASE_MINT!);
-
+    private DECAY_RATE = 0.95;
+    private MAX_DECAY_DAYS = 30;
     constructor(
         tokenProvider: TokenProvider,
         trustScoreDb: TrustScoreDatabase
@@ -85,6 +86,18 @@ export class TrustScoreProvider {
         const suspiciousVolume = await this.suspiciousVolume(tokenAddress);
         const balance = await this.getRecommenederBalance(recommenderWallet);
         const virtualConfidence = balance / 1000000; // TODO: create formula to calculate virtual confidence based on user balance
+        const lastActive = recommenderMetrics.lastActiveDate;
+        const now = new Date();
+        const inactiveDays = Math.floor(
+            (now.getTime() - lastActive.getTime()) / (1000 * 60 * 60 * 24)
+        );
+        const decayFactor = Math.pow(
+            this.DECAY_RATE,
+            Math.min(inactiveDays, this.MAX_DECAY_DAYS)
+        );
+        const decayedScore = recommenderMetrics.trustScore * decayFactor;
+        const validationTrustScore =
+            this.trustScoreDb.calculateValidationTrust(tokenAddress);
 
         return {
             tokenPerformance: {
@@ -107,6 +120,7 @@ export class TrustScoreProvider {
                 sustainedGrowth: sustainedGrowth,
                 rapidDump: isRapidDump,
                 suspiciousVolume: suspiciousVolume,
+                validationTrust: validationTrustScore,
                 lastUpdated: new Date(),
             },
             recommenderMetrics: {
@@ -118,6 +132,8 @@ export class TrustScoreProvider {
                 riskScore: recommenderMetrics.riskScore,
                 consistencyScore: recommenderMetrics.consistencyScore,
                 virtualConfidence: virtualConfidence,
+                lastActiveDate: now,
+                trustDecay: decayedScore,
                 lastUpdated: new Date(),
             },
         };
@@ -125,7 +141,8 @@ export class TrustScoreProvider {
 
     async updateRecommenderMetrics(
         recommenderId: string,
-        tokenPerformance: TokenPerformance
+        tokenPerformance: TokenPerformance,
+        recommenderWallet: string
     ): Promise<void> {
         const recommenderMetrics =
             await this.trustScoreDb.getRecommenderMetrics(recommenderId);
@@ -153,6 +170,20 @@ export class TrustScoreProvider {
             tokenPerformance,
             recommenderMetrics
         );
+
+        const balance = await this.getRecommenederBalance(recommenderWallet);
+        const virtualConfidence = balance / 1000000; // TODO: create formula to calculate virtual confidence based on user balance
+        const lastActive = recommenderMetrics.lastActiveDate;
+        const now = new Date();
+        const inactiveDays = Math.floor(
+            (now.getTime() - lastActive.getTime()) / (1000 * 60 * 60 * 24)
+        );
+        const decayFactor = Math.pow(
+            this.DECAY_RATE,
+            Math.min(inactiveDays, this.MAX_DECAY_DAYS)
+        );
+        const decayedScore = recommenderMetrics.trustScore * decayFactor;
+
         const newRecommenderMetrics: RecommenderMetrics = {
             recommenderId: recommenderId,
             trustScore: overallTrustScore,
@@ -161,7 +192,9 @@ export class TrustScoreProvider {
             avgTokenPerformance: avgTokenPerformance,
             riskScore: riskScore,
             consistencyScore: consistencyScore,
-            virtualConfidence: recommenderMetrics.virtualConfidence,
+            virtualConfidence: virtualConfidence,
+            lastActiveDate: new Date(),
+            trustDecay: decayedScore,
             lastUpdated: new Date(),
         };
 

From 880e5ac981b9298fd3fc385f0694f2b45b95c5e5 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 16:36:01 +1100
Subject: [PATCH 14/23] prettier logs, some minor cleanups

---
 core/src/actions/imageGeneration.ts           |  21 ++
 core/src/adapters/sqlite/sqlite_vec.ts        |   5 +-
 core/src/cli/colors.ts                        | 268 ++++++++++++++++++
 core/src/cli/config.ts                        |   5 +-
 core/src/cli/index.ts                         |  33 ++-
 core/src/clients/telegram/src/index.ts        |  38 +--
 .../clients/telegram/src/messageManager.ts    |   8 +-
 core/src/clients/twitter/base.ts              |   7 +-
 core/src/clients/twitter/utils.ts             |   9 +-
 core/src/core/generation.ts                   |  67 ++---
 core/src/core/runtime.ts                      |   8 +-
 core/src/index.ts                             |  12 +-
 12 files changed, 404 insertions(+), 77 deletions(-)
 create mode 100644 core/src/cli/colors.ts

diff --git a/core/src/actions/imageGeneration.ts b/core/src/actions/imageGeneration.ts
index 0ee3c879b65..208e8265dbc 100644
--- a/core/src/actions/imageGeneration.ts
+++ b/core/src/actions/imageGeneration.ts
@@ -5,6 +5,7 @@ import {
     State,
     Action,
 } from "../core/types.ts";
+import { prettyConsole } from "../index.ts";
 import { generateCaption, generateImage } from "./imageGenerationUtils.ts";
 
 export const imageGeneration: Action = {
@@ -23,11 +24,16 @@ export const imageGeneration: Action = {
         options: any,
         callback: HandlerCallback
     ) => {
+        prettyConsole.log("Composing state for message:", message);
         state = (await runtime.composeState(message)) as State;
         const userId = runtime.agentId;
+        prettyConsole.log("User ID:", userId);
 
         const imagePrompt = message.content.text;
+        prettyConsole.log("Image prompt received:", imagePrompt);
         const res: { image: string; caption: string }[] = [];
+
+        prettyConsole.log("Generating image with prompt:", imagePrompt);
         const images = await generateImage(
             {
                 prompt: imagePrompt,
@@ -37,16 +43,29 @@ export const imageGeneration: Action = {
             },
             runtime
         );
+
         if (images.success && images.data && images.data.length > 0) {
+            prettyConsole.log(
+                "Image generation successful, number of images:",
+                images.data.length
+            );
             for (let i = 0; i < images.data.length; i++) {
                 const image = images.data[i];
+                prettyConsole.log(`Processing image ${i + 1}:`, image);
+
                 const caption = await generateCaption(
                     {
                         imageUrl: image,
                     },
                     runtime
                 );
+
+                prettyConsole.log(
+                    `Generated caption for image ${i + 1}:`,
+                    caption.title
+                );
                 res.push({ image: image, caption: caption.title });
+
                 callback(
                     {
                         text: caption.description,
@@ -64,6 +83,8 @@ export const imageGeneration: Action = {
                     []
                 );
             }
+        } else {
+            prettyConsole.error("Image generation failed or returned no data.");
         }
     },
     examples: [
diff --git a/core/src/adapters/sqlite/sqlite_vec.ts b/core/src/adapters/sqlite/sqlite_vec.ts
index 57429ae188d..2f159d22f99 100644
--- a/core/src/adapters/sqlite/sqlite_vec.ts
+++ b/core/src/adapters/sqlite/sqlite_vec.ts
@@ -1,14 +1,15 @@
 import * as sqliteVec from "sqlite-vec";
 import { Database } from "better-sqlite3";
+import { prettyConsole } from "../../index.ts";
 
 // Loads the sqlite-vec extensions into the provided SQLite database
 export function loadVecExtensions(db: Database): void {
     try {
         // Load sqlite-vec extensions
         sqliteVec.load(db);
-        console.log("sqlite-vec extensions loaded successfully.");
+        prettyConsole.log("sqlite-vec extensions loaded successfully.");
     } catch (error) {
-        console.error("Failed to load sqlite-vec extensions:", error);
+        prettyConsole.error("Failed to load sqlite-vec extensions:", error);
         throw error;
     }
 }
diff --git a/core/src/cli/colors.ts b/core/src/cli/colors.ts
new file mode 100644
index 00000000000..86209c1ebbd
--- /dev/null
+++ b/core/src/cli/colors.ts
@@ -0,0 +1,268 @@
+export class PrettyConsole {
+    closeByNewLine = true;
+    useIcons = true;
+    logsTitle = "LOGS";
+    warningsTitle = "WARNINGS";
+    errorsTitle = "ERRORS";
+    informationsTitle = "INFORMATIONS";
+    successesTitle = "SUCCESS";
+    debugsTitle = "DEBUG";
+    assertsTitle = "ASSERT";
+    #getColor(foregroundColor = "", backgroundColor = "") {
+        let fgc = "\x1b[37m";
+        switch (foregroundColor.trim().toLowerCase()) {
+            case "black":
+                fgc = "\x1b[30m";
+                break;
+            case "red":
+                fgc = "\x1b[31m";
+                break;
+            case "green":
+                fgc = "\x1b[32m";
+                break;
+            case "yellow":
+                fgc = "\x1b[33m";
+                break;
+            case "blue":
+                fgc = "\x1b[34m";
+                break;
+            case "magenta":
+                fgc = "\x1b[35m";
+                break;
+            case "cyan":
+                fgc = "\x1b[36m";
+                break;
+            case "white":
+                fgc = "\x1b[37m";
+                break;
+        }
+
+        let bgc = "";
+        switch (backgroundColor.trim().toLowerCase()) {
+            case "black":
+                bgc = "\x1b[40m";
+                break;
+            case "red":
+                bgc = "\x1b[44m";
+                break;
+            case "green":
+                bgc = "\x1b[44m";
+                break;
+            case "yellow":
+                bgc = "\x1b[43m";
+                break;
+            case "blue":
+                bgc = "\x1b[44m";
+                break;
+            case "magenta":
+                bgc = "\x1b[45m";
+                break;
+            case "cyan":
+                bgc = "\x1b[46m";
+                break;
+            case "white":
+                bgc = "\x1b[47m";
+                break;
+        }
+
+        return `${fgc}${bgc}`;
+    }
+    #getColorReset() {
+        return "\x1b[0m";
+    }
+    clear() {
+        console.clear();
+    }
+    print(foregroundColor = "white", backgroundColor = "black", ...strings) {
+        const c = this.#getColor(foregroundColor, backgroundColor);
+        // turns objects into printable strings
+        strings = strings.map((item) => {
+            if (typeof item === "object") item = JSON.stringify(item);
+            return item;
+        });
+        console.log(c, strings.join(""), this.#getColorReset());
+        if (this.closeByNewLine) console.log("");
+    }
+    log(...strings) {
+        const fg = "white";
+        const bg = "";
+        const icon = "\u25ce";
+        const groupTile = ` ${this.logsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item, this.#getColorReset());
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    warn(...strings) {
+        const fg = "yellow";
+        const bg = "";
+        const icon = "\u26a0";
+        const groupTile = ` ${this.warningsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item, this.#getColorReset());
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    error(...strings) {
+        const fg = "red";
+        const bg = "";
+        const icon = "\u26D4";
+        const groupTile = ` ${this.errorsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item);
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    info(...strings) {
+        const fg = "blue";
+        const bg = "";
+        const icon = "\u2139";
+        const groupTile = ` ${this.informationsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item);
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    success(...strings) {
+        const fg = "green";
+        const bg = "";
+        const icon = "\u2713";
+        const groupTile = ` ${this.successesTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item);
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    debug(...strings) {
+        const fg = "magenta";
+        const bg = "";
+        const icon = "\u1367";
+        const groupTile = ` ${this.debugsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item);
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+    assert(...strings) {
+        const fg = "cyan";
+        const bg = "";
+        const icon = "\u0021";
+        const groupTile = ` ${this.assertsTitle}`;
+        if (strings.length > 1) {
+            const c = this.#getColor(fg, bg);
+            console.group(c, (this.useIcons ? icon : "") + groupTile);
+            const nl = this.closeByNewLine;
+            this.closeByNewLine = false;
+            strings.forEach((item) => {
+                this.print(fg, bg, item);
+            });
+            this.closeByNewLine = nl;
+            console.groupEnd();
+            if (nl) console.log();
+        } else {
+            this.print(
+                fg,
+                bg,
+                strings.map((item) => {
+                    return `${this.useIcons ? `${icon} ` : ""}${item}`;
+                })
+            );
+        }
+    }
+}
diff --git a/core/src/cli/config.ts b/core/src/cli/config.ts
index 05b7bda964e..7162f8e1e15 100644
--- a/core/src/cli/config.ts
+++ b/core/src/cli/config.ts
@@ -3,6 +3,7 @@ import yaml from "js-yaml";
 import path from "path";
 import { fileURLToPath } from "url";
 import { Action } from "../core/types";
+import { prettyConsole } from "../index.ts";
 
 const ROOT_DIR = path.resolve(fileURLToPath(import.meta.url), "../../../src");
 
@@ -29,13 +30,13 @@ export async function loadCustomActions(
 
     for (const config of actionConfigs) {
         const resolvedPath = path.resolve(ROOT_DIR, config.path);
-        console.log(`Importing action from: ${resolvedPath}`); // Debugging log
+        prettyConsole.log(`Importing action from: ${resolvedPath}`); // Debugging log
 
         try {
             const actionModule = await import(resolvedPath);
             actions.push(actionModule[config.name]);
         } catch (error) {
-            console.error(
+            prettyConsole.error(
                 `Failed to import action from ${resolvedPath}:`,
                 error
             );
diff --git a/core/src/cli/index.ts b/core/src/cli/index.ts
index 90c5ef46d41..953bd04adb4 100644
--- a/core/src/cli/index.ts
+++ b/core/src/cli/index.ts
@@ -14,6 +14,7 @@ import { AgentRuntime } from "../core/runtime.ts";
 import { defaultActions } from "../core/actions.ts";
 import { Arguments } from "../types/index.ts";
 import { loadActionConfigs, loadCustomActions } from "./config.ts";
+import { prettyConsole } from "../index.ts";
 
 export async function initializeClients(
     character: Character,
@@ -149,11 +150,16 @@ export async function createAgentRuntime(
     });
 }
 
-export function createDirectRuntime(
+export async function createDirectRuntime(
     character: Character,
     db: any,
-    token: string
+    token: string,
+    configPath: string = "./elizaConfig.yaml"
 ) {
+    const actionConfigs = loadActionConfigs(configPath);
+    const customActions = await loadCustomActions(actionConfigs);
+
+    console.log("Creating runtime for character", character.name);
     return new AgentRuntime({
         databaseAdapter: db,
         token,
@@ -161,7 +167,18 @@ export function createDirectRuntime(
         evaluators: [],
         character,
         providers: [Provider.timeProvider, Provider.boredomProvider],
-        actions: [...defaultActions],
+        actions: [
+            ...defaultActions,
+            // Custom actions
+            Action.followRoom,
+            Action.unfollowRoom,
+            Action.unmuteRoom,
+            Action.muteRoom,
+            Action.imageGeneration,
+
+            // imported from elizaConfig.yaml
+            ...customActions,
+        ],
     });
 }
 
@@ -173,11 +190,11 @@ export async function startTelegram(
     runtime: IAgentRuntime,
     character: Character
 ) {
-    console.log("🔍 Attempting to start Telegram bot...");
+    prettyConsole.log("🔍 Attempting to start Telegram bot...");
     const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
 
     if (!botToken) {
-        console.error(
+        prettyConsole.error(
             `❌ Telegram bot token is not set for character ${character.name}.`
         );
         return null;
@@ -186,12 +203,12 @@ export async function startTelegram(
     try {
         const telegramClient = new Client.TelegramClient(runtime, botToken);
         await telegramClient.start();
-        console.log(
+        prettyConsole.success(
             `✅ Telegram client successfully started for character ${character.name}`
         );
         return telegramClient;
     } catch (error) {
-        console.error(
+        prettyConsole.error(
             `❌ Error creating/starting Telegram client for ${character.name}:`,
             error
         );
@@ -200,7 +217,7 @@ export async function startTelegram(
 }
 
 export async function startTwitter(runtime: IAgentRuntime) {
-    console.log("Starting Twitter clients...");
+    prettyConsole.log("Starting Twitter clients...");
     const twitterSearchClient = new Client.TwitterSearchClient(runtime);
     await wait();
     const twitterInteractionClient = new Client.TwitterInteractionClient(
diff --git a/core/src/clients/telegram/src/index.ts b/core/src/clients/telegram/src/index.ts
index 21505cab590..c378db8cfb3 100644
--- a/core/src/clients/telegram/src/index.ts
+++ b/core/src/clients/telegram/src/index.ts
@@ -2,6 +2,7 @@ import { Context, Telegraf } from "telegraf";
 
 import { IAgentRuntime } from "../../../core/types.ts";
 import { MessageManager } from "./messageManager.ts";
+import { prettyConsole } from "../../../index.ts";
 
 export class TelegramClient {
     private bot: Telegraf<Context>;
@@ -9,18 +10,18 @@ export class TelegramClient {
     private messageManager: MessageManager;
 
     constructor(runtime: IAgentRuntime, botToken: string) {
-        console.log("📱 Constructing new TelegramClient...");
+        prettyConsole.log("📱 Constructing new TelegramClient...");
         this.runtime = runtime;
         this.bot = new Telegraf(botToken);
         this.messageManager = new MessageManager(this.bot, this.runtime);
 
-        console.log("Setting up message handler...");
+        prettyConsole.log("Setting up message handler...");
         this.bot.on("message", async (ctx) => {
             try {
-                console.log("📥 Received message:", ctx.message);
+                prettyConsole.log("📥 Received message:", ctx.message);
                 await this.messageManager.handleMessage(ctx);
             } catch (error) {
-                console.error("❌ Error handling message:", error);
+                prettyConsole.error("❌ Error handling message:", error);
                 await ctx.reply(
                     "An error occurred while processing your message."
                 );
@@ -29,48 +30,51 @@ export class TelegramClient {
 
         // Handle specific message types for better logging
         this.bot.on("photo", (ctx) => {
-            console.log(
+            prettyConsole.log(
                 "📸 Received photo message with caption:",
                 ctx.message.caption
             );
         });
 
         this.bot.on("document", (ctx) => {
-            console.log(
+            prettyConsole.log(
                 "📎 Received document message:",
                 ctx.message.document.file_name
             );
         });
 
         this.bot.catch((err, ctx) => {
-            console.error(`❌ Telegram Error for ${ctx.updateType}:`, err);
+            prettyConsole.error(
+                `❌ Telegram Error for ${ctx.updateType}:`,
+                err
+            );
             ctx.reply("An unexpected error occurred. Please try again later.");
         });
 
-        console.log("✅ TelegramClient constructor completed");
+        prettyConsole.log("✅ TelegramClient constructor completed");
     }
 
     public async start(): Promise<void> {
-        console.log("🚀 Starting Telegram bot...");
+        prettyConsole.log("🚀 Starting Telegram bot...");
         try {
             this.bot.launch({
                 dropPendingUpdates: true,
             });
-            console.log(
+            prettyConsole.log(
                 "✨ Telegram bot successfully launched and is running!"
             );
-            console.log(`Bot username: @${this.bot.botInfo?.username}`);
+            prettyConsole.log(`Bot username: @${this.bot.botInfo?.username}`);
 
             // Graceful shutdown handlers
             const shutdownHandler = async (signal: string) => {
-                console.log(
+                prettyConsole.log(
                     `⚠️ Received ${signal}. Shutting down Telegram bot gracefully...`
                 );
                 try {
                     await this.stop();
-                    console.log("🛑 Telegram bot stopped gracefully");
+                    prettyConsole.log("🛑 Telegram bot stopped gracefully");
                 } catch (error) {
-                    console.error(
+                    prettyConsole.error(
                         "❌ Error during Telegram bot shutdown:",
                         error
                     );
@@ -82,14 +86,14 @@ export class TelegramClient {
             process.once("SIGTERM", () => shutdownHandler("SIGTERM"));
             process.once("SIGHUP", () => shutdownHandler("SIGHUP"));
         } catch (error) {
-            console.error("❌ Failed to launch Telegram bot:", error);
+            prettyConsole.error("❌ Failed to launch Telegram bot:", error);
             throw error;
         }
     }
 
     public async stop(): Promise<void> {
-        console.log("Stopping Telegram bot...");
+        prettyConsole.log("Stopping Telegram bot...");
         await this.bot.stop();
-        console.log("Telegram bot stopped");
+        prettyConsole.log("Telegram bot stopped");
     }
 }
diff --git a/core/src/clients/telegram/src/messageManager.ts b/core/src/clients/telegram/src/messageManager.ts
index ed2566d0814..e662f5f98d6 100644
--- a/core/src/clients/telegram/src/messageManager.ts
+++ b/core/src/clients/telegram/src/messageManager.ts
@@ -42,10 +42,10 @@ export class MessageManager {
     private async processImage(
         message: Message
     ): Promise<{ description: string } | null> {
-        console.log(
-            "🖼️ Processing image message:",
-            JSON.stringify(message, null, 2)
-        );
+        // console.log(
+        //     "🖼️ Processing image message:",
+        //     JSON.stringify(message, null, 2)
+        // );
 
         try {
             let imageUrl: string | null = null;
diff --git a/core/src/clients/twitter/base.ts b/core/src/clients/twitter/base.ts
index 2bc06e43d78..e0fbdb57c7a 100644
--- a/core/src/clients/twitter/base.ts
+++ b/core/src/clients/twitter/base.ts
@@ -21,6 +21,7 @@ import ImageDescriptionService from "../../services/image.ts";
 import { glob } from "glob";
 
 import { stringToUuid } from "../../core/uuid.ts";
+import { prettyConsole } from "../../index.ts";
 
 export function extractAnswer(text: string): string {
     const startIndex = text.indexOf("Answer: ") + 8;
@@ -429,7 +430,7 @@ export class ClientBase extends EventEmitter {
                             : undefined,
                     } as Content;
 
-                    console.log("Creating memory for tweet", tweet.id);
+                    prettyConsole.log("Creating memory for tweet", tweet.id);
 
                     // check if it already exists
                     const memory =
@@ -437,7 +438,7 @@ export class ClientBase extends EventEmitter {
                             stringToUuid(tweet.id)
                         );
                     if (memory) {
-                        console.log(
+                        prettyConsole.log(
                             "Memory already exists, skipping timeline population"
                         );
                         break;
@@ -453,7 +454,7 @@ export class ClientBase extends EventEmitter {
                     });
                 }
 
-                console.log(
+                prettyConsole.log(
                     `Populated ${tweetsToSave.length} missing tweets from the cache.`
                 );
                 return;
diff --git a/core/src/clients/twitter/utils.ts b/core/src/clients/twitter/utils.ts
index aec300cab33..9fff81e3f2f 100644
--- a/core/src/clients/twitter/utils.ts
+++ b/core/src/clients/twitter/utils.ts
@@ -3,6 +3,7 @@ import { embeddingZeroVector } from "../../core/memory.ts";
 import { Content, Memory, UUID } from "../../core/types.ts";
 import { stringToUuid } from "../../core/uuid.ts";
 import { ClientBase } from "./base.ts";
+import { prettyConsole } from "../../index.ts";
 
 const MAX_TWEET_LENGTH = 280;
 
@@ -36,7 +37,7 @@ export async function buildConversationThread(
 
     async function processThread(currentTweet: Tweet) {
         if (!currentTweet) {
-            console.log("No current tweet found");
+            prettyConsole.log("No current tweet found");
             return;
         }
         // check if the current tweet has already been saved
@@ -44,7 +45,7 @@ export async function buildConversationThread(
             stringToUuid(currentTweet.id)
         );
         if (!memory) {
-            console.log("Creating memory for tweet", currentTweet.id);
+            prettyConsole.log("Creating memory for tweet", currentTweet.id);
             const roomId = stringToUuid(currentTweet.conversationId);
             const userId = stringToUuid(currentTweet.userId);
 
@@ -108,9 +109,9 @@ export async function sendTweetChunks(
                     inReplyTo
                 )
         );
-        console.log("send tweet result:\n", result);
+        // console.log("send tweet result:\n", result);
         const body = await result.json();
-        console.log("send tweet body:\n", body);
+        console.log("send tweet body:\n", body.data.create_tweet.tweet_results);
         const tweetResult = body.data.create_tweet.tweet_results.result;
 
         const finalTweet = {
diff --git a/core/src/core/generation.ts b/core/src/core/generation.ts
index 79bf2729778..588fd1efd4c 100644
--- a/core/src/core/generation.ts
+++ b/core/src/core/generation.ts
@@ -12,9 +12,10 @@ import { default as tiktoken, TiktokenModel } from "tiktoken";
 import models from "./models.ts";
 
 import { generateText as aiGenerateText } from "ai";
-import { createAnthropicVertex } from "anthropic-vertex-ai";
-import Anthropic from "@anthropic-ai/sdk";
+
 import { createAnthropic } from "@ai-sdk/anthropic";
+import { prettyConsole } from "../index.ts";
+
 /**
  * Send a message to the model for a text generateText - receive a string back and parse how you'd like
  * @param opts - The options for the generateText request.
@@ -55,7 +56,7 @@ export async function generateText({
     const apiKey = runtime.token;
 
     try {
-        console.log(
+        prettyConsole.log(
             `Trimming context to max length of ${max_context_length} tokens.`
         );
         context = await trimTokens(context, max_context_length, "gpt-4o");
@@ -63,14 +64,14 @@ export async function generateText({
         let response: string;
 
         const _stop = stop || models[provider].settings.stop;
-        console.log(
+        prettyConsole.log(
             `Using provider: ${provider}, model: ${model}, temperature: ${temperature}, max response length: ${max_response_length}`
         );
 
         switch (provider) {
             case ModelProvider.OPENAI:
             case ModelProvider.LLAMACLOUD: {
-                console.log("Initializing OpenAI model.");
+                prettyConsole.log("Initializing OpenAI model.");
                 const openai = createOpenAI({ apiKey });
 
                 const { text: openaiResponse } = await aiGenerateText({
@@ -83,12 +84,12 @@ export async function generateText({
                 });
 
                 response = openaiResponse;
-                console.log("Received response from OpenAI model.");
+                prettyConsole.log("Received response from OpenAI model.");
                 break;
             }
 
             case ModelProvider.ANTHROPIC: {
-                console.log("Initializing Anthropic model.");
+                prettyConsole.log("Initializing Anthropic model.");
 
                 const anthropic = createAnthropic({ apiKey });
 
@@ -102,12 +103,12 @@ export async function generateText({
                 });
 
                 response = anthropicResponse;
-                console.log("Received response from Anthropic model.");
+                prettyConsole.log("Received response from Anthropic model.");
                 break;
             }
 
             case ModelProvider.GROK: {
-                console.log("Initializing Grok model.");
+                prettyConsole.log("Initializing Grok model.");
                 const grok = createGroq({ apiKey });
 
                 const { text: grokResponse } = await aiGenerateText({
@@ -122,12 +123,14 @@ export async function generateText({
                 });
 
                 response = grokResponse;
-                console.log("Received response from Grok model.");
+                prettyConsole.log("Received response from Grok model.");
                 break;
             }
 
             case ModelProvider.LLAMALOCAL:
-                console.log("Using local Llama model for text completion.");
+                prettyConsole.log(
+                    "Using local Llama model for text completion."
+                );
                 response = await runtime.llamaService.queueTextCompletion(
                     context,
                     temperature,
@@ -136,19 +139,19 @@ export async function generateText({
                     presence_penalty,
                     max_response_length
                 );
-                console.log("Received response from local Llama model.");
+                prettyConsole.log("Received response from local Llama model.");
                 break;
 
             default: {
                 const errorMessage = `Unsupported provider: ${provider}`;
-                console.error(errorMessage);
+                prettyConsole.error(errorMessage);
                 throw new Error(errorMessage);
             }
         }
 
         return response;
     } catch (error) {
-        console.error("Error in generateText:", error);
+        prettyConsole.error("Error in generateText:", error);
         throw error;
     }
 }
@@ -198,34 +201,37 @@ export async function generateShouldRespond({
     let retryDelay = 1000;
     while (true) {
         try {
-            console.log("Attempting to generate text with context:", context);
+            prettyConsole.log(
+                "Attempting to generate text with context:",
+                context
+            );
             const response = await generateText({
                 runtime,
                 context,
                 modelClass,
             });
 
-            console.log("Received response from generateText:", response);
+            prettyConsole.log("Received response from generateText:", response);
             const parsedResponse = parseShouldRespondFromText(response.trim());
             if (parsedResponse) {
-                console.log("Parsed response:", parsedResponse);
+                prettyConsole.log("Parsed response:", parsedResponse);
                 return parsedResponse;
             } else {
-                console.log("generateShouldRespond no response");
+                prettyConsole.log("generateShouldRespond no response");
             }
         } catch (error) {
-            console.error("Error in generateShouldRespond:", error);
+            prettyConsole.error("Error in generateShouldRespond:", error);
             if (
                 error instanceof TypeError &&
                 error.message.includes("queueTextCompletion")
             ) {
-                console.error(
+                prettyConsole.error(
                     "TypeError: Cannot read properties of null (reading 'queueTextCompletion')"
                 );
             }
         }
 
-        console.log(`Retrying in ${retryDelay}ms...`);
+        prettyConsole.log(`Retrying in ${retryDelay}ms...`);
         await new Promise((resolve) => setTimeout(resolve, retryDelay));
         retryDelay *= 2;
     }
@@ -316,7 +322,7 @@ export async function generateTrueOrFalse({
                 return parsedResponse;
             }
         } catch (error) {
-            console.error("Error in generateTrueOrFalse:", error);
+            prettyConsole.error("Error in generateTrueOrFalse:", error);
         }
 
         await new Promise((resolve) => setTimeout(resolve, retryDelay));
@@ -349,7 +355,7 @@ export async function generateTextArray({
     modelClass: string;
 }): Promise<string[]> {
     if (!context) {
-        console.error("generateTextArray context is empty");
+        prettyConsole.error("generateTextArray context is empty");
         return [];
     }
     let retryDelay = 1000;
@@ -367,7 +373,7 @@ export async function generateTextArray({
                 return parsedResponse;
             }
         } catch (error) {
-            console.error("Error in generateTextArray:", error);
+            prettyConsole.error("Error in generateTextArray:", error);
         }
 
         await new Promise((resolve) => setTimeout(resolve, retryDelay));
@@ -385,7 +391,7 @@ export async function generateObjectArray({
     modelClass: string;
 }): Promise<any[]> {
     if (!context) {
-        console.error("generateObjectArray context is empty");
+        prettyConsole.error("generateObjectArray context is empty");
         return [];
     }
     let retryDelay = 1000;
@@ -403,7 +409,7 @@ export async function generateObjectArray({
                 return parsedResponse;
             }
         } catch (error) {
-            console.error("Error in generateTextArray:", error);
+            prettyConsole.error("Error in generateTextArray:", error);
         }
 
         await new Promise((resolve) => setTimeout(resolve, retryDelay));
@@ -446,20 +452,17 @@ export async function generateMessageResponse({
             // try parsing the response as JSON, if null then try again
             const parsedContent = parseJSONObjectFromText(response) as Content;
             if (!parsedContent) {
-                console.log("parsedContent is null, retrying");
+                prettyConsole.log("parsedContent is null, retrying");
                 continue;
             }
 
             return parsedContent;
         } catch (error) {
-            console.error("ERROR:", error);
+            prettyConsole.error("ERROR:", error);
             // wait for 2 seconds
             retryLength *= 2;
             await new Promise((resolve) => setTimeout(resolve, retryLength));
-            console.log("Retrying...");
+            prettyConsole.log("Retrying...");
         }
     }
-    throw new Error(
-        "Failed to complete message after 5 tries, probably a network connectivity, model or API key issue"
-    );
 }
diff --git a/core/src/core/runtime.ts b/core/src/core/runtime.ts
index dce60d50c95..95cb59f8bcf 100644
--- a/core/src/core/runtime.ts
+++ b/core/src/core/runtime.ts
@@ -55,6 +55,7 @@ import settings from "./settings.ts";
 import { UUID, type Actor } from "./types.ts";
 import { stringToUuid } from "./uuid.ts";
 import { ImageGenModel } from "./imageGenModels.ts";
+import { prettyConsole } from "../index.ts";
 
 /**
  * Represents the runtime environment for an agent, handling message processing,
@@ -403,6 +404,7 @@ export class AgentRuntime implements IAgentRuntime {
      * @param action The action to register.
      */
     registerAction(action: Action) {
+        prettyConsole.success(`Registering action: ${action.name}`);
         this.actions.push(action);
     }
 
@@ -586,7 +588,7 @@ export class AgentRuntime implements IAgentRuntime {
                 email: email || (userName || "Bot") + "@" + source || "Unknown", // Temporary
                 details: { summary: "" },
             });
-            console.log(`User ${userName} created successfully.`);
+            prettyConsole.success(`User ${userName} created successfully.`);
         }
     }
 
@@ -595,7 +597,7 @@ export class AgentRuntime implements IAgentRuntime {
             await this.databaseAdapter.getParticipantsForRoom(roomId);
         if (!participants.includes(userId)) {
             await this.databaseAdapter.addParticipant(userId, roomId);
-            console.log(
+            prettyConsole.log(
                 `User ${userId} linked to room ${roomId} successfully.`
             );
         }
@@ -641,7 +643,7 @@ export class AgentRuntime implements IAgentRuntime {
         const room = await this.databaseAdapter.getRoom(roomId);
         if (!room) {
             await this.databaseAdapter.createRoom(roomId);
-            console.log(`Room ${roomId} created successfully.`);
+            prettyConsole.log(`Room ${roomId} created successfully.`);
         }
     }
 
diff --git a/core/src/index.ts b/core/src/index.ts
index b017d0be27e..0eec821d9ce 100644
--- a/core/src/index.ts
+++ b/core/src/index.ts
@@ -19,6 +19,7 @@ import {
     loadCharacters,
     parseArguments,
 } from "./cli/index.ts";
+import { PrettyConsole } from "./cli/colors.ts";
 
 let argv: Arguments = parseArguments();
 
@@ -26,10 +27,17 @@ const characters = loadCharacters(argv.characters);
 
 const directClient = new Client.DirectClient();
 
+// Initialize the pretty console
+export const prettyConsole = new PrettyConsole();
+prettyConsole.clear();
+prettyConsole.closeByNewLine = true;
+prettyConsole.useIcons = true;
+
+// Start the direct client
 directClient.start(3000);
 
 async function startAgent(character: Character) {
-    console.log(`Starting agent for character ${character.name}`);
+    prettyConsole.success(`Starting agent for character ${character.name}`);
     const token = getTokenForProvider(character.modelProvider, character);
     const db = initializeDatabase();
 
@@ -37,7 +45,7 @@ async function startAgent(character: Character) {
     const directRuntime = createDirectRuntime(character, db, token);
 
     const clients = await initializeClients(character, runtime);
-    directClient.registerAgent(directRuntime);
+    directClient.registerAgent(await directRuntime);
 
     return clients;
 }

From 3b05a1a43b5d009692679549d6b7a38f8b8325ba Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 16:37:48 +1100
Subject: [PATCH 15/23] prettier

---
 core/src/core/models.ts | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/core/src/core/models.ts b/core/src/core/models.ts
index 5e397effb02..cf9fd861217 100644
--- a/core/src/core/models.ts
+++ b/core/src/core/models.ts
@@ -104,13 +104,15 @@ const models: Models = {
             temperature: 0.3,
         },
         model: {
-            [ModelClass.SMALL]: "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
+            [ModelClass.SMALL]:
+                "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
             [ModelClass.MEDIUM]:
                 "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true", // TODO: ?download=true
             [ModelClass.LARGE]:
-            "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
-                // "RichardErkhov/NousResearch_-_Meta-Llama-3.1-70B-gguf", // TODO: 
-            [ModelClass.EMBEDDING]: "togethercomputer/m2-bert-80M-32k-retrieval"
+                "NousResearch/Hermes-3-Llama-3.1-8B-GGUF/resolve/main/Hermes-3-Llama-3.1-8B.Q8_0.gguf?download=true",
+            // "RichardErkhov/NousResearch_-_Meta-Llama-3.1-70B-gguf", // TODO:
+            [ModelClass.EMBEDDING]:
+                "togethercomputer/m2-bert-80M-32k-retrieval",
         },
     },
     [ModelProvider.GOOGLE]: {

From c0915e79a731234e4ffd929e2d35ffc9e2db5c90 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 17:50:21 +1100
Subject: [PATCH 16/23] discord env

---
 core/src/clients/discord/index.ts | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/core/src/clients/discord/index.ts b/core/src/clients/discord/index.ts
index 8409217d78e..22e0d1885fb 100644
--- a/core/src/clients/discord/index.ts
+++ b/core/src/clients/discord/index.ts
@@ -24,6 +24,7 @@ import { MessageManager } from "./messages.ts";
 import channelStateProvider from "./providers/channelState.ts";
 import voiceStateProvider from "./providers/voiceState.ts";
 import { VoiceManager } from "./voice.ts";
+import { prettyConsole } from "../../index.ts";
 
 export class DiscordClient extends EventEmitter {
     apiToken: string;
@@ -35,9 +36,7 @@ export class DiscordClient extends EventEmitter {
 
     constructor(runtime: IAgentRuntime) {
         super();
-        this.apiToken = runtime.getSetting(
-            "DISCORD_API_TOKEN_" + runtime.character.name.toUpperCase()
-        ) as string;
+        this.apiToken = runtime.getSetting("DISCORD_API_TOKEN") as string;
         this.client = new Client({
             intents: [
                 GatewayIntentBits.Guilds,
@@ -120,10 +119,7 @@ export class DiscordClient extends EventEmitter {
             try {
                 await rest.put(
                     Routes.applicationCommands(
-                        this.runtime.getSetting(
-                            "DISCORD_APPLICATION_ID_" +
-                                this.runtime.character.name.toUpperCase()
-                        )
+                        this.runtime.getSetting("DISCORD_APPLICATION_ID")
                     ),
                     { body: commands }
                 );
@@ -134,16 +130,16 @@ export class DiscordClient extends EventEmitter {
     }
 
     private async onClientReady(readyClient: { user: { tag: any; id: any } }) {
-        console.log(`Logged in as ${readyClient.user?.tag}`);
-        console.log("Use this URL to add the bot to your server:");
-        console.log(
+        prettyConsole.success(`Logged in as ${readyClient.user?.tag}`);
+        prettyConsole.success("Use this URL to add the bot to your server:");
+        prettyConsole.success(
             `https://discord.com/api/oauth2/authorize?client_id=${readyClient.user?.id}&permissions=0&scope=bot%20applications.commands`
         );
         await this.onReady();
     }
 
     async handleReactionAdd(reaction: MessageReaction, user: User) {
-        console.log("Reaction added");
+        prettyConsole.log("Reaction added");
         // if (user.bot) return;
 
         let emoji = reaction.emoji.name;

From a18c192aba597d40e239c7840935d51e0af312f4 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 17:55:24 +1100
Subject: [PATCH 17/23] add type script ref path for cleaner imports

---
 core/src/clients/telegram/src/messageManager.ts | 16 ++++++++--------
 core/tsconfig.json                              |  6 +++++-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/core/src/clients/telegram/src/messageManager.ts b/core/src/clients/telegram/src/messageManager.ts
index e662f5f98d6..5da74bcc3f6 100644
--- a/core/src/clients/telegram/src/messageManager.ts
+++ b/core/src/clients/telegram/src/messageManager.ts
@@ -2,9 +2,9 @@ import { Message } from "@telegraf/types";
 import { Context } from "telegraf";
 import { Telegraf } from "telegraf";
 
-import { composeContext } from "../../../core/context.ts";
-import { log_to_file } from "../../../core/logger.ts";
-import { embeddingZeroVector } from "../../../core/memory.ts";
+import { composeContext } from "@/core/context.ts";
+import { log_to_file } from "@/core/logger.ts";
+import { embeddingZeroVector } from "@/core/memory.ts";
 import {
     Content,
     IAgentRuntime,
@@ -13,17 +13,17 @@ import {
     UUID,
     HandlerCallback,
     ModelClass,
-} from "../../../core/types.ts";
-import { stringToUuid } from "../../../core/uuid.ts";
+} from "@/core/types.ts";
+import { stringToUuid } from "@/core/uuid.ts";
 import {
     messageHandlerTemplate,
     shouldRespondTemplate,
-} from "../../discord/templates.ts";
-import ImageDescriptionService from "../../../services/image.ts";
+} from "@/clients/discord/templates.ts";
+import ImageDescriptionService from "@/services/image.ts";
 import {
     generateMessageResponse,
     generateShouldRespond,
-} from "../../../core/generation.ts";
+} from "@/core/generation.ts";
 
 const MAX_MESSAGE_LENGTH = 4096; // Telegram's max message length
 
diff --git a/core/tsconfig.json b/core/tsconfig.json
index 3527f3ee01e..b8e6dc3265d 100644
--- a/core/tsconfig.json
+++ b/core/tsconfig.json
@@ -20,7 +20,11 @@
         "noEmitOnError": false,
         "moduleDetection": "force",
         "allowArbitraryExtensions": true,
-        "typeRoots": ["./node_modules/@types", "./types"]
+        "typeRoots": ["./node_modules/@types", "./types"],
+        "baseUrl": "./src",
+        "paths": {
+            "@/*": ["*"]
+        }
     },
     "include": ["src/**/*"],
     "exclude": ["node_modules", "dist", "src/**/*.d.ts", "types/**/*.test.ts"]

From 01bef5d967c5ddc66ce1513efe4695e437d2be18 Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 18:00:01 +1100
Subject: [PATCH 18/23] revert

---
 core/src/clients/telegram/src/messageManager.ts | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/core/src/clients/telegram/src/messageManager.ts b/core/src/clients/telegram/src/messageManager.ts
index 5da74bcc3f6..e662f5f98d6 100644
--- a/core/src/clients/telegram/src/messageManager.ts
+++ b/core/src/clients/telegram/src/messageManager.ts
@@ -2,9 +2,9 @@ import { Message } from "@telegraf/types";
 import { Context } from "telegraf";
 import { Telegraf } from "telegraf";
 
-import { composeContext } from "@/core/context.ts";
-import { log_to_file } from "@/core/logger.ts";
-import { embeddingZeroVector } from "@/core/memory.ts";
+import { composeContext } from "../../../core/context.ts";
+import { log_to_file } from "../../../core/logger.ts";
+import { embeddingZeroVector } from "../../../core/memory.ts";
 import {
     Content,
     IAgentRuntime,
@@ -13,17 +13,17 @@ import {
     UUID,
     HandlerCallback,
     ModelClass,
-} from "@/core/types.ts";
-import { stringToUuid } from "@/core/uuid.ts";
+} from "../../../core/types.ts";
+import { stringToUuid } from "../../../core/uuid.ts";
 import {
     messageHandlerTemplate,
     shouldRespondTemplate,
-} from "@/clients/discord/templates.ts";
-import ImageDescriptionService from "@/services/image.ts";
+} from "../../discord/templates.ts";
+import ImageDescriptionService from "../../../services/image.ts";
 import {
     generateMessageResponse,
     generateShouldRespond,
-} from "@/core/generation.ts";
+} from "../../../core/generation.ts";
 
 const MAX_MESSAGE_LENGTH = 4096; // Telegram's max message length
 

From 8bf480916b3ee4b64fd53bd7aefbde28f990b22d Mon Sep 17 00:00:00 2001
From: ponderingdemocritus <ponderingdemocritus@protonmail.com>
Date: Sun, 3 Nov 2024 18:13:47 +1100
Subject: [PATCH 19/23] remove path

---
 core/tsconfig.json | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/core/tsconfig.json b/core/tsconfig.json
index b8e6dc3265d..3527f3ee01e 100644
--- a/core/tsconfig.json
+++ b/core/tsconfig.json
@@ -20,11 +20,7 @@
         "noEmitOnError": false,
         "moduleDetection": "force",
         "allowArbitraryExtensions": true,
-        "typeRoots": ["./node_modules/@types", "./types"],
-        "baseUrl": "./src",
-        "paths": {
-            "@/*": ["*"]
-        }
+        "typeRoots": ["./node_modules/@types", "./types"]
     },
     "include": ["src/**/*"],
     "exclude": ["node_modules", "dist", "src/**/*.d.ts", "types/**/*.test.ts"]

From aee39f9901d364a38629849bbcf3dcfb91692a54 Mon Sep 17 00:00:00 2001
From: alextitonis <alexandrostitonis@gmail.com>
Date: Sun, 3 Nov 2024 16:24:07 +0300
Subject: [PATCH 20/23] server port in env

---
 core/.env.example | 3 ++-
 core/src/index.ts | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/core/.env.example b/core/.env.example
index 3ba2aaa4ed2..1d0c1d9a27d 100644
--- a/core/.env.example
+++ b/core/.env.example
@@ -42,4 +42,5 @@ HELIUS_API_KEY=
 ## Telegram
 TELEGRAM_BOT_TOKEN=
 
-TOGETHER_API_KEY=
\ No newline at end of file
+TOGETHER_API_KEY=
+SERVER_PORT=3000
diff --git a/core/src/index.ts b/core/src/index.ts
index b017d0be27e..a65a8f07727 100644
--- a/core/src/index.ts
+++ b/core/src/index.ts
@@ -26,7 +26,8 @@ const characters = loadCharacters(argv.characters);
 
 const directClient = new Client.DirectClient();
 
-directClient.start(3000);
+const serverPort = parseInt(process.env.SERVER_PORT || "3000");
+directClient.start(serverPort);
 
 async function startAgent(character: Character) {
     console.log(`Starting agent for character ${character.name}`);

From ce0e7157a318a58f1bd31762f80cd6cd7ca5be84 Mon Sep 17 00:00:00 2001
From: sirkitree <sirkitree@gmail.com>
Date: Sun, 3 Nov 2024 07:26:23 -0800
Subject: [PATCH 21/23] correct places were stricter checking is now in place

---
 .github/workflows/ci.yaml   |  6 ++++++
 core/package.json           |  3 ++-
 core/src/cli/config.ts      |  2 +-
 core/src/core/types.ts      |  2 +-
 core/src/providers/token.ts | 26 ++++++++++++--------------
 core/tsconfig.json          |  4 ++--
 6 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 746a58908b5..ace5060659c 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -25,5 +25,11 @@ jobs:
             - name: Run Prettier
               run: pnpm run prettier --check .
 
+            - name: Create test env file
+              run: cp core/.env.test.example core/.env.test || cp core/.env.test core/.env.test
+
+            - name: Run tests
+              run: cd core && pnpm test
+
             - name: Build packages
               run: pnpm run build
diff --git a/core/package.json b/core/package.json
index 309d9d71880..9a00fd6288b 100644
--- a/core/package.json
+++ b/core/package.json
@@ -67,7 +67,8 @@
         "ts-node": "10.9.2",
         "tslib": "2.8.0",
         "typescript": "5.6.3",
-        "wrangler": "3.84.0"
+        "wrangler": "3.84.0",
+        "@types/pdfjs-dist": "^2.10.378"
     },
     "pnpm": {
         "overrides": {
diff --git a/core/src/cli/config.ts b/core/src/cli/config.ts
index 05b7bda964e..cdc31253e10 100644
--- a/core/src/cli/config.ts
+++ b/core/src/cli/config.ts
@@ -2,7 +2,7 @@ import fs from "fs";
 import yaml from "js-yaml";
 import path from "path";
 import { fileURLToPath } from "url";
-import { Action } from "../core/types";
+import { Action } from "../core/types.ts";
 
 const ROOT_DIR = path.resolve(fileURLToPath(import.meta.url), "../../../src");
 
diff --git a/core/src/core/types.ts b/core/src/core/types.ts
index e088e446c10..d2cba443204 100644
--- a/core/src/core/types.ts
+++ b/core/src/core/types.ts
@@ -1,5 +1,5 @@
 import { Readable } from "stream";
-import { ImageGenModel } from "./imageGenModels";
+import { ImageGenModel } from "./imageGenModels.ts";
 
 /**
  * Represents a UUID, which is a universally unique identifier conforming to the UUID standard.
diff --git a/core/src/providers/token.ts b/core/src/providers/token.ts
index 9623cb2b57a..d20aedaebae 100644
--- a/core/src/providers/token.ts
+++ b/core/src/providers/token.ts
@@ -2,7 +2,7 @@ import { Connection } from "@solana/web3.js";
 // import fetch from "cross-fetch";
 import { IAgentRuntime, Memory, Provider, State } from "../core/types.ts";
 import settings from "../core/settings.ts";
-import BigNumber from "bignumber.js";
+import { toBN, BN } from '../utils/bignumber.js';
 import {
     ProcessedTokenData,
     TokenSecurityData,
@@ -609,40 +609,38 @@ export class TokenProvider {
     ): Promise<Array<{ holderAddress: string; balanceUsd: string }>> {
         const holdersData = await this.fetchHolderList();
 
-        const tokenPriceUsd = new BigNumber(tradeData.price);
+        const tokenPriceUsd = toBN(tradeData.price);
 
         const highValueHolders = holdersData
             .filter((holder) => {
-                const balanceUsd = new BigNumber(holder.balance).multipliedBy(
+                const balanceUsd = toBN(holder.balance).multipliedBy(
                     tokenPriceUsd
                 );
                 return balanceUsd.isGreaterThan(5);
             })
             .map((holder) => ({
                 holderAddress: holder.address,
-                balanceUsd: new BigNumber(holder.balance)
-                    .multipliedBy(tokenPriceUsd)
-                    .toFixed(2),
+                balanceUsd: toBN(holder.balance).multipliedBy(tokenPriceUsd).toFixed(2),
             }));
 
         return highValueHolders;
     }
 
     async checkRecentTrades(tradeData: TokenTradeData): Promise<boolean> {
-        return new BigNumber(tradeData.volume_24h_usd).isGreaterThan(0);
+        return toBN(tradeData.volume_24h_usd).isGreaterThan(0);
     }
 
     async countHighSupplyHolders(
         securityData: TokenSecurityData
     ): Promise<number> {
         try {
-            const ownerBalance = new BigNumber(securityData.ownerBalance);
+            const ownerBalance = toBN(securityData.ownerBalance);
             const totalSupply = ownerBalance.plus(securityData.creatorBalance);
 
             const highSupplyHolders = await this.fetchHolderList();
             const highSupplyHoldersCount = highSupplyHolders.filter(
                 (holder) => {
-                    const balance = new BigNumber(holder.balance);
+                    const balance = toBN(holder.balance);
                     return balance.dividedBy(totalSupply).isGreaterThan(0.02);
                 }
             ).length;
@@ -738,8 +736,8 @@ export class TokenProvider {
         output += `- Unique Wallets (24h): ${data.tradeData.unique_wallet_24h}\n`;
         output += `- Price Change (24h): ${data.tradeData.price_change_24h_percent}%\n`;
         output += `- Price Change (12h): ${data.tradeData.price_change_12h_percent}%\n`;
-        output += `- Volume (24h USD): $${new BigNumber(data.tradeData.volume_24h_usd).toFixed(2)}\n`;
-        output += `- Current Price: $${new BigNumber(data.tradeData.price).toFixed(2)}\n\n`;
+        output += `- Volume (24h USD): $${toBN(data.tradeData.volume_24h_usd).toFixed(2)}\n`;
+        output += `- Current Price: $${toBN(data.tradeData.price).toFixed(2)}\n\n`;
 
         // Holder Distribution Trend
         output += `**Holder Distribution Trend:** ${data.holderDistributionTrend}\n\n`;
@@ -771,10 +769,10 @@ export class TokenProvider {
                 output += `\n**Pair ${index + 1}:**\n`;
                 output += `- DEX: ${pair.dexId}\n`;
                 output += `- URL: ${pair.url}\n`;
-                output += `- Price USD: $${new BigNumber(pair.priceUsd).toFixed(6)}\n`;
-                output += `- Volume (24h USD): $${new BigNumber(pair.volume.h24).toFixed(2)}\n`;
+                output += `- Price USD: $${toBN(pair.priceUsd).toFixed(6)}\n`;
+                output += `- Volume (24h USD): $${toBN(pair.volume.h24).toFixed(2)}\n`;
                 output += `- Boosts Active: ${pair.boosts && pair.boosts.active}\n`;
-                output += `- Liquidity USD: $${new BigNumber(pair.liquidity.usd).toFixed(2)}\n`;
+                output += `- Liquidity USD: $${toBN(pair.liquidity.usd).toFixed(2)}\n`;
             });
         }
         output += `\n`;
diff --git a/core/tsconfig.json b/core/tsconfig.json
index afba577e90f..54842ba1c47 100644
--- a/core/tsconfig.json
+++ b/core/tsconfig.json
@@ -1,9 +1,9 @@
 {
     "compilerOptions": {
         "target": "ESNext",
-        "module": "NodeNext",
+        "module": "ESNext",
         "lib": ["ESNext", "dom"],
-        "moduleResolution": "NodeNext",
+        "moduleResolution": "Bundler",
         "outDir": "./dist",
         "rootDir": "./src",
         "strict": false,

From 5898d7cf6d1b3de4cf778d82545455e8d614e875 Mon Sep 17 00:00:00 2001
From: sirkitree <sirkitree@gmail.com>
Date: Sun, 3 Nov 2024 07:30:39 -0800
Subject: [PATCH 22/23] update ci to run the basic test

---
 .github/workflows/ci.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ace5060659c..0e24143d6b0 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -26,7 +26,9 @@ jobs:
               run: pnpm run prettier --check .
 
             - name: Create test env file
-              run: cp core/.env.test.example core/.env.test || cp core/.env.test core/.env.test
+              run: |
+                echo "TEST_DATABASE_CLIENT=sqlite" > core/.env.test
+                echo "NODE_ENV=test" >> core/.env.test
 
             - name: Run tests
               run: cd core && pnpm test

From a432cd7e3e8410573152074f9843335661ae85ef Mon Sep 17 00:00:00 2001
From: sirkitree <sirkitree@gmail.com>
Date: Sun, 3 Nov 2024 07:35:58 -0800
Subject: [PATCH 23/23] add util files

---
 core/src/utils/bignumber.ts | 9 +++++++++
 core/src/utils/youtube.ts   | 3 +++
 2 files changed, 12 insertions(+)
 create mode 100644 core/src/utils/bignumber.ts
 create mode 100644 core/src/utils/youtube.ts

diff --git a/core/src/utils/bignumber.ts b/core/src/utils/bignumber.ts
new file mode 100644
index 00000000000..7bcf3cfb10e
--- /dev/null
+++ b/core/src/utils/bignumber.ts
@@ -0,0 +1,9 @@
+import BigNumber from 'bignumber.js';
+
+// Re-export BigNumber constructor
+export const BN = BigNumber;
+
+// Helper function to create new BigNumber instances
+export function toBN(value: string | number | BigNumber): BigNumber {
+    return new BigNumber(value);
+}
\ No newline at end of file
diff --git a/core/src/utils/youtube.ts b/core/src/utils/youtube.ts
new file mode 100644
index 00000000000..253dd060c19
--- /dev/null
+++ b/core/src/utils/youtube.ts
@@ -0,0 +1,3 @@
+import youtubeDl from 'youtube-dl-exec';
+
+export const youtube = (url: string, options?: any) => youtubeDl(url, options);
\ No newline at end of file