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