diff --git a/.env.example b/.env.example index 28ded6975..c2d1e1821 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,16 @@ -# Required environment variables +# Discord Configuration DISCORD_APPLICATION_ID= DISCORD_API_TOKEN= # Bot token + +# AI Model API Keys OPENAI_API_KEY= # OpenAI API key, starting with sk- REDPILL_API_KEY= # REDPILL API Key GROK_API_KEY= # GROK API Key GROQ_API_KEY= # Starts with gsk_ OPENROUTER_API_KEY= GOOGLE_GENERATIVE_AI_API_KEY= # Gemini API key + +# Speech Synthesis ELEVENLABS_XI_API_KEY= # API key from elevenlabs # ElevenLabs Settings @@ -73,11 +77,18 @@ BASE_MINT=So11111111111111111111111111111111111111112 RPC_URL=https://api.mainnet-beta.solana.com HELIUS_API_KEY= -# Other Services +# Telegram Configuration TELEGRAM_BOT_TOKEN= + +# Together Configuration TOGETHER_API_KEY= + +# Server Configuration SERVER_PORT=3000 # Starknet Configuration STARKNET_ADDRESS= STARKNET_PRIVATE_KEY= +STARKNET_RPC_URL= + + diff --git a/agent/src/index.ts b/agent/src/index.ts index bd78a2f4c..9ab8b17d2 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -1,6 +1,6 @@ import { PostgresDatabaseAdapter } from "@ai16z/adapter-postgres"; import { SqliteDatabaseAdapter } from "@ai16z/adapter-sqlite"; -import { DirectClient, DirectClientInterface } from "@ai16z/client-direct"; +import { DirectClientInterface } from "@ai16z/client-direct"; import { DiscordClientInterface } from "@ai16z/client-discord"; import { AutoClientInterface } from "@ai16z/client-auto"; import { TelegramClientInterface } from "@ai16z/client-telegram"; @@ -20,6 +20,7 @@ import { elizaLogger, settings, IDatabaseAdapter, + validateCharacterConfig, } from "@ai16z/eliza"; import { bootstrapPlugin } from "@ai16z/plugin-bootstrap"; import { solanaPlugin } from "@ai16z/plugin-solana"; @@ -30,7 +31,8 @@ import readline from "readline"; import yargs from "yargs"; import path from "path"; import { fileURLToPath } from "url"; -import { character } from "./character.ts"; +import blobert from "./blobert.ts"; +import { DirectClient } from "@ai16z/client-direct"; const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file const __dirname = path.dirname(__filename); // get the name of the directory diff --git a/packages/client-discord/src/enviroment.ts b/packages/client-discord/src/enviroment.ts index 149c7da7d..269bfd925 100644 --- a/packages/client-discord/src/enviroment.ts +++ b/packages/client-discord/src/enviroment.ts @@ -10,21 +10,16 @@ export const discordEnvSchema = z.object({ export type DiscordConfig = z.infer; -// Validate and export the config -export const discordConfig = discordEnvSchema.parse({ - DISCORD_APPLICATION_ID: process.env.DISCORD_APPLICATION_ID, - DISCORD_API_TOKEN: process.env.DISCORD_API_TOKEN, -}); - -export function validateDiscordConfig(runtime: IAgentRuntime): DiscordConfig { - console.log(runtime?.character.settings.secrets.DISCORD_APPLICATION_ID); +export async function validateDiscordConfig( + runtime: IAgentRuntime +): Promise { try { const config = { DISCORD_APPLICATION_ID: - runtime?.character.settings.secrets.DISCORD_APPLICATION_ID || + runtime.getSetting("DISCORD_APPLICATION_ID") || process.env.DISCORD_APPLICATION_ID, DISCORD_API_TOKEN: - runtime?.character.settings.secrets.DISCORD_API_TOKEN || + runtime.getSetting("DISCORD_API_TOKEN") || process.env.DISCORD_API_TOKEN, }; diff --git a/packages/client-discord/src/index.ts b/packages/client-discord/src/index.ts index 743ce2013..061f8e55c 100644 --- a/packages/client-discord/src/index.ts +++ b/packages/client-discord/src/index.ts @@ -299,7 +299,8 @@ export function startDiscord(runtime: IAgentRuntime) { export const DiscordClientInterface: ElizaClient = { start: async (runtime: IAgentRuntime) => { - // validateDiscordConfig(runtime); + await validateDiscordConfig(runtime); + return new DiscordClient(runtime); }, stop: async (runtime: IAgentRuntime) => { diff --git a/packages/client-github/src/enviroment.ts b/packages/client-github/src/enviroment.ts new file mode 100644 index 000000000..69df61ac3 --- /dev/null +++ b/packages/client-github/src/enviroment.ts @@ -0,0 +1,38 @@ +import { IAgentRuntime } from "@ai16z/eliza"; +import { z } from "zod"; + +export const githubEnvSchema = z.object({ + GITHUB_OWNER: z.string().min(1, "GitHub owner is required"), + GITHUB_REPO: z.string().min(1, "GitHub repo is required"), + GITHUB_BRANCH: z.string().min(1, "GitHub branch is required"), + GITHUB_PATH: z.string().min(1, "GitHub path is required"), + GITHUB_API_TOKEN: z.string().min(1, "GitHub API token is required"), +}); + +export type GithubConfig = z.infer; + +export async function validateGithubConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + GITHUB_OWNER: runtime.getSetting("GITHUB_OWNER"), + GITHUB_REPO: runtime.getSetting("GITHUB_REPO"), + GITHUB_BRANCH: runtime.getSetting("GITHUB_BRANCH"), + GITHUB_PATH: runtime.getSetting("GITHUB_PATH"), + GITHUB_API_TOKEN: runtime.getSetting("GITHUB_API_TOKEN"), + }; + + return githubEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `GitHub configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/client-github/src/index.ts b/packages/client-github/src/index.ts index 59260baea..17ad91a29 100644 --- a/packages/client-github/src/index.ts +++ b/packages/client-github/src/index.ts @@ -17,6 +17,7 @@ import { splitChunks, embed, } from "@ai16z/eliza"; +import { validateGithubConfig } from "./enviroment"; export interface GitHubConfig { owner: string; @@ -220,6 +221,7 @@ export class GitHubClient { export const GitHubClientInterface: Client = { start: async (runtime: IAgentRuntime) => { + await validateGithubConfig(runtime); elizaLogger.log("GitHubClientInterface start"); const client = new GitHubClient(runtime as AgentRuntime); diff --git a/packages/client-telegram/src/enviroment.ts b/packages/client-telegram/src/enviroment.ts index cb4c5a131..b83b9e896 100644 --- a/packages/client-telegram/src/enviroment.ts +++ b/packages/client-telegram/src/enviroment.ts @@ -1,3 +1,4 @@ +import { IAgentRuntime } from "@ai16z/eliza"; import { z } from "zod"; export const telegramEnvSchema = z.object({ @@ -6,14 +7,17 @@ export const telegramEnvSchema = z.object({ export type TelegramConfig = z.infer; -// Validate and export the config -export const telegramConfig = telegramEnvSchema.parse({ - TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN, -}); - -export function validateTelegramConfig(): TelegramConfig { +export async function validateTelegramConfig( + runtime: IAgentRuntime +): Promise { try { - return telegramEnvSchema.parse(process.env); + const config = { + TELEGRAM_BOT_TOKEN: + runtime.getSetting("TELEGRAM_BOT_TOKEN") || + process.env.TELEGRAM_BOT_TOKEN, + }; + + return telegramEnvSchema.parse(config); } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.errors diff --git a/packages/client-telegram/src/index.ts b/packages/client-telegram/src/index.ts index 91b288d8d..41008057e 100644 --- a/packages/client-telegram/src/index.ts +++ b/packages/client-telegram/src/index.ts @@ -5,7 +5,7 @@ import { validateTelegramConfig } from "./enviroment.ts"; export const TelegramClientInterface: Client = { start: async (runtime: IAgentRuntime) => { - validateTelegramConfig(); + await validateTelegramConfig(runtime); const tg = new TelegramClient( runtime, diff --git a/packages/client-twitter/src/enviroment.ts b/packages/client-twitter/src/enviroment.ts index f318d93a0..58d456f5f 100644 --- a/packages/client-twitter/src/enviroment.ts +++ b/packages/client-twitter/src/enviroment.ts @@ -1,29 +1,41 @@ +import { IAgentRuntime } from "@ai16z/eliza"; import { z } from "zod"; export const twitterEnvSchema = z.object({ TWITTER_DRY_RUN: z .string() .transform((val) => val.toLowerCase() === "true"), - TWITTER_USERNAME: z.string().min(1), - TWITTER_PASSWORD: z.string().min(1), - TWITTER_EMAIL: z.string().email(), + TWITTER_USERNAME: z.string().min(1, "Twitter username is required"), + TWITTER_PASSWORD: z.string().min(1, "Twitter password is required"), + TWITTER_EMAIL: z.string().email("Valid Twitter email is required"), TWITTER_COOKIES: z.string().optional(), }); export type TwitterConfig = z.infer; -// Validate and export the config -export const twitterConfig = twitterEnvSchema.parse({ - TWITTER_DRY_RUN: process.env.TWITTER_DRY_RUN, - TWITTER_USERNAME: process.env.TWITTER_USERNAME, - TWITTER_PASSWORD: process.env.TWITTER_PASSWORD, - TWITTER_EMAIL: process.env.TWITTER_EMAIL, - TWITTER_COOKIES: process.env.TWITTER_COOKIES, -}); - -export function validateTwitterConfig(): TwitterConfig { +export async function validateTwitterConfig( + runtime: IAgentRuntime +): Promise { try { - return twitterEnvSchema.parse(process.env); + const config = { + TWITTER_DRY_RUN: + runtime.getSetting("TWITTER_DRY_RUN") || + process.env.TWITTER_DRY_RUN, + TWITTER_USERNAME: + runtime.getSetting("TWITTER_USERNAME") || + process.env.TWITTER_USERNAME, + TWITTER_PASSWORD: + runtime.getSetting("TWITTER_PASSWORD") || + process.env.TWITTER_PASSWORD, + TWITTER_EMAIL: + runtime.getSetting("TWITTER_EMAIL") || + process.env.TWITTER_EMAIL, + TWITTER_COOKIES: + runtime.getSetting("TWITTER_COOKIES") || + process.env.TWITTER_COOKIES, + }; + + return twitterEnvSchema.parse(config); } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.errors diff --git a/packages/client-twitter/src/index.ts b/packages/client-twitter/src/index.ts index ab6bc5908..2ac9056e3 100644 --- a/packages/client-twitter/src/index.ts +++ b/packages/client-twitter/src/index.ts @@ -23,7 +23,7 @@ class TwitterManager { export const TwitterClientInterface: Client = { async start(runtime: IAgentRuntime) { - validateTwitterConfig(); + await validateTwitterConfig(runtime); elizaLogger.log("Twitter client started"); diff --git a/packages/plugin-image-generation/src/enviroment.ts b/packages/plugin-image-generation/src/enviroment.ts new file mode 100644 index 000000000..9fea6d94a --- /dev/null +++ b/packages/plugin-image-generation/src/enviroment.ts @@ -0,0 +1,54 @@ +import { IAgentRuntime } from "@ai16z/eliza"; +import { z } from "zod"; + +export const imageGenEnvSchema = z + .object({ + ANTHROPIC_API_KEY: z.string().optional(), + TOGETHER_API_KEY: z.string().optional(), + HEURIST_API_KEY: z.string().optional(), + }) + .refine( + (data) => { + return !!( + data.ANTHROPIC_API_KEY || + data.TOGETHER_API_KEY || + data.HEURIST_API_KEY + ); + }, + { + message: + "At least one of ANTHROPIC_API_KEY, TOGETHER_API_KEY, or HEURIST_API_KEY is required", + } + ); + +export type ImageGenConfig = z.infer; + +export async function validateImageGenConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + ANTHROPIC_API_KEY: + runtime.getSetting("ANTHROPIC_API_KEY") || + process.env.ANTHROPIC_API_KEY, + TOGETHER_API_KEY: + runtime.getSetting("TOGETHER_API_KEY") || + process.env.TOGETHER_API_KEY, + HEURIST_API_KEY: + runtime.getSetting("HEURIST_API_KEY") || + process.env.HEURIST_API_KEY, + }; + + return imageGenEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `Image generation configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/plugin-image-generation/src/index.ts b/packages/plugin-image-generation/src/index.ts index 05b3995a1..0aac366e1 100644 --- a/packages/plugin-image-generation/src/index.ts +++ b/packages/plugin-image-generation/src/index.ts @@ -11,6 +11,7 @@ import { generateCaption, generateImage } from "@ai16z/eliza"; import fs from "fs"; import path from "path"; +import { validateImageGenConfig } from "./enviroment"; export function saveBase64Image(base64Data: string, filename: string): string { // Create generatedImages directory if it doesn't exist @@ -76,6 +77,8 @@ const imageGeneration: Action = { ], description: "Generate an image to go along with the message.", validate: async (runtime: IAgentRuntime, message: Memory) => { + await validateImageGenConfig(runtime); + const anthropicApiKeyOk = !!runtime.getSetting("ANTHROPIC_API_KEY"); const togetherApiKeyOk = !!runtime.getSetting("TOGETHER_API_KEY"); const heuristApiKeyOk = !!runtime.getSetting("HEURIST_API_KEY"); diff --git a/packages/plugin-node/src/enviroment.ts b/packages/plugin-node/src/enviroment.ts new file mode 100644 index 000000000..779704cb4 --- /dev/null +++ b/packages/plugin-node/src/enviroment.ts @@ -0,0 +1,77 @@ +import { IAgentRuntime } from "@ai16z/eliza"; +import { z } from "zod"; + +export const nodeEnvSchema = z.object({ + OPENAI_API_KEY: z.string().min(1, "OpenAI API key is required"), + ELEVENLABS_XI_API_KEY: z.string().optional(), + ELEVENLABS_MODEL_ID: z.string().min(1, "ElevenLabs model ID is required"), + ELEVENLABS_VOICE_ID: z.string().min(1, "ElevenLabs voice ID is required"), + ELEVENLABS_VOICE_STABILITY: z + .string() + .min(1, "ElevenLabs voice stability is required"), + ELEVENLABS_VOICE_SIMILARITY_BOOST: z + .string() + .min(1, "ElevenLabs voice similarity boost is required"), + ELEVENLABS_VOICE_STYLE: z + .string() + .min(1, "ElevenLabs voice style is required"), + ELEVENLABS_VOICE_USE_SPEAKER_BOOST: z + .string() + .min(1, "ElevenLabs voice speaker boost setting is required"), + ELEVENLABS_OPTIMIZE_STREAMING_LATENCY: z + .string() + .min(1, "ElevenLabs streaming latency optimization is required"), + ELEVENLABS_OUTPUT_FORMAT: z + .string() + .min(1, "ElevenLabs output format is required"), +}); + +export type NodeConfig = z.infer; + +export async function validateNodeConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + OPENAI_API_KEY: + runtime.getSetting("OPENAI_API_KEY") || + process.env.OPENAI_API_KEY, + ELEVENLABS_MODEL_ID: + runtime.getSetting("ELEVENLABS_MODEL_ID") || + process.env.ELEVENLABS_MODEL_ID, + ELEVENLABS_VOICE_ID: + runtime.getSetting("ELEVENLABS_VOICE_ID") || + process.env.ELEVENLABS_VOICE_ID, + ELEVENLABS_VOICE_STABILITY: + runtime.getSetting("ELEVENLABS_VOICE_STABILITY") || + process.env.ELEVENLABS_VOICE_STABILITY, + ELEVENLABS_VOICE_SIMILARITY_BOOST: + runtime.getSetting("ELEVENLABS_VOICE_SIMILARITY_BOOST") || + process.env.ELEVENLABS_VOICE_SIMILARITY_BOOST, + ELEVENLABS_VOICE_STYLE: + runtime.getSetting("ELEVENLABS_VOICE_STYLE") || + process.env.ELEVENLABS_VOICE_STYLE, + ELEVENLABS_VOICE_USE_SPEAKER_BOOST: + runtime.getSetting("ELEVENLABS_VOICE_USE_SPEAKER_BOOST") || + process.env.ELEVENLABS_VOICE_USE_SPEAKER_BOOST, + ELEVENLABS_OPTIMIZE_STREAMING_LATENCY: + runtime.getSetting("ELEVENLABS_OPTIMIZE_STREAMING_LATENCY") || + process.env.ELEVENLABS_OPTIMIZE_STREAMING_LATENCY, + ELEVENLABS_OUTPUT_FORMAT: + runtime.getSetting("ELEVENLABS_OUTPUT_FORMAT") || + process.env.ELEVENLABS_OUTPUT_FORMAT, + }; + + return nodeEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `Node configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/plugin-node/src/services/speech.ts b/packages/plugin-node/src/services/speech.ts index e5a0beed4..c30928955 100644 --- a/packages/plugin-node/src/services/speech.ts +++ b/packages/plugin-node/src/services/speech.ts @@ -3,6 +3,7 @@ import { IAgentRuntime, ISpeechService, ServiceType } from "@ai16z/eliza"; import { getWavHeader } from "./audioUtils.ts"; import { synthesize } from "../vendor/vits.ts"; import { Service } from "@ai16z/eliza"; +import { validateNodeConfig } from "../enviroment.ts"; function prependWavHeader( readable: Readable, @@ -33,7 +34,7 @@ function prependWavHeader( } async function textToSpeech(runtime: IAgentRuntime, text: string) { - console.log("11 TTS: " + text); + await validateNodeConfig(runtime); const body = { model_id: runtime.getSetting("ELEVENLABS_MODEL_ID"), text: text, diff --git a/packages/plugin-solana/src/enviroment.ts b/packages/plugin-solana/src/enviroment.ts new file mode 100644 index 000000000..c7606dd2b --- /dev/null +++ b/packages/plugin-solana/src/enviroment.ts @@ -0,0 +1,51 @@ +import { IAgentRuntime } from "@ai16z/eliza"; +import { z } from "zod"; + +export const solanaEnvSchema = z.object({ + WALLET_SECRET_KEY: z.string().min(1, "Wallet secret key is required"), + WALLET_PUBLIC_KEY: z.string().min(1, "Wallet public key is required"), + SOL_ADDRESS: z.string().min(1, "SOL address is required"), + SLIPPAGE: z.string().min(1, "Slippage is required"), + RPC_URL: z.string().min(1, "RPC URL is required"), + HELIUS_API_KEY: z.string().min(1, "Helius API key is required"), + BIRDEYE_API_KEY: z.string().min(1, "Birdeye API key is required"), +}); + +export type SolanaConfig = z.infer; + +export async function validateSolanaConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + WALLET_SECRET_KEY: + runtime.getSetting("WALLET_SECRET_KEY") || + process.env.WALLET_SECRET_KEY, + WALLET_PUBLIC_KEY: + runtime.getSetting("WALLET_PUBLIC_KEY") || + process.env.WALLET_PUBLIC_KEY, + SOL_ADDRESS: + runtime.getSetting("SOL_ADDRESS") || process.env.SOL_ADDRESS, + SLIPPAGE: runtime.getSetting("SLIPPAGE") || process.env.SLIPPAGE, + RPC_URL: runtime.getSetting("RPC_URL") || process.env.RPC_URL, + HELIUS_API_KEY: + runtime.getSetting("HELIUS_API_KEY") || + process.env.HELIUS_API_KEY, + BIRDEYE_API_KEY: + runtime.getSetting("BIRDEYE_API_KEY") || + process.env.BIRDEYE_API_KEY, + }; + + return solanaEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `Solana configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/plugin-starknet/src/actions/swap.ts b/packages/plugin-starknet/src/actions/swap.ts index 46760ce02..b5e231333 100644 --- a/packages/plugin-starknet/src/actions/swap.ts +++ b/packages/plugin-starknet/src/actions/swap.ts @@ -17,6 +17,7 @@ import { } from "@avnu/avnu-sdk"; import { getStarknetAccount, validateSettings } from "../utils/index.ts"; +import { validateStarknetConfig } from "../enviroment.ts"; interface SwapContent { sellTokenAddress: string; @@ -80,7 +81,8 @@ export const executeSwap: Action = { "STARKNET_EXCHANGE_TOKENS", ], validate: async (runtime: IAgentRuntime, message: Memory) => { - return validateSettings(runtime); + await validateStarknetConfig(runtime); + return true; }, description: "Perform a token swap on starknet. Use this action when a user asks you to swap tokens anything.", diff --git a/packages/plugin-starknet/src/actions/takeOrder.ts b/packages/plugin-starknet/src/actions/takeOrder.ts index c79d00f9f..a18dab230 100644 --- a/packages/plugin-starknet/src/actions/takeOrder.ts +++ b/packages/plugin-starknet/src/actions/takeOrder.ts @@ -10,6 +10,7 @@ import * as fs from "fs"; import { settings } from "@ai16z/eliza"; import { composeContext } from "@ai16z/eliza"; import { generateText } from "@ai16z/eliza"; +import { validateStarknetConfig } from "../enviroment"; interface Order { userId: string; @@ -42,6 +43,8 @@ const take_order: Action = { description: "Records a starknet buy order based on the user's conviction level.", validate: async (runtime: IAgentRuntime, message: Memory) => { + await validateStarknetConfig(runtime); + const text = (message.content as Content).text; // Check if the message contains a ticker symbol const tickerRegex = /\b[A-Z]{1,5}\b/g; diff --git a/packages/plugin-starknet/src/actions/transfer.ts b/packages/plugin-starknet/src/actions/transfer.ts index 1f4f85e87..76baba1c3 100644 --- a/packages/plugin-starknet/src/actions/transfer.ts +++ b/packages/plugin-starknet/src/actions/transfer.ts @@ -19,6 +19,7 @@ import { validateSettings, } from "../utils"; import { ERC20Token } from "../utils/ERC20Token"; +import { validateStarknetConfig } from "../enviroment"; const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. @@ -58,7 +59,8 @@ export default { "PAY_ON_STARKNET", ], validate: async (runtime: IAgentRuntime, message: Memory) => { - return validateSettings(runtime); + await validateStarknetConfig(runtime); + return true; }, description: "MUST use this action if the user requests send a token or transfer a token, the request might be varied, but it will always be a token transfer. If the user requests a transfer of lords, use this action.", diff --git a/packages/plugin-starknet/src/actions/unruggable.ts b/packages/plugin-starknet/src/actions/unruggable.ts index 897fb1bfa..9dcde7e8e 100644 --- a/packages/plugin-starknet/src/actions/unruggable.ts +++ b/packages/plugin-starknet/src/actions/unruggable.ts @@ -27,6 +27,7 @@ import { RECOMMENDED_EKUBO_FEES, } from "@unruggable_starknet/core/constants"; import { ACCOUNTS, TOKENS } from "../utils/constants.ts"; +import { validateStarknetConfig } from "../enviroment.ts"; export function isDeployTokenContent( content: DeployData @@ -82,7 +83,8 @@ export const deployToken: Action = { "STARKNET_CREATE_MEMECOIN", ], validate: async (runtime: IAgentRuntime, message: Memory) => { - return validateSettings(runtime); + await validateStarknetConfig(runtime); + return true; }, description: "Deploy an Unruggable Memecoin on Starknet. Use this action when a user asks you to deploy a new token on Starknet.", diff --git a/packages/plugin-starknet/src/enviroment.ts b/packages/plugin-starknet/src/enviroment.ts new file mode 100644 index 000000000..89a1247de --- /dev/null +++ b/packages/plugin-starknet/src/enviroment.ts @@ -0,0 +1,40 @@ +import { IAgentRuntime } from "@ai16z/eliza"; +import { z } from "zod"; + +export const starknetEnvSchema = z.object({ + STARKNET_ADDRESS: z.string().min(1, "Starknet address is required"), + STARKNET_PRIVATE_KEY: z.string().min(1, "Starknet private key is required"), + STARKNET_RPC_URL: z.string().min(1, "Starknet RPC URL is required"), +}); + +export type StarknetConfig = z.infer; + +export async function validateStarknetConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + STARKNET_ADDRESS: + runtime.getSetting("STARKNET_ADDRESS") || + process.env.STARKNET_ADDRESS, + STARKNET_PRIVATE_KEY: + runtime.getSetting("STARKNET_PRIVATE_KEY") || + process.env.STARKNET_PRIVATE_KEY, + STARKNET_RPC_URL: + runtime.getSetting("STARKNET_RPC_URL") || + process.env.STARKNET_RPC_URL, + }; + + return starknetEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `Starknet configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47a81c81f..13f9f3c70 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -546,7 +546,7 @@ importers: version: 3.4.33(openai@4.69.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) anthropic-vertex-ai: specifier: ^1.0.0 - version: 1.0.1(encoding@0.1.13)(zod@3.23.8) + version: 1.0.2(encoding@0.1.13)(zod@3.23.8) fastembed: specifier: ^1.14.1 version: 1.14.1 @@ -5505,8 +5505,8 @@ packages: ansicolors@0.3.2: resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} - anthropic-vertex-ai@1.0.1: - resolution: {integrity: sha512-Gr/7O1YQTO3oOYtq1tScfkUZXePqZ+5qyoaBrPWgnOsS2VZBfS990mD8D7AIkt+rsx77RrheQ/TBp6c1trqRcw==} + anthropic-vertex-ai@1.0.2: + resolution: {integrity: sha512-4YuK04KMmBGkx6fi2UjnHkE4mhaIov7tnT5La9+DMn/gw/NSOLZoWNUx+13VY3mkcaseKBMEn1DBzdXXJFIP7A==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -13909,7 +13909,7 @@ snapshots: '@anthropic-ai/sdk': 0.30.1(encoding@0.1.13) '@types/uuid': 10.0.0 ai: 3.4.33(openai@4.69.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) - anthropic-vertex-ai: 1.0.1(encoding@0.1.13)(zod@3.23.8) + anthropic-vertex-ai: 1.0.2(encoding@0.1.13)(zod@3.23.8) fastembed: 1.14.1 gaxios: 6.7.1(encoding@0.1.13) glob: 11.0.0 @@ -19754,7 +19754,7 @@ snapshots: ansicolors@0.3.2: {} - anthropic-vertex-ai@1.0.1(encoding@0.1.13)(zod@3.23.8): + anthropic-vertex-ai@1.0.2(encoding@0.1.13)(zod@3.23.8): dependencies: '@ai-sdk/provider': 0.0.24 '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8)