diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..e234e9516c5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +# Ignore node_modules from the build context +node_modules + +# Ignore logs and temporary files +*.log +*.tmp +.DS_Store + +# Ignore Git files and metadata +.gitignore + +# Ignore IDE and editor config files +.vscode +.idea +*.swp + +# Ignore build artifacts from the host +dist +build \ No newline at end of file diff --git a/.env.example b/.env.example index a9364c2427c..1e77aebbc72 100644 --- a/.env.example +++ b/.env.example @@ -4,8 +4,8 @@ # Cache Configs CACHE_STORE=database # Defaults to database. Other available cache store: redis and filesystem -REDIS_URL= # Redis URL - could be a local redis instance or cloud hosted redis. Also support rediss:// URLs -PGLITE_DATA_DIR= #../pgLite/ if selecting a directory --- or memory:// if selecting in memory +REDIS_URL= # Redis URL - could be a local redis instance or cloud hosted redis. Also support rediss:// URLs +PGLITE_DATA_DIR= #../pgLite/ if selecting a directory --- or memory:// if selecting in memory # Eliza Port Config SERVER_PORT=3000 @@ -14,128 +14,202 @@ SERVER_PORT=3000 SUPABASE_URL= SUPABASE_ANON_KEY= +# MongoDB +MONGODB_CONNECTION_STRING= #mongodb connection string +MONGODB_DATABASE= #name of the database in mongoDB atlas #default: 'elizaAgent' + +# Comma separated list of remote character urls (optional) +REMOTE_CHARACTER_URLS= + +# Stores characters set by using the direct API in the data/character folder for further load when the app restarts +USE_CHARACTER_STORAGE=false + +# Logging +DEFAULT_LOG_LEVEL=warn +LOG_JSON_FORMAT=false # Print everything in logger as json; false by default + ############################### #### Client Configurations #### ############################### +# BitMind Bittensor API +BITMIND=true +BITMIND_API_TOKEN= + # Discord Configuration DISCORD_APPLICATION_ID= -DISCORD_API_TOKEN= # Bot token -DISCORD_VOICE_CHANNEL_ID= # The ID of the voice channel the bot should join (optional) +DISCORD_API_TOKEN= # Bot token +DISCORD_VOICE_CHANNEL_ID= # The ID of the voice channel the bot should join (optional) + +# Devin Configuration +DEVIN_API_TOKEN= # Get your API key from docs.devin.ai/tutorials/api-integration + +# Gelato Configuration +GELATO_RELAY_API_KEY= # Gelato API key # Farcaster Neynar Configuration -FARCASTER_FID= # The FID associated with the account your are sending casts from -FARCASTER_NEYNAR_API_KEY= # Neynar API key: https://neynar.com/ -FARCASTER_NEYNAR_SIGNER_UUID= # Signer for the account you are sending casts from. Create a signer here: https://dev.neynar.com/app -FARCASTER_DRY_RUN=false # Set to true if you want to run the bot without actually publishing casts -FARCASTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for farcaster interactions (replies and mentions) +FARCASTER_FID= # The FID associated with the account your are sending casts from +FARCASTER_NEYNAR_API_KEY= # Neynar API key: https://neynar.com/ +FARCASTER_NEYNAR_SIGNER_UUID= # Signer for the account you are sending casts from. Create a signer here: https://dev.neynar.com/app +FARCASTER_DRY_RUN=false # Set to true if you want to run the bot without actually publishing casts +FARCASTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for farcaster interactions (replies and mentions) # Telegram Configuration TELEGRAM_BOT_TOKEN= +# Telegram account client Configuration +TELEGRAM_ACCOUNT_PHONE= # Account phone number for authorization +TELEGRAM_ACCOUNT_APP_ID= # Telegram app api_id (get it at me.telegram.org) +TELEGRAM_ACCOUNT_APP_HASH= # Telegram app api_hash (get it at me.telegram.org) +TELEGRAM_ACCOUNT_DEVICE_MODEL= # Device model. Example: Samsung Galaxy S28+ +TELEGRAM_ACCOUNT_SYSTEM_VERSION= # Device system version. Example: Android 12 S? (31) + # Twitter/X Configuration TWITTER_DRY_RUN=false -TWITTER_USERNAME= # Account username -TWITTER_PASSWORD= # Account password -TWITTER_EMAIL= # Account email +TWITTER_USERNAME= # Account username +TWITTER_PASSWORD= # Account password +TWITTER_EMAIL= # Account email TWITTER_2FA_SECRET= -TWITTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for interactions -TWITTER_SEARCH_ENABLE=FALSE # Enable timeline search, WARNING this greatly increases your chance of getting banned -TWITTER_TARGET_USERS= # Comma separated list of Twitter user names to interact with -TWITTER_RETRY_LIMIT= # Maximum retry attempts for Twitter login -TWITTER_SPACES_ENABLE=false # Enable or disable Twitter Spaces logic +TWITTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for interactions +TWITTER_SEARCH_ENABLE=FALSE # Enable timeline search, WARNING this greatly increases your chance of getting banned +TWITTER_TARGET_USERS= # Comma separated list of Twitter user names to interact with +TWITTER_RETRY_LIMIT= # Maximum retry attempts for Twitter login +TWITTER_SPACES_ENABLE=false # Enable or disable Twitter Spaces logic # Post Interval Settings (in minutes) -POST_INTERVAL_MIN= # Default: 90 -POST_INTERVAL_MAX= # Default: 180 -POST_IMMEDIATELY= # Default: false +POST_INTERVAL_MIN= # Default: 90 +POST_INTERVAL_MAX= # Default: 180 +POST_IMMEDIATELY= # Default: false # Twitter action processing configuration -ACTION_INTERVAL= # Interval in minutes between action processing runs (default: 5 minutes) -ENABLE_ACTION_PROCESSING=false # Set to true to enable the action processing loop -MAX_ACTIONS_PROCESSING=1 # Maximum number of actions (e.g., retweets, likes) to process in a single cycle. Helps prevent excessive or uncontrolled actions. -ACTION_TIMELINE_TYPE=foryou # Type of timeline to interact with. Options: "foryou" or "following". Default: "foryou" +ACTION_INTERVAL= # Interval in minutes between action processing runs (default: 5 minutes) +ENABLE_ACTION_PROCESSING=false # Set to true to enable the action processing loop +MAX_ACTIONS_PROCESSING=1 # Maximum number of actions (e.g., retweets, likes) to process in a single cycle. Helps prevent excessive or uncontrolled actions. +ACTION_TIMELINE_TYPE=foryou # Type of timeline to interact with. Options: "foryou" or "following". Default: "foryou" # CONFIGURATION FOR APPROVING TWEETS BEFORE IT GETS POSTED -TWITTER_APPROVAL_DISCORD_CHANNEL_ID= # Channel ID for the Discord bot to listen and send approval messages -TWITTER_APPROVAL_DISCORD_BOT_TOKEN= # Discord bot token (this could be a different bot token from DISCORD_API_TOKEN) -TWITTER_APPROVAL_ENABLED= # Enable or disable Twitter approval logic #Default is false -TWITTER_APPROVAL_CHECK_INTERVAL=60000 # Default: 60 seconds +TWITTER_APPROVAL_DISCORD_CHANNEL_ID= # Channel ID for the Discord bot to listen and send approval messages +TWITTER_APPROVAL_DISCORD_BOT_TOKEN= # Discord bot token (this could be a different bot token from DISCORD_API_TOKEN) +TWITTER_APPROVAL_ENABLED= # Enable or disable Twitter approval logic #Default is false +TWITTER_APPROVAL_CHECK_INTERVAL=60000 # Default: 60 seconds # WhatsApp Cloud API Configuration -WHATSAPP_ACCESS_TOKEN= # Permanent access token from Facebook Developer Console -WHATSAPP_PHONE_NUMBER_ID= # Phone number ID from WhatsApp Business API -WHATSAPP_BUSINESS_ACCOUNT_ID= # Business Account ID from Facebook Business Manager -WHATSAPP_WEBHOOK_VERIFY_TOKEN= # Custom string for webhook verification -WHATSAPP_API_VERSION=v17.0 # WhatsApp API version (default: v17.0) +WHATSAPP_ACCESS_TOKEN= # Permanent access token from Facebook Developer Console +WHATSAPP_PHONE_NUMBER_ID= # Phone number ID from WhatsApp Business API +WHATSAPP_BUSINESS_ACCOUNT_ID= # Business Account ID from Facebook Business Manager +WHATSAPP_WEBHOOK_VERIFY_TOKEN= # Custom string for webhook verification +WHATSAPP_API_VERSION=v17.0 # WhatsApp API version (default: v17.0) + +# Alexa Client Configuration +ALEXA_SKILL_ID= # Your Alexa skill ID from developer console (format: amzn1.ask.skill-...) +ALEXA_CLIENT_ID= # OAuth2 Client ID from Alexa developer console permissions tab +ALEXA_CLIENT_SECRET= # OAuth2 Client Secret from Alexa developer console permissions tab +# Simsai Specific Configuration +SIMSAI_API_KEY= # API key for SimsAI authentication +SIMSAI_AGENT_ID= # Unique identifier for the SimsAI agent +SIMSAI_USERNAME= # Username for SimsAI platform access +SIMSAI_DRY_RUN= # Set to true to test without making actual API calls + # Direct Client Setting -EXPRESS_MAX_PAYLOAD= # Default: 100kb +EXPRESS_MAX_PAYLOAD= # Default: 100kb ####################################### #### Model Provider Configurations #### ####################################### # OpenAI Configuration -OPENAI_API_KEY= # OpenAI API key, starting with sk- -OPENAI_API_URL= # OpenAI API Endpoint (optional), Default: https://api.openai.com/v1 -SMALL_OPENAI_MODEL= # Default: gpt-4o-mini -MEDIUM_OPENAI_MODEL= # Default: gpt-4o -LARGE_OPENAI_MODEL= # Default: gpt-4o -EMBEDDING_OPENAI_MODEL= # Default: text-embedding-3-small -IMAGE_OPENAI_MODEL= # Default: dall-e-3 -USE_OPENAI_EMBEDDING= # Set to TRUE for OpenAI/1536, leave blank for local +OPENAI_API_KEY= # OpenAI API key, starting with sk- +OPENAI_API_URL= # OpenAI API Endpoint (optional), Default: https://api.openai.com/v1 +SMALL_OPENAI_MODEL= # Default: gpt-4o-mini +MEDIUM_OPENAI_MODEL= # Default: gpt-4o +LARGE_OPENAI_MODEL= # Default: gpt-4o +EMBEDDING_OPENAI_MODEL= # Default: text-embedding-3-small +IMAGE_OPENAI_MODEL= # Default: dall-e-3 +USE_OPENAI_EMBEDDING= # Set to TRUE for OpenAI/1536, leave blank for local + +# Community Plugin for OpenAI Configuration +ENABLE_OPEN_AI_COMMUNITY_PLUGIN=false +OPENAI_DEFAULT_MODEL= +OPENAI_MAX_TOKENS= +OPENAI_TEMPERATURE= + + + + +# Atoma SDK Configuration +ATOMASDK_BEARER_AUTH= # Atoma SDK Bearer Auth token +ATOMA_API_URL= # Default: https://api.atoma.network/v1 +SMALL_ATOMA_MODEL= # Default: meta-llama/Llama-3.3-70B-Instruct +MEDIUM_ATOMA_MODEL= # Default: meta-llama/Llama-3.3-70B-Instruct +LARGE_ATOMA_MODEL= # Default: meta-llama/Llama-3.3-70B-Instruct # Eternal AI's Decentralized Inference API ETERNALAI_URL= -ETERNALAI_MODEL= # Default: "neuralmagic/Meta-Llama-3.1-405B-Instruct-quantized.w4a16" -ETERNALAI_CHAIN_ID=45762 #Default: "45762" +ETERNALAI_MODEL= # Default: "NousResearch/Hermes-3-Llama-3.1-70B-FP8" +ETERNALAI_CHAIN_ID=8453 # Default: "8453" +ETERNALAI_RPC_URL= # Ex: https://mainnet.base.org/ +ETERNALAI_AGENT_CONTRACT_ADDRESS= # Ex: 0xAed016e060e2fFE3092916b1650Fc558D62e1CCC +ETERNALAI_AGENT_ID= # Ex: 1711 ETERNALAI_API_KEY= -ETERNALAI_LOG=false #Default: false +ETERNALAI_LOG=false #Default: false -# Hyperbolic Configuration -HYPERBOLIC_API_KEY= # Hyperbolic API Key +# Hyperbolic Provider Configuration +HYPERBOLIC_API_KEY= # Hyperbolic API Key HYPERBOLIC_MODEL= -IMAGE_HYPERBOLIC_MODEL= # Default: FLUX.1-dev -SMALL_HYPERBOLIC_MODEL= # Default: meta-llama/Llama-3.2-3B-Instruct -MEDIUM_HYPERBOLIC_MODEL= # Default: meta-llama/Meta-Llama-3.1-70B-Instruct -LARGE_HYPERBOLIC_MODEL= # Default: meta-llama/Meta-Llama-3.1-405-Instruct + +IMAGE_HYPERBOLIC_MODEL= # Default: FLUX.1-dev +SMALL_HYPERBOLIC_MODEL= # Default: meta-llama/Llama-3.2-3B-Instruct +MEDIUM_HYPERBOLIC_MODEL= # Default: meta-llama/Meta-Llama-3.1-70B-Instruct +LARGE_HYPERBOLIC_MODEL= # Default: meta-llama/Meta-Llama-3.1-405-Instruct + + +# Hyperbolic Plugin Configuration +HYPERBOLIC_ENV=production +HYPERBOLIC_API_KEY= +HYPERBOLIC_GRANULAR_LOG=true +HYPERBOLIC_SPASH=true +HYPERBOLIC_LOG_LEVEL=debug # Infera Configuration - INFERA_API_KEY= # visit api.infera.org/docs to obtain an API key under /signup_user - INFERA_MODEL= # Default: llama3.2:latest - INFERA_SERVER_URL= # Default: https://api.infera.org/ - SMALL_INFERA_MODEL= #Recommended: llama3.2:latest - MEDIUM_INFERA_MODEL= #Recommended: mistral-nemo:latest - LARGE_INFERA_MODEL= #Recommended: mistral-small:latest - - # Venice Configuration - VENICE_API_KEY= # generate from venice settings - SMALL_VENICE_MODEL= # Default: llama-3.3-70b - MEDIUM_VENICE_MODEL= # Default: llama-3.3-70b - LARGE_VENICE_MODEL= # Default: llama-3.1-405b - IMAGE_VENICE_MODEL= # Default: fluently-xl - - # Nineteen.ai Configuration - NINETEEN_AI_API_KEY= # Get a free api key from https://nineteen.ai/app/api - SMALL_NINETEEN_AI_MODEL= # Default: unsloth/Llama-3.2-3B-Instruct - MEDIUM_NINETEEN_AI_MODEL= # Default: unsloth/Meta-Llama-3.1-8B-Instruct - LARGE_NINETEEN_AI_MODEL= # Default: hugging-quants/Meta-Llama-3.1-70B-Instruct-AWQ-INT4 - IMAGE_NINETEEN_AI_MODE= # Default: dataautogpt3/ProteusV0.4-Lightning - - # Akash Chat API Configuration docs: https://chatapi.akash.network/documentation - AKASH_CHAT_API_KEY= # Get from https://chatapi.akash.network/ - SMALL_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-2-3B-Instruct - MEDIUM_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-3-70B-Instruct - LARGE_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-1-405B-Instruct-FP8 +INFERA_API_KEY= # visit api.infera.org/docs to obtain an API key under /signup_user +INFERA_MODEL= # Default: llama3.2:latest +INFERA_SERVER_URL= # Default: https://api.infera.org/ +SMALL_INFERA_MODEL= #Recommended: llama3.2:latest +MEDIUM_INFERA_MODEL= #Recommended: mistral-nemo:latest +LARGE_INFERA_MODEL= #Recommended: mistral-small:latest + +# Venice Configuration +VENICE_API_KEY= # generate from venice settings +SMALL_VENICE_MODEL= # Default: llama-3.3-70b +MEDIUM_VENICE_MODEL= # Default: llama-3.3-70b +LARGE_VENICE_MODEL= # Default: llama-3.1-405b +IMAGE_VENICE_MODEL= # Default: fluently-xl + +# Nineteen.ai Configuration +NINETEEN_AI_API_KEY= # Get a free api key from https://nineteen.ai/app/api +SMALL_NINETEEN_AI_MODEL= # Default: unsloth/Llama-3.2-3B-Instruct +MEDIUM_NINETEEN_AI_MODEL= # Default: unsloth/Meta-Llama-3.1-8B-Instruct +LARGE_NINETEEN_AI_MODEL= # Default: hugging-quants/Meta-Llama-3.1-70B-Instruct-AWQ-INT4 +IMAGE_NINETEEN_AI_MODE= # Default: dataautogpt3/ProteusV0.4-Lightning + +# Akash Chat API Configuration docs: https://chatapi.akash.network/documentation +AKASH_CHAT_API_KEY= # Get from https://chatapi.akash.network/ +SMALL_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-2-3B-Instruct +MEDIUM_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-3-70B-Instruct +LARGE_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-1-405B-Instruct-FP8 # Livepeer configuration -LIVEPEER_GATEWAY_URL= # Free inference gateways and docs: https://livepeer-eliza.com/ -LIVEPEER_IMAGE_MODEL= # Default: ByteDance/SDXL-Lightning + +LIVEPEER_GATEWAY_URL=https://dream-gateway.livepeer.cloud # Free inference gateways and docs: https://livepeer-eliza.com/ +IMAGE_LIVEPEER_MODEL= # Default: ByteDance/SDXL-Lightning +SMALL_LIVEPEER_MODEL= # Default: meta-llama/Meta-Llama-3.1-8B-Instruct +MEDIUM_LIVEPEER_MODEL= # Default: meta-llama/Meta-Llama-3.1-8B-Instruct +LARGE_LIVEPEER_MODEL= # Default: meta-llama/Meta-Llama-3.1-8B-Instruct # Speech Synthesis -ELEVENLABS_XI_API_KEY= # API key from elevenlabs +ELEVENLABS_XI_API_KEY= # API key from elevenlabs # Transcription Provider -TRANSCRIPTION_PROVIDER= # Default: local (possible values: openai, deepgram, local) +TRANSCRIPTION_PROVIDER= # Default: local (possible values: openai, deepgram, local) # ElevenLabs Settings ELEVENLABS_MODEL_ID=eleven_multilingual_v2 @@ -148,123 +222,132 @@ ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=4 ELEVENLABS_OUTPUT_FORMAT=pcm_16000 # OpenRouter Configuration -OPENROUTER_API_KEY= # OpenRouter API Key -OPENROUTER_MODEL= # Default: uses hermes 70b/405b +OPENROUTER_API_KEY= # OpenRouter API Key +OPENROUTER_MODEL= # Default: uses hermes 70b/405b SMALL_OPENROUTER_MODEL= MEDIUM_OPENROUTER_MODEL= LARGE_OPENROUTER_MODEL= # REDPILL Configuration (https://docs.red-pill.ai/get-started/supported-models) -REDPILL_API_KEY= # REDPILL API Key +REDPILL_API_KEY= # REDPILL API Key REDPILL_MODEL= -SMALL_REDPILL_MODEL= # Default: gpt-4o-mini -MEDIUM_REDPILL_MODEL= # Default: gpt-4o -LARGE_REDPILL_MODEL= # Default: gpt-4o +SMALL_REDPILL_MODEL= # Default: gpt-4o-mini +MEDIUM_REDPILL_MODEL= # Default: gpt-4o +LARGE_REDPILL_MODEL= # Default: gpt-4o # Grok Configuration -GROK_API_KEY= # GROK/xAI API Key -SMALL_GROK_MODEL= # Default: grok-2-1212 -MEDIUM_GROK_MODEL= # Default: grok-2-1212 -LARGE_GROK_MODEL= # Default: grok-2-1212 -EMBEDDING_GROK_MODEL= # Default: grok-2-1212 +GROK_API_KEY= # GROK/xAI API Key +SMALL_GROK_MODEL= # Default: grok-2-1212 +MEDIUM_GROK_MODEL= # Default: grok-2-1212 +LARGE_GROK_MODEL= # Default: grok-2-1212 +EMBEDDING_GROK_MODEL= # Default: grok-2-1212 # Ollama Configuration -OLLAMA_SERVER_URL= # Default: localhost:11434 +OLLAMA_SERVER_URL= # Default: localhost:11434 OLLAMA_MODEL= -USE_OLLAMA_EMBEDDING= # Set to TRUE for OLLAMA/1024, leave blank for local -OLLAMA_EMBEDDING_MODEL= # Default: mxbai-embed-large -SMALL_OLLAMA_MODEL= # Default: llama3.2 -MEDIUM_OLLAMA_MODEL= # Default: hermes3 -LARGE_OLLAMA_MODEL= # Default: hermes3:70b +USE_OLLAMA_EMBEDDING= # Set to TRUE for OLLAMA/1024, leave blank for local +OLLAMA_EMBEDDING_MODEL= # Default: mxbai-embed-large +SMALL_OLLAMA_MODEL= # Default: llama3.2 +MEDIUM_OLLAMA_MODEL= # Default: hermes3 +LARGE_OLLAMA_MODEL= # Default: hermes3:70b # Google Configuration GOOGLE_MODEL= -SMALL_GOOGLE_MODEL= # Default: gemini-1.5-flash-latest -MEDIUM_GOOGLE_MODEL= # Default: gemini-1.5-flash-latest -LARGE_GOOGLE_MODEL= # Default: gemini-1.5-pro-latest -EMBEDDING_GOOGLE_MODEL= # Default: text-embedding-004 +SMALL_GOOGLE_MODEL= # Default: gemini-1.5-flash-latest +MEDIUM_GOOGLE_MODEL= # Default: gemini-1.5-flash-latest +LARGE_GOOGLE_MODEL= # Default: gemini-1.5-pro-latest +EMBEDDING_GOOGLE_MODEL= # Default: text-embedding-004 # Mistral Configuration MISTRAL_MODEL= -SMALL_MISTRAL_MODEL= # Default: mistral-small-latest -MEDIUM_MISTRAL_MODEL= # Default: mistral-large-latest -LARGE_MISTRAL_MODEL= # Default: mistral-large-latest +SMALL_MISTRAL_MODEL= # Default: mistral-small-latest +MEDIUM_MISTRAL_MODEL= # Default: mistral-large-latest +LARGE_MISTRAL_MODEL= # Default: mistral-large-latest # Groq Configuration -GROQ_API_KEY= # Starts with gsk_ -SMALL_GROQ_MODEL= # Default: llama-3.1-8b-instant -MEDIUM_GROQ_MODEL= # Default: llama-3.3-70b-versatile -LARGE_GROQ_MODEL= # Default: llama-3.2-90b-vision-preview -EMBEDDING_GROQ_MODEL= # Default: llama-3.1-8b-instant +GROQ_API_KEY= # Starts with gsk_ +SMALL_GROQ_MODEL= # Default: llama-3.1-8b-instant +MEDIUM_GROQ_MODEL= # Default: llama-3.3-70b-versatile +LARGE_GROQ_MODEL= # Default: llama-3.2-90b-vision-preview +EMBEDDING_GROQ_MODEL= # Default: llama-3.1-8b-instant # LlamaLocal Configuration -LLAMALOCAL_PATH= # Default: "" which is the current directory in plugin-node/dist/ which gets destroyed and recreated on every build +LLAMALOCAL_PATH= # Default: "" which is the current directory in plugin-node/dist/ which gets destroyed and recreated on every build # NanoGPT Configuration -SMALL_NANOGPT_MODEL= # Default: gpt-4o-mini -MEDIUM_NANOGPT_MODEL= # Default: gpt-4o -LARGE_NANOGPT_MODEL= # Default: gpt-4o +SMALL_NANOGPT_MODEL= # Default: gpt-4o-mini +MEDIUM_NANOGPT_MODEL= # Default: gpt-4o +LARGE_NANOGPT_MODEL= # Default: gpt-4o # Anthropic Configuration -ANTHROPIC_API_KEY= # For Claude -SMALL_ANTHROPIC_MODEL= # Default: claude-3-haiku-20240307 -MEDIUM_ANTHROPIC_MODEL= # Default: claude-3-5-sonnet-20241022 -LARGE_ANTHROPIC_MODEL= # Default: claude-3-5-sonnet-20241022 +ANTHROPIC_API_KEY= # For Claude +SMALL_ANTHROPIC_MODEL= # Default: claude-3-haiku-20240307 +MEDIUM_ANTHROPIC_MODEL= # Default: claude-3-5-sonnet-20241022 +LARGE_ANTHROPIC_MODEL= # Default: claude-3-5-sonnet-20241022 # Heurist Configuration -HEURIST_API_KEY= # Get from https://heurist.ai/dev-access -SMALL_HEURIST_MODEL= # Default: meta-llama/llama-3-70b-instruct -MEDIUM_HEURIST_MODEL= # Default: meta-llama/llama-3-70b-instruct -LARGE_HEURIST_MODEL= # Default: meta-llama/llama-3.1-405b-instruct -HEURIST_IMAGE_MODEL= # Default: PepeXL +HEURIST_API_KEY= # Get from https://heurist.ai/dev-access +SMALL_HEURIST_MODEL= # Default: meta-llama/llama-3-70b-instruct +MEDIUM_HEURIST_MODEL= # Default: meta-llama/llama-3-70b-instruct +LARGE_HEURIST_MODEL= # Default: meta-llama/llama-3.3-70b-instruct +HEURIST_IMAGE_MODEL= # Default: FLUX.1-dev +HEURIST_EMBEDDING_MODEL= # Default: BAAI/bge-large-en-v1.5 +USE_HEURIST_EMBEDDING= # Set to TRUE for HEURIST embedding, leave blank for local # Gaianet Configuration GAIANET_MODEL= GAIANET_SERVER_URL= -SMALL_GAIANET_MODEL= # Default: llama3b -SMALL_GAIANET_SERVER_URL= # Default: https://llama3b.gaia.domains/v1 -MEDIUM_GAIANET_MODEL= # Default: llama -MEDIUM_GAIANET_SERVER_URL= # Default: https://llama8b.gaia.domains/v1 -LARGE_GAIANET_MODEL= # Default: qwen72b -LARGE_GAIANET_SERVER_URL= # Default: https://qwen72b.gaia.domains/v1 +SMALL_GAIANET_MODEL= # Default: llama3b +SMALL_GAIANET_SERVER_URL= # Default: https://llama3b.gaia.domains/v1 +MEDIUM_GAIANET_MODEL= # Default: llama +MEDIUM_GAIANET_SERVER_URL= # Default: https://llama8b.gaia.domains/v1 +LARGE_GAIANET_MODEL= # Default: qwen72b +LARGE_GAIANET_SERVER_URL= # Default: https://qwen72b.gaia.domains/v1 GAIANET_EMBEDDING_MODEL= -USE_GAIANET_EMBEDDING= # Set to TRUE for GAIANET/768, leave blank for local +USE_GAIANET_EMBEDDING= # Set to TRUE for GAIANET/768, leave blank for local # Volcengine Configuration -VOLENGINE_API_URL= # Volcengine API Endpoint, Default: https://open.volcengineapi.com/api/v3/ +VOLENGINE_API_URL= # Volcengine API Endpoint, Default: https://open.volcengineapi.com/api/v3/ VOLENGINE_MODEL= -SMALL_VOLENGINE_MODEL= # Default: doubao-lite-128k -MEDIUM_VOLENGINE_MODEL= # Default: doubao-pro-128k -LARGE_VOLENGINE_MODEL= # Default: doubao-pro-256k -VOLENGINE_EMBEDDING_MODEL= # Default: doubao-embedding +SMALL_VOLENGINE_MODEL= # Default: doubao-lite-128k +MEDIUM_VOLENGINE_MODEL= # Default: doubao-pro-128k +LARGE_VOLENGINE_MODEL= # Default: doubao-pro-256k +VOLENGINE_EMBEDDING_MODEL= # Default: doubao-embedding # DeepSeek Configuration -DEEPSEEK_API_URL= # Default: https://api.deepseek.com -SMALL_DEEPSEEK_MODEL= # Default: deepseek-chat -MEDIUM_DEEPSEEK_MODEL= # Default: deepseek-chat -LARGE_DEEPSEEK_MODEL= # Default: deepseek-chat - +DEEPSEEK_API_KEY= #Your DeepSeek API key +DEEPSEEK_API_URL= # Default: https://api.deepseek.com +SMALL_DEEPSEEK_MODEL= # Default: deepseek-chat +MEDIUM_DEEPSEEK_MODEL= # Default: deepseek-chat +LARGE_DEEPSEEK_MODEL= # Default: deepseek-chat # fal.ai Configuration FAL_API_KEY= FAL_AI_LORA_PATH= # LetzAI Configuration -LETZAI_API_KEY= # LetzAI API Key -LETZAI_MODELS= # list of Letzai models to add to each prompt, e.g.: "@modelname1, @modelname2" +LETZAI_API_KEY= # LetzAI API Key +LETZAI_MODELS= # list of Letzai models to add to each prompt, e.g.: "@modelname1, @modelname2" # Galadriel Configuration -GALADRIEL_API_KEY=gal-* # Get from https://dashboard.galadriel.com/ -SMALL_GALADRIEL_MODEL= # Default: gpt-4o-mini -MEDIUM_GALADRIEL_MODEL= # Default: gpt-4o -LARGE_GALADRIEL_MODEL= # Default: gpt-4o -GALADRIEL_FINE_TUNE_API_KEY= # Use an OpenAI key to use a fine-tuned model with the verified inference endpoint +GALADRIEL_API_KEY=gal-* # Get from https://dashboard.galadriel.com/ +SMALL_GALADRIEL_MODEL= # Default: gpt-4o-mini +MEDIUM_GALADRIEL_MODEL= # Default: gpt-4o +LARGE_GALADRIEL_MODEL= # Default: gpt-4o +GALADRIEL_FINE_TUNE_API_KEY= # Use an OpenAI key to use a fine-tuned model with the verified inference endpoint + +# LM Studio Configuration +LMSTUDIO_SERVER_URL= # Default: http://localhost:1234/v1 +LMSTUDIO_MODEL= +SMALL_LMSTUDIO_MODEL= # Default: hermes-3-llama-3.1-8b +MEDIUM_LMSTUDIO_MODEL= # Default: hermes-3-llama-3.1-8b +LARGE_LMSTUDIO_MODEL= # Default: hermes-3-llama-3.1-8b # Remaining Provider Configurations -GOOGLE_GENERATIVE_AI_API_KEY= # Gemini API key -ALI_BAILIAN_API_KEY= # Ali Bailian API Key -NANOGPT_API_KEY= # NanoGPT API Key -TOGETHER_API_KEY= # Together API Key +GOOGLE_GENERATIVE_AI_API_KEY= # Gemini API key +ALI_BAILIAN_API_KEY= # Ali Bailian API Key +NANOGPT_API_KEY= # NanoGPT API Key +TOGETHER_API_KEY= # Together API Key ###################################### #### Crypto Plugin Configurations #### @@ -273,14 +356,24 @@ TOGETHER_API_KEY= # Together API Key # CoinMarketCap / CMC COINMARKETCAP_API_KEY= +# Zerion +ZERION_API_KEY= + # CoinGecko COINGECKO_API_KEY= COINGECKO_PRO_API_KEY= +# Moralis +MORALIS_API_KEY= + # EVM EVM_PRIVATE_KEY= EVM_PROVIDER_URL= +# Zilliqa +ZILLIQA_PRIVATE_KEY= +ZILLIQA_PROVIDER_URL= + # Avalanche AVALANCHE_PRIVATE_KEY= AVALANCHE_PUBLIC_KEY= @@ -291,11 +384,15 @@ ARTHERA_PRIVATE_KEY= # Solana SOLANA_PRIVATE_KEY= SOLANA_PUBLIC_KEY= -SOLANA_CLUSTER= # Default: devnet. Solana Cluster: 'devnet' | 'testnet' | 'mainnet-beta' +SOLANA_CLUSTER= # Default: devnet. Solana Cluster: 'devnet' | 'testnet' | 'mainnet-beta' SOLANA_ADMIN_PRIVATE_KEY= # This wallet is used to verify NFTs -SOLANA_ADMIN_PUBLIC_KEY= # This wallet is used to verify NFTs -SOLANA_VERIFY_TOKEN= # Authentication token for calling the verification API +SOLANA_ADMIN_PUBLIC_KEY= # This wallet is used to verify NFTs +SOLANA_VERIFY_TOKEN= # Authentication token for calling the verification API +# Injective +INJECTIVE_PRIVATE_KEY= # +INJECTIVE_PUBLIC_KEY= # +INJECTIVE_NETWORK= # # Fallback Wallet Configuration (deprecated) WALLET_PRIVATE_KEY= WALLET_PUBLIC_KEY= @@ -323,16 +420,25 @@ STARKNET_RPC_URL= LENS_ADDRESS= LENS_PRIVATE_KEY= +# Form Chain +FORM_PRIVATE_KEY= # Form character account private key +FORM_TESTNET=true # A flag indicating if connection is made to Form Testnet. Set to false for Mainnet connection. + # Coinbase -COINBASE_COMMERCE_KEY= # From Coinbase developer portal -COINBASE_API_KEY= # From Coinbase developer portal -COINBASE_PRIVATE_KEY= # From Coinbase developer portal -COINBASE_GENERATED_WALLET_ID= # Not your address but the wallet ID from generating a wallet through the plugin +COINBASE_COMMERCE_KEY= # From Coinbase developer portal +COINBASE_API_KEY= # From Coinbase developer portal +COINBASE_PRIVATE_KEY= # From Coinbase developer portal +COINBASE_GENERATED_WALLET_ID= # Not your address but the wallet ID from generating a wallet through the plugin COINBASE_GENERATED_WALLET_HEX_SEED= # Not your address but the wallet hex seed from generating a wallet through the plugin and calling export -COINBASE_NOTIFICATION_URI= # For webhook plugin the uri you want to send the webhook to for dummy ones use https://webhook.site +COINBASE_NOTIFICATION_URI= # For webhook plugin the uri you want to send the webhook to for dummy ones use https://webhook.site + +# Coinbase AgentKit +CDP_API_KEY_NAME= +CDP_API_KEY_PRIVATE_KEY= +CDP_AGENT_KIT_NETWORK=base-sepolia # Optional: Defaults to base-sepolia # Coinbase Charity Configuration -IS_CHARITABLE=false # Set to true to enable charity donations +IS_CHARITABLE=false # Set to true to enable charity donations CHARITY_ADDRESS_BASE=0x1234567890123456789012345678901234567890 CHARITY_ADDRESS_SOL=pWvDXKu6CpbKKvKQkZvDA66hgsTB6X2AgFxksYogHLV CHARITY_ADDRESS_ETH=0x750EF1D7a0b4Ab1c97B7A623D7917CcEb5ea779C @@ -340,7 +446,7 @@ CHARITY_ADDRESS_ARB=0x1234567890123456789012345678901234567890 CHARITY_ADDRESS_POL=0x1234567890123456789012345678901234567890 # thirdweb -THIRDWEB_SECRET_KEY= # Create key on thirdweb developer dashboard: https://thirdweb.com/ +THIRDWEB_SECRET_KEY= # Create key on thirdweb developer dashboard: https://thirdweb.com/ # Conflux Configuration CONFLUX_CORE_PRIVATE_KEY= @@ -349,50 +455,95 @@ CONFLUX_ESPACE_PRIVATE_KEY= CONFLUX_ESPACE_RPC_URL= CONFLUX_MEME_CONTRACT_ADDRESS= +# Mind Network Configuration +MIND_HOT_WALLET_PRIVATE_KEY= +MIND_COLD_WALLET_ADDRESS= + # ZeroG ZEROG_INDEXER_RPC= ZEROG_EVM_RPC= ZEROG_PRIVATE_KEY= ZEROG_FLOW_ADDRESS= +# IQ6900 +# Load json recorded on-chain through IQ +# Inscribe your json character file here: https://elizacodein.com/ + +IQ_WALLET_ADDRESS= # If you enter the wallet address used on the site, the most recently inscribed json will be loaded. +IQSOlRPC= + +# Squid Router +SQUID_SDK_URL=https://apiplus.squidrouter.com # Default: https://apiplus.squidrouter.com +SQUID_INTEGRATOR_ID= # get integrator id through https://docs.squidrouter.com/ +SQUID_EVM_ADDRESS= +SQUID_EVM_PRIVATE_KEY= +SQUID_API_THROTTLE_INTERVAL=1000 # Default: 1000; Used to throttle API calls to avoid rate limiting (in ms) + # TEE Configuration # TEE_MODE options: # - LOCAL: Uses simulator at localhost:8090 (for local development) # - DOCKER: Uses simulator at host.docker.internal:8090 (for docker development) # - PRODUCTION: No simulator, uses production endpoints # Defaults to OFF if not specified -TEE_MODE=OFF # LOCAL | DOCKER | PRODUCTION -WALLET_SECRET_SALT= # ONLY define if you want to use TEE Plugin, otherwise it will throw errors +TEE_MODE=OFF # LOCAL | DOCKER | PRODUCTION +WALLET_SECRET_SALT= # ONLY define if you want to use TEE Plugin, otherwise it will throw errors +TEE_LOG_DB_PATH= # Custom path for TEE Log database, default: ./data/tee_log.sqlite + +# TEE Verifiable Log Configuration +VLOG= # true/false; if you want to use TEE Verifiable Log, set this to "true" + +# Galadriel Configuration +GALADRIEL_API_KEY=gal-* # Get from https://dashboard.galadriel.com/ -ENABLE_TEE_LOG=false # Set to true to enable TEE logging, only available when running eliza in TEE + +# Akash Chat API Configuration docs: https://chatapi.akash.network/documentation +AKASH_CHAT_API_KEY= # Get from https://chatapi.akash.network/ +SMALL_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-2-3B-Instruct +MEDIUM_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-3-70B-Instruct +LARGE_AKASH_CHAT_API_MODEL= # Default: Meta-Llama-3-1-405B-Instruct-FP8 + +# fal.ai Configuration +FAL_API_KEY= +FAL_AI_LORA_PATH= + +# Web search API Configuration +TAVILY_API_KEY= + +# WhatsApp Cloud API Configuration +WHATSAPP_ACCESS_TOKEN= # Permanent access token from Facebook Developer Console +WHATSAPP_PHONE_NUMBER_ID= # Phone number ID from WhatsApp Business API +WHATSAPP_BUSINESS_ACCOUNT_ID= # Business Account ID from Facebook Business Manager +WHATSAPP_WEBHOOK_VERIFY_TOKEN= # Custom string for webhook verification +WHATSAPP_API_VERSION=v17.0 # WhatsApp API version (default: v17.0) +ENABLE_TEE_LOG=false # Set to true to enable TEE logging, only available when running eliza in TEE # Flow Blockchain Configuration FLOW_ADDRESS= -FLOW_PRIVATE_KEY= # Private key for SHA3-256 + P256 ECDSA -FLOW_NETWORK= # Default: mainnet -FLOW_ENDPOINT_URL= # Default: https://mainnet.onflow.org +FLOW_PRIVATE_KEY= # Private key for SHA3-256 + P256 ECDSA +FLOW_NETWORK= # Default: mainnet +FLOW_ENDPOINT_URL= # Default: https://mainnet.onflow.org # ICP INTERNET_COMPUTER_PRIVATE_KEY= INTERNET_COMPUTER_ADDRESS= - #Cloudflare AI Gateway -CLOUDFLARE_GW_ENABLED= # Set to true to enable Cloudflare AI Gateway -CLOUDFLARE_AI_ACCOUNT_ID= # Cloudflare AI Account ID - found in the Cloudflare Dashboard under AI Gateway -CLOUDFLARE_AI_GATEWAY_ID= # Cloudflare AI Gateway ID - found in the Cloudflare Dashboard under AI Gateway +CLOUDFLARE_GW_ENABLED= # Set to true to enable Cloudflare AI Gateway +CLOUDFLARE_AI_ACCOUNT_ID= # Cloudflare AI Account ID - found in the Cloudflare Dashboard under AI Gateway +CLOUDFLARE_AI_GATEWAY_ID= # Cloudflare AI Gateway ID - found in the Cloudflare Dashboard under AI Gateway # Aptos -APTOS_PRIVATE_KEY= # Aptos private key -APTOS_NETWORK= # Must be one of mainnet, testnet +APTOS_PRIVATE_KEY= # Aptos private key +APTOS_NETWORK= # Must be one of mainnet, testnet # MultiversX -MVX_PRIVATE_KEY= # Multiversx private key -MVX_NETWORK= # must be one of mainnet, devnet, testnet +MVX_PRIVATE_KEY= # Multiversx private key +MVX_NETWORK= # must be one of mainnet, devnet, testnet +ACCESS_TOKEN_MANAGEMENT_TO=everyone # you can put an userid to limit token managament to one user only (use same id as in the database) # NEAR -NEAR_WALLET_SECRET_KEY= # NEAR Wallet Secret Key -NEAR_WALLET_PUBLIC_KEY= # NEAR Wallet Public Key +NEAR_WALLET_SECRET_KEY= # NEAR Wallet Secret Key +NEAR_WALLET_PUBLIC_KEY= # NEAR Wallet Public Key NEAR_ADDRESS= NEAR_SLIPPAGE=1 NEAR_RPC_URL=https://rpc.testnet.near.org @@ -402,43 +553,52 @@ NEAR_NETWORK=testnet # or mainnet ZKSYNC_ADDRESS= ZKSYNC_PRIVATE_KEY= +# HoldStation Wallet Configuration +HOLDSTATION_PRIVATE_KEY= + # Avail DA Configuration AVAIL_ADDRESS= AVAIL_SEED= AVAIL_APP_ID=0 -AVAIL_RPC_URL=wss://avail-turing.public.blastapi.io/ # (Default) Testnet: wss://avail-turing.public.blastapi.io/ | Mainnet: wss://avail-mainnet.public.blastapi.io/ +AVAIL_RPC_URL=wss://avail-turing.public.blastapi.io/ # (Default) Testnet: wss://avail-turing.public.blastapi.io/ | Mainnet: wss://avail-mainnet.public.blastapi.io/ # Marlin -TEE_MARLIN= # Set "yes" to enable the plugin -TEE_MARLIN_ATTESTATION_ENDPOINT= # Optional, default "http://127.0.0.1:1350" +TEE_MARLIN= # Set "yes" to enable the plugin +TEE_MARLIN_ATTESTATION_ENDPOINT= # Optional, default "http://127.0.0.1:1350" # Ton -TON_PRIVATE_KEY= # Ton Mnemonic Seed Phrase Join With Empty String -TON_RPC_URL= # ton rpc +TON_PRIVATE_KEY= # Ton Mnemonic Seed Phrase Join With Empty String +TON_RPC_URL= # ton rpc +TON_RPC_API_KEY= # ton rpc api key # Sui -SUI_PRIVATE_KEY= # Sui Mnemonic Seed Phrase (`sui keytool generate ed25519`) , Also support `suiprivatekeyxxxx` (sui keytool export --key-identity 0x63) -SUI_NETWORK= # must be one of mainnet, testnet, devnet, localnet +SUI_PRIVATE_KEY= # Sui Mnemonic Seed Phrase (`sui keytool generate ed25519`) , Also support `suiprivatekeyxxxx` (sui keytool export --key-identity 0x63) +SUI_NETWORK= # must be one of mainnet, testnet, devnet, localnet + +# Mina Settings +MINA_PRIVATE_KEY= # Mina Mnemonic Seed Phrase: https://docs.minaprotocol.com/using-mina/install-a-wallet +MINA_NETWORK=devnet # must be one of mainnet, testnet, devnet, localnet # Story -STORY_PRIVATE_KEY= # Story private key -STORY_API_BASE_URL= # Story API base URL -STORY_API_KEY= # Story API key -PINATA_JWT= # Pinata JWT for uploading files to IPFS +STORY_PRIVATE_KEY= # Story private key +STORY_API_BASE_URL= # Story API base URL +STORY_API_KEY= # Story API key +PINATA_JWT= # Pinata JWT for uploading files to IPFS # Cosmos -COSMOS_RECOVERY_PHRASE= # 12 words recovery phrase (need to be in quotes, because of spaces) -COSMOS_AVAILABLE_CHAINS= # mantrachaintestnet2,cosmos # Array of chains +COSMOS_RECOVERY_PHRASE= # 12 words recovery phrase (need to be in quotes, because of spaces) +COSMOS_AVAILABLE_CHAINS= # mantrachaintestnet2,cosmos # Array of chains # Cronos zkEVM CRONOSZKEVM_ADDRESS= CRONOSZKEVM_PRIVATE_KEY= + # Fuel Ecosystem (FuelVM) FUEL_WALLET_PRIVATE_KEY= # Tokenizer Settings -TOKENIZER_MODEL= # Specify the tokenizer model to be used. -TOKENIZER_TYPE= # Options: tiktoken (for OpenAI models) or auto (AutoTokenizer from Hugging Face for non-OpenAI models). Default: tiktoken. +TOKENIZER_MODEL= # Specify the tokenizer model to be used. +TOKENIZER_TYPE= # Options: tiktoken (for OpenAI models) or auto (AutoTokenizer from Hugging Face for non-OpenAI models). Default: tiktoken. # Spheron SPHERON_PRIVATE_KEY= @@ -451,6 +611,12 @@ STARGAZE_ENDPOINT= # GenLayer GENLAYER_PRIVATE_KEY= # Private key of the GenLayer account to use for the agent in this format (0x0000000000000000000000000000000000000000000000000000000000000000) +# BNB chain +BNB_PRIVATE_KEY= # BNB chain private key +BNB_PUBLIC_KEY= # BNB-smart-chain public key (address) +BSC_PROVIDER_URL= # BNB-smart-chain rpc url +OPBNB_PROVIDER_URL= # OPBNB rpc url + #################################### #### Misc Plugin Configurations #### #################################### @@ -462,44 +628,69 @@ INTIFACE_WEBSOCKET_URL=ws://localhost:12345 GIPHY_API_KEY= # OpenWeather -OPEN_WEATHER_API_KEY= # OpenWeather API key - +OPEN_WEATHER_API_KEY= # OpenWeather API key +#GITCOIN Passport +PASSPORT_API_KEY= #Gitcoin Passport key +PASSPORT_SCORER= #Scorer number # EchoChambers Configuration ECHOCHAMBERS_API_URL=http://127.0.0.1:3333 ECHOCHAMBERS_API_KEY=testingkey0011 ECHOCHAMBERS_USERNAME=eliza -ECHOCHAMBERS_DEFAULT_ROOM=general +ECHOCHAMBERS_ROOMS=general #comma delimited list of rooms the agent watches ECHOCHAMBERS_POLL_INTERVAL=60 ECHOCHAMBERS_MAX_MESSAGES=10 +# How often the agent checks if it should start a conversation +ECHOCHAMBERS_CONVERSATION_STARTER_INTERVAL=300 # 5 minutes - checks rooms every 5 minutes + +# How long a room must be quiet before starting a new conversation +ECHOCHAMBERS_QUIET_PERIOD=900 # 15 minutes - waits for 15 minutes of silence # Allora -ALLORA_API_KEY= # Allora API key, format: UP-f8db7d6558ab432ca0d92716 -ALLORA_CHAIN_SLUG= # must be one of mainnet, testnet. If not specified, it will use testnet by default +ALLORA_API_KEY= # Allora API key, format: UP-f8db7d6558ab432ca0d92716 +ALLORA_CHAIN_SLUG= # must be one of mainnet, testnet. If not specified, it will use testnet by default + + +# B2 Network +B2_PRIVATE_KEY= # Private key of the B2 Network account to use for the agent # Opacity zkTLS OPACITY_TEAM_ID=f309ac8ae8a9a14a7e62cd1a521b1c5f OPACITY_CLOUDFLARE_NAME=eigen-test OPACITY_PROVER_URL=https://opacity-ai-zktls-demo.vercel.app -# AWS S3 Configuration Settings for File Upload +# AWS Credentials for S3 File Upload and Amazon Bedrock AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_REGION= AWS_S3_BUCKET= AWS_S3_UPLOAD_PATH= +AWS_S3_ENDPOINT= +AWS_S3_SSL_ENABLED= +AWS_S3_FORCE_PATH_STYLE= + + +# Deva Configuration +DEVA_API_KEY= # You can get the API key from the created application in deva.me/settings/apps +DEVA_API_BASE_URL=https://api.deva.me # Default server url for production. Use https://api-staging.deva.me for staging. # Deepgram DEEPGRAM_API_KEY= -# Web search API Configuration -TAVILY_API_KEY= - # Verifiable Inference Configuration -VERIFIABLE_INFERENCE_ENABLED=false # Set to false to disable verifiable inference +VERIFIABLE_INFERENCE_ENABLED=false # Set to false to disable verifiable inference VERIFIABLE_INFERENCE_PROVIDER=opacity # Options: opacity +# Qdrant +# URL of your Qdrant instance (e.g., https://your-instance.qdrant.tech) +QDRANT_URL= +# API key for authentication (optional for local instances) +QDRANT_KEY= +# Qdrant service port (default: 443 for cloud, typically 6333 for local) +QDRANT_PORT=443 +# Vector size matching your embedding model (default: 1536 for OpenAI embeddings) +QDRANT_VECTOR_SIZE=1536 # Autonome Configuration AUTONOME_JWT_TOKEN= @@ -549,7 +740,216 @@ AKASH_MANIFEST_MODE=auto AKASH_MANIFEST_PATH= # Values: "strict" | "lenient" | "none" - Default: "strict" AKASH_MANIFEST_VALIDATION_LEVEL=strict - # Quai Network Ecosystem QUAI_PRIVATE_KEY= QUAI_RPC_URL=https://rpc.quai.network + +# Chainbase +CHAINBASE_API_KEY=demo # demo is a free tier key + +# 0x +ZERO_EX_API_KEY= +ALCHEMY_HTTP_TRANSPORT_URL= + +# Instagram Configuration +INSTAGRAM_DRY_RUN=false +INSTAGRAM_USERNAME= # Account username +INSTAGRAM_PASSWORD= # Account password +INSTAGRAM_APP_ID= # Instagram App ID is required +INSTAGRAM_APP_SECRET= # Instagram App Secret is required +INSTAGRAM_BUSINESS_ACCOUNT_ID= # Optional Business Account ID for additional features +INSTAGRAM_POST_INTERVAL_MIN=60 # Default: 60 minutes +INSTAGRAM_POST_INTERVAL_MAX=120 # Default: 120 minutes +INSTAGRAM_ENABLE_ACTION_PROCESSING=false # Enable/disable action processing +INSTAGRAM_ACTION_INTERVAL=5 # Interval between actions in minutes +INSTAGRAM_MAX_ACTIONS=1 # Maximum number of actions to process at once + +#################################### +#### Pyth Plugin Configuration #### +#################################### +# Network Environment (mainnet or testnet)git +PYTH_NETWORK_ENV=mainnet + +# Mainnet Network Configuration +PYTH_MAINNET_HERMES_URL=https://hermes.pyth.network +PYTH_MAINNET_WSS_URL=wss://hermes.pyth.network/ws +PYTH_MAINNET_PYTHNET_URL=https://pythnet.rpcpool.com +PYTH_MAINNET_CONTRACT_REGISTRY=https://pyth.network/developers/price-feed-ids +PYTH_MAINNET_PROGRAM_KEY= + +# Testnet Network Configuration +PYTH_TESTNET_HERMES_URL=https://hermes.pyth.network +PYTH_TESTNET_WSS_URL=wss://hermes.pyth.network/ws +PYTH_TESTNET_PYTHNET_URL=https://pythnet.rpcpool.com +PYTH_TESTNET_CONTRACT_REGISTRY=https://pyth.network/developers/price-feed-ids#testnet +PYTH_TESTNET_PROGRAM_KEY= + +# Connection Settings +PYTH_MAX_RETRIES=3 +PYTH_RETRY_DELAY=1000 +PYTH_TIMEOUT=5000 +PYTH_GRANULAR_LOG=true +PYTH_LOG_LEVEL=debug +PYTH_LOG_LEVEL=info + +# Runtime Settings +RUNTIME_CHECK_MODE=false + +# Pyth Price Streaming and test ID +PYTH_ENABLE_PRICE_STREAMING=true +PYTH_MAX_PRICE_STREAMS=2 +PYTH_TEST_ID01=0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43 +PYTH_TEST_ID02=0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace + +# Router Nitro EVM Configuration +ROUTER_NITRO_EVM_ADDRESS= +ROUTER_NITRO_EVM_PRIVATE_KEY= + +# OriginTrail DKG +DKG_ENVIRONMENT="" +# Values: "development", "testnet", "mainnet" +DKG_HOSTNAME="" +DKG_PORT="8900" +DKG_PUBLIC_KEY="" +DKG_PRIVATE_KEY="" +DKG_BLOCKCHAIN_NAME="" +# Values: (mainnet) "base:8453", "gnosis:100", "otp:2043" (testnet) "base:84532", "gnosis:10200", "otp:20430" + +# Initia Plugin Configuration +INITIA_PRIVATE_KEY= # Your Initia wallet private key +INITIA_NODE_URL= # Initia node URL (default: testnet) +INITIA_CHAIN_ID=initia-test # Chain ID (default: testnet) + +# #################################### +# #### NVIDIA Configuration ########## +# #################################### +NVIDIA_NIM_ENV=production +NVIDIA_NIM_SPASH=false +# Api Keys +NVIDIA_NIM_API_KEY= +NVIDIA_NGC_API_KEY= +NVIDIA_NIM_MAX_RETRIES=3 +NVIDIA_NIM_RETRY_DELAY=1000 +NVIDIA_NIM_TIMEOUT=5000 +# Logging Configuration +NVIDIA_GRANULAR_LOG=true +NVIDIA_LOG_LEVEL=debug +# NVIDIA Off-topic system and user configuration +NVIDIA_OFFTOPIC_SYSTEM= +NVIDIA_OFFTOPIC_USER= +# NVIDIA Cosmos Model Configuration +NVIDIA_NIM_BASE_VISION_URL=https://ai.api.nvidia.com/v1/vlm +NVIDIA_COSMOS_MODEL=nvidia/cosmos-nemotron-34b +NVIDIA_COSMOS_INVOKE_URL=https://ai.api.nvidia.com/v1/vlm/nvidia/cosmos-nemotron-34b +NVIDIA_COSMOS_ASSET_URL=https://api.nvcf.nvidia.com/v2/nvcf/assets +NVIDIA_COSMOS_MAX_TOKENS=1000 + +# Email Plugin Configuration + +# Outgoing Email Settings (SMTP/Gmail) +EMAIL_OUTGOING_SERVICE=smtp # Use "smtp" or "gmail" +EMAIL_OUTGOING_HOST=smtp.example.com # Required for SMTP only +EMAIL_OUTGOING_PORT=465 # Default 465 for secure SMTP, 587 for TLS +EMAIL_OUTGOING_USER= +EMAIL_OUTGOING_PASS= # For Gmail, use App Password + +# Incoming Email Settings (IMAP) +EMAIL_INCOMING_SERVICE=imap +EMAIL_INCOMING_HOST=imap.example.com +EMAIL_INCOMING_PORT=993 # Default port for secure IMAP +EMAIL_INCOMING_USER= +EMAIL_INCOMING_PASS= + +# SEI Network Ecosystem +SEI_PRIVATE_KEY= +SEI_NETWORK= # Either "mainnet", "testnet", or "devnet" +SEI_RPC_URL= # Only set if using a different RPC URL from the default + +# Omniflix +OMNIFLIX_API_URL= # https://rest.omniflix.network +OMNIFLIX_MNEMONIC= # your mnemonic 12 words or 24 words +OMNIFLIX_RPC_ENDPOINT= # https://rpc.omniflix.network +OMNIFLIX_PRIVATE_KEY= # your private key + +# Suno AI Music Generation +SUNO_API_KEY= + +# Udio AI Music Generation +UDIO_AUTH_TOKEN= + +# Football Plugin Configuration +FOOTBALL_API_KEY= # API key from Football-Data.org (https://www.football-data.org/) + +# Imgflip +IMGFLIP_USERNAME= +IMGFLIP_PASSWORD= + +# Hyperliquid Api +HYPERLIQUID_PRIVATE_KEY= # Required for trading and cancelling orders, your_private_key +HYPERLIQUID_TESTNET= # Optional, defaults to false; true or false + +# Lit Protocol +FUNDING_PRIVATE_KEY= # Private key for funding transactions in Lit Protocol +EVM_RPC_URL= # RPC endpoint URL for blockchain interactions + +# EthStorage DA Configuration +ETHSTORAGE_PRIVATE_KEY= +ETHSTORAGE_ADDRESS=0x64003adbdf3014f7E38FC6BE752EB047b95da89A +ETHSTORAGE_RPC_URL=https://rpc.beta.testnet.l2.quarkchain.io:8545 + + +# Email Automation Plugin Configuration +RESEND_API_KEY= # Your Resend API key +DEFAULT_TO_EMAIL= # Default recipient +DEFAULT_FROM_EMAIL= # Default sender + +# Optional Settings +EMAIL_AUTOMATION_ENABLED=false # Enable AI detection. If this is enabled, the plugin will automatically detect email-worthy conversations and handle generation/delivery and only that. +EMAIL_EVALUATION_PROMPT= # Custom detection criteria for shouldEmail# #################################### + + +# #### ANKR Configuration #### +# #################################### +ANKR_ENV=production +ANKR_WALLET= +ANKR_MAX_RETRIES=3 +ANKR_RETRY_DELAY=1000 +ANKR_TIMEOUT=5000 +ANKR_GRANULAR_LOG=true +ANKR_LOG_LEVEL=debug +ANKR_RUNTIME_CHECK_MODE=false +ANKR_SPASH=true + +# DCAP Plugin Configuration +DCAP_EVM_PRIVATE_KEY= +DCAP_MODE= # Options: OFF, PLUGIN-SGX, PLUGIN-TEE, MOCK + +# QuickIntel Token Security API +QUICKINTEL_API_KEY= # Your QuickIntel API key for token security analysis + +# News API Key +NEWS_API_KEY= # News API KEY from https://newsapi.org/ + +# BTCFUN Plugin Configuration +BTCFUN_API_URL= # Default: https://api-testnet-new.btc.fun +BTC_PRIVATE_KEY_WIF= # Your BTC private key in WIF format +BTC_ADDRESS= # Your BTC address +BTC_MINT_CAP=10000 # Maximum amount that can be minted +BTC_MINT_DEADLINE=864000 # Deadline for minting in seconds +BTC_FUNDRAISING_CAP=100 # Maximum amount for fundraising + +# Trikon Plugin Configuration +TRIKON_WALLET_ADDRESS= # Your Trikon wallet address (must be a valid 64-character hex string starting with '0x') +TRIKON_INITIAL_BALANCE= # (Optional) The initial balance for the wallet. Defaults to "0" if not provided. + +#################################### +#### Arbitrage Plugin Configuration #### +#################################### + +ARBITRAGE_ETHEREUM_WS_URL= # WebSocket URL for Ethereum node connection +ARBITRAGE_EVM_PROVIDER_URL= # RPC URL for Ethereum node connection (if WS not available) +ARBITRAGE_EVM_PRIVATE_KEY= # Private key for the wallet executing arbitrage transactions +FLASHBOTS_RELAY_SIGNING_KEY= # Signing key for Flashbots relay interactions +BUNDLE_EXECUTOR_ADDRESS= # Address of the bundle executor contract + + diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 33527e7c354..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "plugins": ["@stylistic"], - "extends": [ - "next/core-web-vitals", - "plugin:@stylistic/recommended-extends" - ], - "rules": { - "@stylistic/indent": [ - "error", - 4, - { - "SwitchCase": 1 - } - ], - "@stylistic/no-tabs": "error", - "@stylistic/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@stylistic/eol-last": ["error", "always"], - "@stylistic/multiline-ternary": "off", - "@stylistic/semi": ["error", "always"], - "@stylistic/quotes": "off", - "@stylistic/comma-dangle": "off", - "@stylistic/brace-style": ["error", "1tbs"] - } -} diff --git a/.github/workflows/block-mini.yml b/.github/workflows/block-mini.yml new file mode 100644 index 00000000000..eaacd20d175 --- /dev/null +++ b/.github/workflows/block-mini.yml @@ -0,0 +1,60 @@ +name: Block Minified JavaScript/TypeScript + +on: + pull_request: + branches: ["main", "develop", "*"] + push: + branches: ["main", "develop", "*"] + +jobs: + block-minified-code: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Detect potential minified code + shell: bash + run: | + echo "Scanning for potential minified JS/TS code..." + + # We'll look in .ts, .tsx, .js, .jsx files, skipping common build dirs. + FILES=$(find . \ + \( -name 'node_modules' -prune \) -o \ + \( -name 'dist' -prune \) -o \ + \( -name 'build' -prune \) -o \ + -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' \) \ + -print) + + if [ -z "$FILES" ]; then + echo "No relevant JS/TS files found." + exit 0 + fi + + THRESHOLD=1000 + VIOLATIONS=0 + + for file in $FILES; do + # Use grep -En to capture line number and text + # If any line is ≥ THRESHOLD chars, we store those lines in RESULTS + RESULTS=$(grep -En ".{${THRESHOLD},}" "$file" || true) + if [ -n "$RESULTS" ]; then + # We have potential minified lines + while IFS= read -r match; do + # 'match' will be something like "1234:the entire matched line" + LINENUM=$(echo "$match" | cut -d: -f1) + # If you want the text, you can do: + # MATCHED_LINE=$(echo "$match" | cut -d: -f2-) + + echo "::error file=$file,line=$LINENUM::Detected potential minified code (≥ $THRESHOLD chars)." + done <<< "$RESULTS" + VIOLATIONS=1 + fi + done + + if [ "$VIOLATIONS" -eq 1 ]; then + echo "ERROR: Minified code detected. Please remove or exclude it." + exit 1 + else + echo "No minified code detected." + fi diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 45a4b4b3673..b0ae26bf7d9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,12 +7,17 @@ on: jobs: check: runs-on: ubuntu-latest + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_REMOTE_ONLY: true steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v3 with: - version: 9.4.0 + version: 9.15.0 - uses: actions/setup-node@v4 with: @@ -22,11 +27,13 @@ jobs: - name: Install dependencies run: pnpm install -r --no-frozen-lockfile - - name: Run Prettier - run: pnpm run prettier --check . + - name: Setup Biome CLI + uses: biomejs/setup-biome@v2 + with: + version: latest - - name: Run Linter - run: pnpm run lint + - name: Run Biome + run: biome ci - name: Create test env file run: | diff --git a/.github/workflows/generate-readme-translations.yml b/.github/workflows/generate-readme-translations.yml index b1ba989d358..de2d5fa13b1 100644 --- a/.github/workflows/generate-readme-translations.yml +++ b/.github/workflows/generate-readme-translations.yml @@ -24,6 +24,15 @@ jobs: { code: "TH", name: "Thai" }, { code: "TR", name: "Turkish" }, { code: "VI", name: "Vietnamese" }, + { code: "AR", name: "Arabic" }, + { code: "RS", name: "Srpski" }, + { code: "TG", name: "Tagalog" }, + { code: "PL", name: "Polski" }, + { code: "HU", name: "Hungarian" }, + { code: "FA", name: "Persian" }, + { code: "RO", name: "Romanian" }, + { code: "GR", name: "Greek" }, + { code: "NL", name: "Dutch" }, ] permissions: contents: write @@ -53,7 +62,7 @@ jobs: "content_path": "README.md" } ], - "save_path": "README_${{ matrix.language.code }}.md", + save_path: "i18n/readme/README_${{ matrix.language.code }}.md", "model": "gpt-4o" } diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 750e5ce458b..4e39d95ffff 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -12,5 +12,5 @@ jobs: - uses: actions/first-interaction@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-message: "Hello @${{ github.actor }}! Welcome to the ai16z community. Thank you for opening your first issue; we appreciate your contribution. You are now a ai16z contributor!" - pr-message: "Hi @${{ github.actor }}! Welcome to the ai16z community. Thanks for submitting your first pull request; your efforts are helping us accelerate towards AGI. We'll review it shortly. You are now a ai16z contributor!" + issue-message: "Hello @${{ github.actor }}! Welcome to the elizaOS community. Thank you for opening your first issue; we appreciate your contribution. You are now an elizaOS contributor!" + pr-message: "Hi @${{ github.actor }}! Welcome to the elizaOS community. Thanks for submitting your first pull request; your efforts are helping us accelerate towards AGI. We'll review it shortly. You are now an elizaOS contributor!" diff --git a/.github/workflows/integrationTests.yaml b/.github/workflows/integrationTests.yaml index b21aac7b558..0681d3d3327 100644 --- a/.github/workflows/integrationTests.yaml +++ b/.github/workflows/integrationTests.yaml @@ -1,41 +1,44 @@ name: Integration Tests on: - push: - branches: - - "*" - pull_request: - branches: - - "*" + push: + branches: + - "*" + pull_request_target: + branches: + - "*" jobs: - integration-tests: - runs-on: ubuntu-latest - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - steps: - - uses: actions/checkout@v4 + integration-tests: + runs-on: ubuntu-latest + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_REMOTE_ONLY: true + steps: + - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v3 - with: - version: 9.15.0 + - uses: pnpm/action-setup@v3 + with: + version: 9.15.0 - - uses: actions/setup-node@v4 - with: - node-version: "23.3.0" - cache: "pnpm" + - uses: actions/setup-node@v4 + with: + node-version: "23.3" + cache: "pnpm" - - name: Clean up - run: pnpm clean + - name: Install dependencies + run: pnpm install --no-frozen-lockfile - - name: Install dependencies - run: pnpm install -r --no-frozen-lockfile + - name: Build packages + run: pnpm build - - name: Build packages - run: pnpm build + - name: Check for API key + run: | + if [ -z "$OPENAI_API_KEY" ]; then + echo "Error: OPENAI_API_KEY is not set." + exit 1 + fi - - name: Run integration tests - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COINBASE_COMMERCE_KEY: ${{ secrets.COINBASE_COMMERCE_KEY }} - run: | - pnpm run integrationTests + - name: Run integration tests + run: pnpm run integrationTests \ No newline at end of file diff --git a/.github/workflows/minimal-merge-queue.yml b/.github/workflows/minimal-merge-queue.yml new file mode 100644 index 00000000000..08fd3e9b8e9 --- /dev/null +++ b/.github/workflows/minimal-merge-queue.yml @@ -0,0 +1,10 @@ +name: Merge Group Checks +on: + merge_group: + types: [checks_requested] +jobs: + minimal-check: + runs-on: ubuntu-latest + steps: + - name: Always pass + run: echo "All good!" diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index e228b9d071e..b90c3031bfb 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -22,7 +22,7 @@ jobs: - uses: pnpm/action-setup@v3 with: - version: 8 + version: 9.15.0 - name: Configure Git run: | diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 2c088afbe68..3070cd3f63b 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -1,26 +1,31 @@ name: smoke-test on: - push: - branches: - - "*" - pull_request: - branches: - - "*" + push: + branches: + - "*" + pull_request: + branches: + - "*" jobs: - smoke-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 + smoke-tests: + runs-on: ubuntu-latest + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_REMOTE_ONLY: true + steps: + - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v3 - with: - version: 9.15.0 + - uses: pnpm/action-setup@v3 + with: + version: 9.15.0 - - uses: actions/setup-node@v4 - with: - node-version: "23.3.0" - cache: "pnpm" + - uses: actions/setup-node@v4 + with: + node-version: "23.3" + cache: "pnpm" - - name: Run smoke tests - run: pnpm run smokeTests + - name: Run smoke tests + run: pnpm run smokeTests diff --git a/.gitignore b/.gitignore index 86be41efaf2..2746205bef8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,11 @@ concatenated-output.ts embedding-cache.json packages/plugin-buttplug/intiface-engine +node-compile-cache + .idea +.vscode +.zed .DS_Store dist/ @@ -40,7 +44,11 @@ timeline_cache.json *.sqlite -characters/ +# Character configurations +characters/**/secrets.json +characters/**/*.env +characters/**/*.key +characters/**/private/ packages/core/src/providers/cache packages/core/src/providers/cache/* @@ -52,6 +60,8 @@ tsup.config.bundled_*.mjs .turbo .cursorrules .pnpm-store +instructions.md +wallet_data.txt coverage .eslintcache @@ -61,3 +71,24 @@ agent/content eliza.manifest eliza.manifest.sgx eliza.sig + +packages/plugin-nvidia-nim/extra +packages/plugin-nvidia-nim/old_code +packages/plugin-nvidia-nim/docs + +# Edriziai specific ignores +characters/edriziai-info/secrets.json + +# Bug Hunter logs and checkpoints +scripts/bug_hunt/logs/ +scripts/bug_hunt/logs/*.log +scripts/bug_hunt/checkpoints/ +scripts/bug_hunt/checkpoints/*.json +scripts/bug_hunt/reports/ +scripts/bug_hunt/reports/*.md + +lit-config.json + +# Configuration to exclude the extra and local_docs directories +extra +**/dist/** \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 30a1891bdc1..00000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Launch via pnpm", - "runtimeExecutable": "pnpm", - "runtimeArgs": ["run", "dev"], - "skipFiles": ["/**"] - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 7d430c55039..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" - }, - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.insertSpaces": true, - "editor.detectIndentation": false, - "editor.tabSize": 4, - "eslint.format.enable": true, - "javascript.format.enable": false, - "typescript.format.enable": false, - "files.trimTrailingWhitespace": true, - "editor.trimAutoWhitespace": true, - "cadence.test.maxConcurrency": 5, - "cadence.customConfigPath": "packages/plugin-flow/flow.json", - "[properties]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[javascriptreact]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, - "[jsonc]": { - "editor.defaultFormatter": "vscode.json-language-features" - }, - "[javascript]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, - "[scss]": { - "editor.defaultFormatter": "vscode.css-language-features" - }, - "[dotenv]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "files.associations": { - "*.css": "tailwindcss" - }, - "[shellscript]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "explorer.fileNesting.enabled": true, - "explorer.fileNesting.patterns": { - "*.ts": "${capture}.js", - "*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts", - "*.jsx": "${capture}.js", - "*.tsx": "${capture}.ts", - "tsconfig.json": "tsconfig.*.json", - "package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb,pnpm-workspace.yaml", - "README.md": "*.md", - "Dockerfile": "docker-compose-docs.yaml,docker-compose.yaml,Dockerfile.docs" - } -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 805402a1908..00000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "type": "typescript", - "tsconfig": "packages/core/tsconfig.json", - "problemMatcher": ["$tsc"], - "label": "tsbuild", - "group": "build" - } - ] -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 828ba71d42e..8ec2756c0f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1312,7 +1312,7 @@ - Add OLLAMA as Model Provider [\#221](https://github.com/elizaOS/eliza/pull/221) ([o-on-x](https://github.com/o-on-x)) - lazy load llama [\#220](https://github.com/elizaOS/eliza/pull/220) ([lalalune](https://github.com/lalalune)) - Implement grok beta [\#216](https://github.com/elizaOS/eliza/pull/216) ([MeDott29](https://github.com/MeDott29)) -- Abstracts Eliza into a Package to enble publishing onto NPM along with plugin system [\#214](https://github.com/elizaOS/eliza/pull/214) ([ponderingdemocritus](https://github.com/ponderingdemocritus)) +- Abstracts Eliza into a Package to enable publishing onto NPM along with plugin system [\#214](https://github.com/elizaOS/eliza/pull/214) ([ponderingdemocritus](https://github.com/ponderingdemocritus)) - add the template overrides [\#207](https://github.com/elizaOS/eliza/pull/207) ([lalalune](https://github.com/lalalune)) - Shaw fix characters paths, .ts requirement and missings args [\#204](https://github.com/elizaOS/eliza/pull/204) ([lalalune](https://github.com/lalalune)) - Fix Discord Voice and DMs [\#203](https://github.com/elizaOS/eliza/pull/203) ([lalalune](https://github.com/lalalune)) diff --git a/Dockerfile b/Dockerfile index 4a4341ebaab..12adbb4a213 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,43 +1,62 @@ # Use a specific Node.js version for better reproducibility FROM node:23.3.0-slim AS builder -# Install pnpm globally and install necessary build tools +# Install pnpm globally and necessary build tools RUN npm install -g pnpm@9.4.0 && \ apt-get update && \ - apt-get install -y git python3 make g++ && \ + apt-get upgrade -y && \ + apt-get install -y \ + git \ + python3 \ + python3-pip \ + curl \ + node-gyp \ + ffmpeg \ + libtool-bin \ + autoconf \ + automake \ + libopus-dev \ + make \ + g++ \ + build-essential \ + libcairo2-dev \ + libjpeg-dev \ + libpango1.0-dev \ + libgif-dev \ + openssl \ + libssl-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # Set Python 3 as the default python -RUN ln -s /usr/bin/python3 /usr/bin/python +RUN ln -sf /usr/bin/python3 /usr/bin/python # Set the working directory WORKDIR /app -# Copy package.json and other configuration files -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc turbo.json ./ +# Copy application code +COPY . . -# Copy the rest of the application code -COPY agent ./agent -COPY packages ./packages -COPY scripts ./scripts -COPY characters ./characters +# Install dependencies +RUN pnpm install --no-frozen-lockfile -# Install dependencies and build the project -RUN pnpm install \ - && pnpm build-docker \ - && pnpm prune --prod +# Build the project +RUN pnpm run build && pnpm prune --prod -# Create a new stage for the final image +# Final runtime image FROM node:23.3.0-slim -# Install runtime dependencies if needed +# Install runtime dependencies RUN npm install -g pnpm@9.4.0 && \ apt-get update && \ - apt-get install -y git python3 && \ + apt-get install -y \ + git \ + python3 \ + ffmpeg && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +# Set the working directory WORKDIR /app # Copy built artifacts and production dependencies from the builder stage @@ -47,9 +66,14 @@ COPY --from=builder /app/.npmrc ./ COPY --from=builder /app/turbo.json ./ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/agent ./agent +COPY --from=builder /app/client ./client +COPY --from=builder /app/lerna.json ./ COPY --from=builder /app/packages ./packages COPY --from=builder /app/scripts ./scripts COPY --from=builder /app/characters ./characters -# Set the command to run the application -CMD ["pnpm", "start"] +# Expose necessary ports +EXPOSE 3000 5173 + +# Command to start the application +CMD ["sh", "-c", "pnpm start & pnpm start:client"] diff --git a/Dockerfile.docs b/Dockerfile.docs index f91ecc49395..2a9f0a6557d 100644 --- a/Dockerfile.docs +++ b/Dockerfile.docs @@ -1,63 +1,43 @@ # syntax=docker/dockerfile:1 -## Modified version of https://docusaurus.community/knowledge/deployment/docker/ - # Stage 1: Base image. ## Start with a base image containing NodeJS so we can build Docusaurus. FROM node:23.3.0-slim AS base ## Disable colour output from yarn to make logs easier to read. - -## https://pnpm.io/docker -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" - ENV FORCE_COLOR=0 ## Enable corepack. RUN corepack enable ## Set the working directory to `/opt/docusaurus`. WORKDIR /opt/docusaurus -## Required by docusaurus: [ERROR] Loading of version failed for version current -RUN apt-get update && apt-get install -y git - +# Stage 2a: Development mode. FROM base AS dev ## Set the working directory to `/opt/docusaurus`. WORKDIR /opt/docusaurus ## Expose the port that Docusaurus will run on. EXPOSE 3000 ## Run the development server. -CMD [ -d "node_modules" ] && npm run start -- --host 0.0.0.0 --poll 1000 || pnpm install && pnpm run start -- --host 0.0.0.0 --poll 1000 +CMD [ -d "node_modules" ] && pnpm start -- --host 0.0.0.0 --poll 1000 || pnpm install && pnpm start -- --host 0.0.0.0 --poll 1000 # Stage 2b: Production build mode. -FROM base AS preprod +FROM base AS prod ## Set the working directory to `/opt/docusaurus`. WORKDIR /opt/docusaurus -## This is in case someone needs to build the lock file -#RUN apt install python-is-python3 g++ make -y - -COPY docs/package.json /opt/docusaurus/package.json -COPY docs/package-lock.json /opt/docusaurus/package-lock.json - -FROM preprod AS prod - -## Install dependencies with `--immutable` to ensure reproducibility. -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install - -## Copy over the source code. COPY docs/ /opt/docusaurus/ COPY packages/ /opt/packages/ ## Required buy docusaurus [ERROR] Loading of version failed for version current COPY .git/ /opt/.git/ -# Build from sources -RUN pnpm run build +## Install dependencies with `--frozen-lockfile` to ensure reproducibility. +RUN pnpm install --no-frozen-lockfile +## Build the static site. +RUN pnpm build # Stage 3a: Serve with `docusaurus serve`. FROM prod AS serve ## Expose the port that Docusaurus will run on. EXPOSE 3000 ## Run the production server. -CMD ["npm", "run", "serve", "--", "--host", "0.0.0.0", "--no-open"] - +CMD ["pnpm", "run", "serve", "--host", "0.0.0.0", "--no-open"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index fcc24382ce0..3e7c8aad86a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Shaw Walters, aka Moon aka @lalalune +Copyright (c) 2025 Shaw Walters, aka Moon aka @lalalune Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/README.md b/README.md index 06a538b21dd..c5b6346f7b1 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@
-📖 [Documentation](https://elizaos.github.io/eliza/) | 🎯 [Examples](https://github.com/thejoven/awesome-eliza) +📑 [Technical Report](https://arxiv.org/pdf/2501.06781) | 📖 [Documentation](https://elizaos.github.io/eliza/) | 🎯 [Examples](https://github.com/thejoven/awesome-eliza)
## 🌍 README Translations -[中文说明](./README_CN.md) | [日本語の説明](./README_JA.md) | [한국어 설명](./README_KOR.md) | [Persian](./README_FA.md) | [Français](./README_FR.md) | [Português](./README_PTBR.md) | [Türkçe](./README_TR.md) | [Русский](./README_RU.md) | [Español](./README_ES.md) | [Italiano](./README_IT.md) | [ไทย](./README_TH.md) | [Deutsch](./README_DE.md) | [Tiếng Việt](./README_VI.md) | [עִברִית](https://github.com/elizaos/Elisa/blob/main/README_HE.md) | [Tagalog](./README_TG.md) | [Polski](./README_PL.md) | [Arabic](./README_AR.md) | [Hungarian](./README_HU.md) | [Srpski](./README_RS.md) | [Română](./README_RO.md) | [Nederlands](./README_NL.md) +[中文说明](i18n/readme/README_CN.md) | [日本語の説明](i18n/readme/README_JA.md) | [한국어 설명](i18n/readme/README_KOR.md) | [Persian](i18n/readme/README_FA.md) | [Français](i18n/readme/README_FR.md) | [Português](i18n/readme/README_PTBR.md) | [Türkçe](i18n/readme/README_TR.md) | [Русский](i18n/readme/README_RU.md) | [Español](i18n/readme/README_ES.md) | [Italiano](i18n/readme/README_IT.md) | [ไทย](i18n/readme/README_TH.md) | [Deutsch](i18n/readme/README_DE.md) | [Tiếng Việt](i18n/readme/README_VI.md) | [עִברִית](i18n/readme/README_HE.md) | [Tagalog](i18n/readme/README_TG.md) | [Polski](i18n/readme/README_PL.md) | [Arabic](i18n/readme/README_AR.md) | [Hungarian](i18n/readme/README_HU.md) | [Srpski](i18n/readme/README_RS.md) | [Română](i18n/readme/README_RO.md) | [Nederlands](i18n/readme/README_NL.md) | [Ελληνικά](i18n/readme/README_GR.md) ## 🚩 Overview @@ -23,12 +23,11 @@ ## ✨ Features - 🛠️ Full-featured Discord, Twitter and Telegram connectors -- 🔗 Support for every model (Llama, Grok, OpenAI, Anthropic, etc.) +- 🔗 Support for every model (Llama, Grok, OpenAI, Anthropic, Gemini, etc.) - 👥 Multi-agent and room support - 📚 Easily ingest and interact with your documents - 💾 Retrievable memory and document store - 🚀 Highly extensible - create your own actions and clients -- ☁️ Supports many models (local Llama, OpenAI, Anthropic, Groq, etc.) - 📦 Just works! ## Video Tutorials @@ -62,33 +61,21 @@ cp .env.example .env pnpm i && pnpm build && pnpm start ``` -Once the agent is running, you should see the message to run "pnpm start:client" at the end. -Open another terminal and move to same directory and then run below command and follow the URL to chat to your agent. - -```bash -pnpm start:client -``` - -Then read the [Documentation](https://elizaos.github.io/eliza/) to learn how to customize your Eliza. - ### Manually Start Eliza (Only recommended if you know what you are doing) +#### Checkout the latest release + ```bash # Clone the repository git clone https://github.com/elizaos/eliza.git -# Checkout the latest release # This project iterates fast, so we recommend checking out the latest release git checkout $(git describe --tags --abbrev=0) # If the above doesn't checkout the latest release, this should work: # git checkout $(git describe --tags `git rev-list --tags --max-count=1`) ``` -### Start Eliza with Gitpod - -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/elizaos/eliza/tree/main) - -### Edit the .env file +#### Edit the .env file Copy .env.example to .env and fill in the appropriate values. @@ -98,15 +85,46 @@ cp .env.example .env Note: .env is optional. If you're planning to run multiple distinct agents, you can pass secrets through the character JSON +#### Start Eliza + +```bash +pnpm i +pnpm build +pnpm start + +# The project iterates fast, sometimes you need to clean the project if you are coming back to the project +pnpm clean +``` + +### Interact via Browser + +Once the agent is running, you should see the message to run "pnpm start:client" at the end. + +Open another terminal, move to the same directory, run the command below, then follow the URL to chat with your agent. + +```bash +pnpm start:client +``` + +Then read the [Documentation](https://elizaos.github.io/eliza/) to learn how to customize your Eliza. + +--- + ### Automatically Start Eliza -This will run everything to set up the project and start the bot with the default character. +The start script provides an automated way to set up and run Eliza: ```bash sh scripts/start.sh ``` -### Edit the character file +For detailed instructions on using the start script, including character management and troubleshooting, see our [Start Script Guide](./docs/docs/guides/start-script.md). + +> **Note**: The start script handles all dependencies, environment setup, and character management automatically. + +--- + +### Modify Character 1. Open `packages/core/src/defaultCharacter.ts` to modify the default character. Uncomment and edit. @@ -116,16 +134,7 @@ sh scripts/start.sh 3. Connect with X (Twitter) - change `"clients": []` to `"clients": ["twitter"]` in the character file to connect with X -### Manually Start Eliza - -```bash -pnpm i -pnpm build -pnpm start - -# The project iterates fast, sometimes you need to clean the project if you are coming back to the project -pnpm clean -``` +--- #### Additional Requirements @@ -135,17 +144,49 @@ You may need to install Sharp. If you see an error when starting up, try install pnpm install --include=optional sharp ``` +--- + +### Start Eliza with Gitpod + +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/elizaos/eliza/tree/main) + +--- + +### Deploy Eliza in one click + +Use [Fleek](https://fleek.xyz/eliza/) to deploy Eliza in one click. This opens Eliza to non-developers and provides the following options to build your agent: +1. Start with a template +2. Build characterfile from scratch +3. Upload pre-made characterfile + +Click [here](https://fleek.xyz/eliza/) to get started! + +--- + ### Community & contact - [GitHub Issues](https://github.com/elizaos/eliza/issues). Best for: bugs you encounter using Eliza, and feature proposals. - [Discord](https://discord.gg/ai16z). Best for: sharing your applications and hanging out with the community. +## Citation + +We now have a [paper](https://arxiv.org/pdf/2501.06781) you can cite for the Eliza OS: +```bibtex +@article{walters2025eliza, + title={Eliza: A Web3 friendly AI Agent Operating System}, + author={Walters, Shaw and Gao, Sam and Nerd, Shakker and Da, Feng and Williams, Warren and Meng, Ting-Chien and Han, Hunter and He, Frank and Zhang, Allen and Wu, Ming and others}, + journal={arXiv preprint arXiv:2501.06781}, + year={2025} +} +``` + ## Contributors - + Eliza project contributors + ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=elizaos/eliza&type=Date)](https://star-history.com/#elizaos/eliza&Date) diff --git a/README_FR.md b/README_FR.md deleted file mode 100644 index 6f120c1f00c..00000000000 --- a/README_FR.md +++ /dev/null @@ -1,84 +0,0 @@ -# Eliza - -Eliza Banner - -## Fonctionnalités - -- 🛠 Support des connecteurs Discord/ Twitter / Telegram -- 🔗 Support des différents modèles d'IA (Llama, Grok, OpenAI, Anthropic, etc.) -- 👥 Gestion de plusieurs agents et assistance -- 📚 Import et interactions avec différents types de documents simplifiés -- 💾 Accès aux données en mémoire et aux documents stockés -- 🚀 Grande personnalisation possible : création de nouveaux clients et de nouvelles actions -- 📦 Simplicité d'utilisation - -Que pouvez-vous faire avec Eliza? - -- 🤖 Chatbot -- 🕵 Agents autonomes -- 📈 Processus automatisés -- 🎮 PNJ interactifs -- 🧠 Trading automatisé - -# Premiers pas - -**Pré-requis (obligatoire) :** - -- [Python 2.7+](https://www.python.org/downloads/) -- [Node.js 23+](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) -- [pnpm](https://pnpm.io/installation) - -> **Note pour Windows :** WSL est requis - -### Editer le fichier .env - -- Copier le fichier d'exemple .env.example et le remplir avec les valeurs adéquates - -``` -cp .env.example .env -``` - -### Modifier les fichiers personnage - -1. Ouvrir le document `src/core/defaultCharacter.ts` afin de modifier le personnage par défaut - -2. Pour ajouter des personnages personnalisés : - - Lancer la commande `pnpm start --characters="path/to/your/character.json"` - - Plusieurs fichiers personnages peuvent être ajoutés en même temps - -### Lancer Eliza - -Après avoir terminé la configuration et les fichiers personnage, lancer le bot en tapant la ligne de commande suivante: - -```bash -pnpm i -pnpm build -pnpm start - -# Le projet étant régulièrement mis à jour, il vous faudra parfois le nettoyer avant de recommencer à travailler dessus -pnpm clean -``` - -#### Ressources additionnelles - -Il vous faudra peut-être installer Sharp. -S'il y a une erreur lors du lancement du bot, essayez d'installer Sharp comme ceci : - -``` -pnpm install --include=optional sharp -``` - -### Communauté et réseaux sociaux - -- [GitHub](https://github.com/elizaos/eliza/issues). Pour partager les bugs découverts lors de l'utilisation d'Eliza, et proposer de nouvelles fonctionnalités. -- [Discord](https://discord.gg/ai16z). Pour partager ses applications et rencontrer la communauté. - -## Contributeurs - - - - - -## Historique d'étoiles - -[![Star History Chart](https://api.star-history.com/svg?repos=elizaos/eliza&type=Date)](https://star-history.com/#elizaos/eliza&Date) diff --git a/agent/package.json b/agent/package.json index 7fd1e3844b0..4d2e88e48b6 100644 --- a/agent/package.json +++ b/agent/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/agent", - "version": "0.1.8-alpha.1", + "version": "0.1.9", "main": "src/index.ts", "type": "module", "scripts": { @@ -18,79 +18,139 @@ "exec": "node --enable-source-maps --loader ts-node/esm src/index.ts" }, "dependencies": { + "@elizaos/adapter-supabase": "workspace:*", "@elizaos/adapter-pglite": "workspace:*", "@elizaos/adapter-postgres": "workspace:*", "@elizaos/adapter-redis": "workspace:*", "@elizaos/adapter-sqlite": "workspace:*", - "@elizaos/adapter-supabase": "workspace:*", + "@elizaos/adapter-qdrant": "workspace:*", + "@elizaos/adapter-mongodb": "workspace:*", "@elizaos/client-auto": "workspace:*", "@elizaos/client-direct": "workspace:*", "@elizaos/client-discord": "workspace:*", "@elizaos/client-farcaster": "workspace:*", "@elizaos/client-lens": "workspace:*", - "@elizaos/client-slack": "workspace:*", "@elizaos/client-telegram": "workspace:*", + "@elizaos/client-telegram-account": "workspace:*", "@elizaos/client-twitter": "workspace:*", + "@elizaos/client-instagram": "workspace:*", + "@elizaos/client-slack": "workspace:*", + "@elizaos/client-alexa": "workspace:*", + "@elizaos/client-simsai": "workspace:*", "@elizaos/core": "workspace:*", "@elizaos/plugin-0g": "workspace:*", - "@elizaos/plugin-3d-generation": "workspace:*", "@elizaos/plugin-abstract": "workspace:*", - "@elizaos/plugin-akash": "workspace:*", - "@elizaos/plugin-allora": "workspace:*", + "@elizaos/plugin-agentkit": "workspace:*", "@elizaos/plugin-aptos": "workspace:*", - "@elizaos/plugin-arthera": "workspace:*", - "@elizaos/plugin-autonome": "workspace:*", - "@elizaos/plugin-avail": "workspace:*", - "@elizaos/plugin-avalanche": "workspace:*", + "@elizaos/plugin-birdeye": "workspace:*", + "@elizaos/plugin-zerion": "workspace:*", "@elizaos/plugin-binance": "workspace:*", + "@elizaos/plugin-avail": "workspace:*", + "@elizaos/plugin-bnb": "workspace:*", "@elizaos/plugin-bootstrap": "workspace:*", + "@elizaos/plugin-di": "workspace:*", + "@elizaos/plugin-intiface": "workspace:*", "@elizaos/plugin-coinbase": "workspace:*", "@elizaos/plugin-coingecko": "workspace:*", "@elizaos/plugin-coinmarketcap": "workspace:*", "@elizaos/plugin-conflux": "workspace:*", "@elizaos/plugin-cosmos": "workspace:*", - "@elizaos/plugin-cronoszkevm": "workspace:*", - "@elizaos/plugin-depin": "workspace:*", "@elizaos/plugin-echochambers": "workspace:*", "@elizaos/plugin-evm": "workspace:*", "@elizaos/plugin-flow": "workspace:*", - "@elizaos/plugin-fuel": "workspace:*", - "@elizaos/plugin-genlayer": "workspace:*", + "@elizaos/plugin-gelato": "workspace:*", "@elizaos/plugin-giphy": "workspace:*", "@elizaos/plugin-gitbook": "workspace:*", + "@elizaos/plugin-gitcoin-passport": "workspace:*", "@elizaos/plugin-goat": "workspace:*", - "@elizaos/plugin-hyperliquid": "workspace:*", "@elizaos/plugin-icp": "workspace:*", + "@elizaos/plugin-initia": "workspace:*", "@elizaos/plugin-image-generation": "workspace:*", "@elizaos/plugin-intiface": "workspace:*", - "@elizaos/plugin-lensNetwork": "workspace:*", + "@elizaos/plugin-lens-network": "workspace:*", "@elizaos/plugin-letzai": "workspace:*", + "@elizaos/plugin-lit": "workspace:*", "@elizaos/plugin-massa": "workspace:*", + "@elizaos/plugin-mind-network": "workspace:*", + "@elizaos/plugin-moralis": "workspace:*", "@elizaos/plugin-movement": "workspace:*", - "@elizaos/plugin-multiversx": "workspace:*", - "@elizaos/plugin-near": "workspace:*", + "@elizaos/plugin-news": "workspace:*", "@elizaos/plugin-nft-generation": "workspace:*", "@elizaos/plugin-node": "workspace:*", - "@elizaos/plugin-obsidian": "workspace:*", - "@elizaos/plugin-opacity": "workspace:*", - "@elizaos/plugin-open-weather": "workspace:*", - "@elizaos/plugin-primus": "workspace:*", - "@elizaos/plugin-quai": "workspace:*", - "@elizaos/plugin-sgx": "workspace:*", + "@elizaos/plugin-quick-intel": "workspace:*", "@elizaos/plugin-solana": "workspace:*", - "@elizaos/plugin-solana-agentkit": "workspace:*", - "@elizaos/plugin-stargaze": "workspace:*", + "@elizaos/plugin-solana-v2": "workspace:*", + "@elizaos/plugin-injective": "workspace:*", + "@elizaos/plugin-solana-agent-kit": "workspace:*", + "@elizaos/plugin-squid-router": "workspace:*", + "@elizaos/plugin-autonome": "workspace:*", "@elizaos/plugin-starknet": "workspace:*", "@elizaos/plugin-story": "workspace:*", "@elizaos/plugin-sui": "workspace:*", + "@elizaos/plugin-sgx": "workspace:*", + "@elizaos/plugin-iq6900": "workspace:*", "@elizaos/plugin-tee": "workspace:*", "@elizaos/plugin-tee-log": "workspace:*", "@elizaos/plugin-tee-marlin": "workspace:*", - "@elizaos/plugin-thirdweb": "workspace:*", "@elizaos/plugin-ton": "workspace:*", "@elizaos/plugin-twitter": "workspace:*", + "@elizaos/plugin-primus": "workspace:*", + "@elizaos/plugin-cronoszkevm": "workspace:*", + "@elizaos/plugin-cronos": "workspace:*", + "@elizaos/plugin-3d-generation": "workspace:*", + "@elizaos/plugin-fuel": "workspace:*", + "@elizaos/plugin-avalanche": "workspace:*", "@elizaos/plugin-video-generation": "workspace:*", "@elizaos/plugin-web-search": "workspace:*", + "@elizaos/plugin-dexscreener": "workspace:*", + "@elizaos/plugin-letzai": "workspace:*", + "@elizaos/plugin-thirdweb": "workspace:*", + "@elizaos/plugin-genlayer": "workspace:*", + "@elizaos/plugin-tee-verifiable-log": "workspace:*", + "@elizaos/plugin-depin": "workspace:*", + "@elizaos/plugin-open-weather": "workspace:*", + "@elizaos/plugin-obsidian": "workspace:*", + "@elizaos/plugin-arthera": "workspace:*", + "@elizaos/plugin-allora": "workspace:*", + "@elizaos/plugin-opacity": "workspace:*", + "@elizaos/plugin-hyperliquid": "workspace:*", + "@elizaos/plugin-akash": "workspace:*", + "@elizaos/plugin-quai": "workspace:*", + "@elizaos/plugin-lightning": "workspace:*", + "@elizaos/plugin-b2": "workspace:*", + "@elizaos/plugin-nft-collections": "workspace:*", + "@elizaos/plugin-pyth-data": "workspace:*", + "@elizaos/plugin-openai": "workspace:*", + "@elizaos/plugin-devin": "workspace:*", + "@elizaos/plugin-holdstation": "workspace:*", + "@elizaos/plugin-router-nitro": "workspace:*", + "@elizaos/plugin-nvidia-nim": "workspace:*", + "@elizaos/plugin-0x": "workspace:*", + "@elizaos/plugin-bittensor": "workspace:*", + "@elizaos/plugin-chainbase": "workspace:*", + "@elizaos/plugin-dkg": "workspace:*", + "@elizaos/plugin-email": "workspace:*", + "@elizaos/plugin-sei": "workspace:*", + "@elizaos/plugin-omniflix": "workspace:*", + "@elizaos/plugin-suno": "workspace:*", + "@elizaos/plugin-udio": "workspace:*", + "@elizaos/plugin-hyperbolic": "workspace:*", + "@elizaos/plugin-football": "workspace:*", + "@elizaos/plugin-imgflip": "workspace:*", + "@elizaos/plugin-ethstorage": "workspace:*", + "@elizaos/plugin-mina": "workspace:*", + "@elizaos/plugin-email-automation": "workspace:*", + "@elizaos/plugin-dcap": "workspace:*", + "@elizaos/plugin-form": "workspace:*", + "@elizaos/plugin-ankr": "workspace:*", + "@elizaos/client-xmtp": "workspace:*", + "@elizaos/plugin-trikon": "workspace:*", + "@elizaos/plugin-zilliqa": "workspace:*", + "@elizaos/client-deva": "workspace:*", + "@elizaos/plugin-arbitrage": "workspace:*", + "@elizaos/plugin-multiversx": "workspace:*", + "@elizaos/plugin-near": "workspace:*", + "@elizaos/plugin-stargaze": "workspace:*", "@elizaos/plugin-zksync-era": "workspace:*", "readline": "1.3.0", "ws": "8.18.0", diff --git a/agent/src/__tests__/client-type-identification.test.ts b/agent/src/__tests__/client-type-identification.test.ts index 07424d07dd5..436fba44114 100644 --- a/agent/src/__tests__/client-type-identification.test.ts +++ b/agent/src/__tests__/client-type-identification.test.ts @@ -1,11 +1,11 @@ -import { Client, IAgentRuntime } from "@elizaos/core"; +import type { Client, IAgentRuntime } from "@elizaos/core"; import { describe, it, expect } from "@jest/globals"; // Helper function to identify client types function determineClientType(client: Client): string { // Check if client has a direct type identifier - if ("type" in client) { - return (client as any).type; + if ("type" in client && typeof client.type === "string") { + return client.type; } // Check constructor name diff --git a/agent/src/index.ts b/agent/src/index.ts index 68a58daa346..1c22ad3ec9a 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -1,53 +1,76 @@ import { PGLiteDatabaseAdapter } from "@elizaos/adapter-pglite"; import { PostgresDatabaseAdapter } from "@elizaos/adapter-postgres"; +import { QdrantDatabaseAdapter } from "@elizaos/adapter-qdrant"; import { RedisClient } from "@elizaos/adapter-redis"; import { SqliteDatabaseAdapter } from "@elizaos/adapter-sqlite"; import { SupabaseDatabaseAdapter } from "@elizaos/adapter-supabase"; import { AutoClientInterface } from "@elizaos/client-auto"; import { DiscordClientInterface } from "@elizaos/client-discord"; -import { FarcasterAgentClient } from "@elizaos/client-farcaster"; +import { InstagramClientInterface } from "@elizaos/client-instagram"; import { LensAgentClient } from "@elizaos/client-lens"; import { SlackClientInterface } from "@elizaos/client-slack"; import { TelegramClientInterface } from "@elizaos/client-telegram"; +import { TelegramAccountClientInterface } from "@elizaos/client-telegram-account"; import { TwitterClientInterface } from "@elizaos/client-twitter"; -// import { ReclaimAdapter } from "@elizaos/plugin-reclaim"; +import { AlexaClientInterface } from "@elizaos/client-alexa"; +import { MongoDBDatabaseAdapter } from "@elizaos/adapter-mongodb"; +import { DevaClientInterface } from "@elizaos/client-deva"; + +import { FarcasterClientInterface } from "@elizaos/client-farcaster"; +import { OmniflixPlugin } from "@elizaos/plugin-omniflix"; +import { JeeterClientInterface } from "@elizaos/client-simsai"; +import { XmtpClientInterface } from "@elizaos/client-xmtp"; import { DirectClient } from "@elizaos/client-direct"; +import { agentKitPlugin } from "@elizaos/plugin-agentkit"; +import { gelatoPlugin } from "@elizaos/plugin-gelato"; import { PrimusAdapter } from "@elizaos/plugin-primus"; - +import { lightningPlugin } from "@elizaos/plugin-lightning"; +import { elizaCodeinPlugin, onchainJson } from "@elizaos/plugin-iq6900"; +import { dcapPlugin } from "@elizaos/plugin-dcap"; import { AgentRuntime, CacheManager, CacheStore, - Character, - Client, + type Character, + type Client, Clients, DbCacheAdapter, defaultCharacter, elizaLogger, FsCacheAdapter, - IAgentRuntime, - ICacheManager, - IDatabaseAdapter, - IDatabaseCacheAdapter, + type IAgentRuntime, + type ICacheManager, + type IDatabaseAdapter, + type IDatabaseCacheAdapter, ModelProviderName, + parseBooleanFromText, settings, stringToUuid, validateCharacterConfig, } from "@elizaos/core"; import { zgPlugin } from "@elizaos/plugin-0g"; +import { footballPlugin } from "@elizaos/plugin-football"; import { bootstrapPlugin } from "@elizaos/plugin-bootstrap"; +import { normalizeCharacter } from "@elizaos/plugin-di"; import createGoatPlugin from "@elizaos/plugin-goat"; +import createZilliqaPlugin from "@elizaos/plugin-zilliqa"; + // import { intifacePlugin } from "@elizaos/plugin-intiface"; -import { DirectClient } from "@elizaos/client-direct"; import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation"; import { abstractPlugin } from "@elizaos/plugin-abstract"; +import { akashPlugin } from "@elizaos/plugin-akash"; import { alloraPlugin } from "@elizaos/plugin-allora"; import { aptosPlugin } from "@elizaos/plugin-aptos"; import { artheraPlugin } from "@elizaos/plugin-arthera"; +import { autonomePlugin } from "@elizaos/plugin-autonome"; import { availPlugin } from "@elizaos/plugin-avail"; import { avalanchePlugin } from "@elizaos/plugin-avalanche"; +import { b2Plugin } from "@elizaos/plugin-b2"; import { binancePlugin } from "@elizaos/plugin-binance"; +import { birdeyePlugin } from "@elizaos/plugin-birdeye"; +import { bittensorPlugin } from "@elizaos/plugin-bittensor"; +import { bnbPlugin } from "@elizaos/plugin-bnb"; import { advancedTradePlugin, coinbaseCommercePlugin, @@ -56,58 +79,89 @@ import { tradePlugin, webhookPlugin, } from "@elizaos/plugin-coinbase"; -import { coinmarketcapPlugin } from "@elizaos/plugin-coinmarketcap"; import { coingeckoPlugin } from "@elizaos/plugin-coingecko"; +import { coinmarketcapPlugin } from "@elizaos/plugin-coinmarketcap"; import { confluxPlugin } from "@elizaos/plugin-conflux"; import { createCosmosPlugin } from "@elizaos/plugin-cosmos"; import { cronosZkEVMPlugin } from "@elizaos/plugin-cronoszkevm"; -import { echoChambersPlugin } from "@elizaos/plugin-echochambers"; import { evmPlugin } from "@elizaos/plugin-evm"; import { flowPlugin } from "@elizaos/plugin-flow"; import { fuelPlugin } from "@elizaos/plugin-fuel"; import { genLayerPlugin } from "@elizaos/plugin-genlayer"; +import { gitcoinPassportPlugin } from "@elizaos/plugin-gitcoin-passport"; +import { initiaPlugin } from "@elizaos/plugin-initia"; import { imageGenerationPlugin } from "@elizaos/plugin-image-generation"; -import { lensPlugin } from "@elizaos/plugin-lensNetwork"; +import { lensPlugin } from "@elizaos/plugin-lens-network"; +import { litPlugin } from "@elizaos/plugin-lit"; +import { mindNetworkPlugin } from "@elizaos/plugin-mind-network"; import { multiversxPlugin } from "@elizaos/plugin-multiversx"; import { nearPlugin } from "@elizaos/plugin-near"; +import createNFTCollectionsPlugin from "@elizaos/plugin-nft-collections"; import { nftGenerationPlugin } from "@elizaos/plugin-nft-generation"; import { createNodePlugin } from "@elizaos/plugin-node"; import { obsidianPlugin } from "@elizaos/plugin-obsidian"; +import { OpacityAdapter } from "@elizaos/plugin-opacity"; +import { openWeatherPlugin } from "@elizaos/plugin-open-weather"; +import { quaiPlugin } from "@elizaos/plugin-quai"; import { sgxPlugin } from "@elizaos/plugin-sgx"; import { solanaPlugin } from "@elizaos/plugin-solana"; -import { solanaAgentkitPlguin } from "@elizaos/plugin-solana-agentkit"; -import { autonomePlugin } from "@elizaos/plugin-autonome"; +import { solanaPluginV2 } from "@elizaos/plugin-solana-v2"; +import { solanaAgentkitPlugin } from "@elizaos/plugin-solana-agent-kit"; +import { squidRouterPlugin } from "@elizaos/plugin-squid-router"; +import { stargazePlugin } from "@elizaos/plugin-stargaze"; import { storyPlugin } from "@elizaos/plugin-story"; import { suiPlugin } from "@elizaos/plugin-sui"; import { TEEMode, teePlugin } from "@elizaos/plugin-tee"; import { teeLogPlugin } from "@elizaos/plugin-tee-log"; import { teeMarlinPlugin } from "@elizaos/plugin-tee-marlin"; +import { verifiableLogPlugin } from "@elizaos/plugin-tee-verifiable-log"; import { tonPlugin } from "@elizaos/plugin-ton"; import { webSearchPlugin } from "@elizaos/plugin-web-search"; - +import { dkgPlugin } from "@elizaos/plugin-dkg"; +import { injectivePlugin } from "@elizaos/plugin-injective"; import { giphyPlugin } from "@elizaos/plugin-giphy"; import { letzAIPlugin } from "@elizaos/plugin-letzai"; import { thirdwebPlugin } from "@elizaos/plugin-thirdweb"; import { hyperliquidPlugin } from "@elizaos/plugin-hyperliquid"; +import { moralisPlugin } from "@elizaos/plugin-moralis"; +import { echoChambersPlugin } from "@elizaos/plugin-echochambers"; +import { dexScreenerPlugin } from "@elizaos/plugin-dexscreener"; +import { pythDataPlugin } from "@elizaos/plugin-pyth-data"; +import { openaiPlugin } from "@elizaos/plugin-openai"; +import nitroPlugin from "@elizaos/plugin-router-nitro"; +import { devinPlugin } from "@elizaos/plugin-devin"; import { zksyncEraPlugin } from "@elizaos/plugin-zksync-era"; - -import { OpacityAdapter } from "@elizaos/plugin-opacity"; -import { openWeatherPlugin } from "@elizaos/plugin-open-weather"; -import { stargazePlugin } from "@elizaos/plugin-stargaze"; -import { akashPlugin } from "@elizaos/plugin-akash"; -import { quaiPlugin } from "@elizaos/plugin-quai"; +import { chainbasePlugin } from "@elizaos/plugin-chainbase"; +import { holdstationPlugin } from "@elizaos/plugin-holdstation"; +import { nvidiaNimPlugin } from "@elizaos/plugin-nvidia-nim"; +import { zxPlugin } from "@elizaos/plugin-0x"; +import { hyperbolicPlugin } from "@elizaos/plugin-hyperbolic"; import Database from "better-sqlite3"; import fs from "fs"; import net from "net"; import path from "path"; import { fileURLToPath } from "url"; import yargs from "yargs"; -import {dominosPlugin} from "@elizaos/plugin-dominos"; - +import { emailPlugin } from "@elizaos/plugin-email"; +import { emailAutomationPlugin } from "@elizaos/plugin-email-automation"; +import { seiPlugin } from "@elizaos/plugin-sei"; +import { sunoPlugin } from "@elizaos/plugin-suno"; +import { udioPlugin } from "@elizaos/plugin-udio"; +import { imgflipPlugin } from "@elizaos/plugin-imgflip"; +import { ethstoragePlugin } from "@elizaos/plugin-ethstorage"; +import { zerionPlugin } from "@elizaos/plugin-zerion"; +import { minaPlugin } from "@elizaos/plugin-mina"; +import { ankrPlugin } from "@elizaos/plugin-ankr"; +import { formPlugin } from "@elizaos/plugin-form"; +import { MongoClient } from "mongodb"; +import { quickIntelPlugin } from "@elizaos/plugin-quick-intel"; + +import { trikonPlugin } from "@elizaos/plugin-trikon"; +import arbitragePlugin from "@elizaos/plugin-arbitrage"; const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file const __dirname = path.dirname(__filename); // get the name of the directory -export const wait = (minTime: number = 1000, maxTime: number = 3000) => { +export const wait = (minTime = 1000, maxTime = 3000) => { const waitTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime; return new Promise((resolve) => setTimeout(resolve, waitTime)); @@ -152,136 +206,279 @@ function tryLoadFile(filePath: string): string | null { function mergeCharacters(base: Character, child: Character): Character { const mergeObjects = (baseObj: any, childObj: any) => { const result: any = {}; - const keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})]); - keys.forEach(key => { - if (typeof baseObj[key] === 'object' && typeof childObj[key] === 'object' && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) { + const keys = new Set([ + ...Object.keys(baseObj || {}), + ...Object.keys(childObj || {}), + ]); + keys.forEach((key) => { + if ( + typeof baseObj[key] === "object" && + typeof childObj[key] === "object" && + !Array.isArray(baseObj[key]) && + !Array.isArray(childObj[key]) + ) { result[key] = mergeObjects(baseObj[key], childObj[key]); - } else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) { - result[key] = [...(baseObj[key] || []), ...(childObj[key] || [])]; + } else if ( + Array.isArray(baseObj[key]) || + Array.isArray(childObj[key]) + ) { + result[key] = [ + ...(baseObj[key] || []), + ...(childObj[key] || []), + ]; } else { - result[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key]; + result[key] = + childObj[key] !== undefined ? childObj[key] : baseObj[key]; } }); return result; }; return mergeObjects(base, child); } -async function loadCharacter(filePath: string): Promise { - const content = tryLoadFile(filePath); - if (!content) { - throw new Error(`Character file not found: ${filePath}`); +function isAllStrings(arr: unknown[]): boolean { + return Array.isArray(arr) && arr.every((item) => typeof item === "string"); +} +export async function loadCharacterFromOnchain(): Promise { + const jsonText = onchainJson; + + console.log("JSON:", jsonText); + if (!jsonText) return []; + const loadedCharacters = []; + try { + const character = JSON.parse(jsonText); + validateCharacterConfig(character); + + // .id isn't really valid + const characterId = character.id || character.name; + const characterPrefix = `CHARACTER.${characterId + .toUpperCase() + .replace(/ /g, "_")}.`; + + const characterSettings = Object.entries(process.env) + .filter(([key]) => key.startsWith(characterPrefix)) + .reduce((settings, [key, value]) => { + const settingKey = key.slice(characterPrefix.length); + settings[settingKey] = value; + return settings; + }, {}); + + if (Object.keys(characterSettings).length > 0) { + character.settings = character.settings || {}; + character.settings.secrets = { + ...characterSettings, + ...character.settings.secrets, + }; + } + + // Handle plugins + if (isAllStrings(character.plugins)) { + elizaLogger.info("Plugins are: ", character.plugins); + const importedPlugins = await Promise.all( + character.plugins.map(async (plugin) => { + const importedPlugin = await import(plugin); + return importedPlugin.default; + }) + ); + character.plugins = importedPlugins; + } + + loadedCharacters.push(character); + elizaLogger.info( + `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}` + ); + return loadedCharacters; + } catch (e) { + elizaLogger.error( + `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}` + ); + process.exit(1); + } +} + +async function loadCharactersFromUrl(url: string): Promise { + try { + const response = await fetch(url); + const responseJson = await response.json(); + + let characters: Character[] = []; + if (Array.isArray(responseJson)) { + characters = await Promise.all( + responseJson.map((character) => jsonToCharacter(url, character)) + ); + } else { + const character = await jsonToCharacter(url, responseJson); + characters.push(character); + } + return characters; + } catch (e) { + elizaLogger.error(`Error loading character(s) from ${url}: ${e}`); + process.exit(1); } - let character = JSON.parse(content); +} + +async function jsonToCharacter( + filePath: string, + character: any +): Promise { validateCharacterConfig(character); - // .id isn't really valid - const characterId = character.id || character.name; - const characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, "_")}.`; - const characterSettings = Object.entries(process.env) - .filter(([key]) => key.startsWith(characterPrefix)) - .reduce((settings, [key, value]) => { - const settingKey = key.slice(characterPrefix.length); - return { ...settings, [settingKey]: value }; - }, {}); - if (Object.keys(characterSettings).length > 0) { - character.settings = character.settings || {}; - character.settings.secrets = { - ...characterSettings, - ...character.settings.secrets, - }; - } - // Handle plugins - character.plugins = await handlePluginImporting( - character.plugins - ); + // .id isn't really valid + const characterId = character.id || character.name; + const characterPrefix = `CHARACTER.${characterId + .toUpperCase() + .replace(/ /g, "_")}.`; + const characterSettings = Object.entries(process.env) + .filter(([key]) => key.startsWith(characterPrefix)) + .reduce((settings, [key, value]) => { + const settingKey = key.slice(characterPrefix.length); + return { ...settings, [settingKey]: value }; + }, {}); + if (Object.keys(characterSettings).length > 0) { + character.settings = character.settings || {}; + character.settings.secrets = { + ...characterSettings, + ...character.settings.secrets, + }; + } + // Handle plugins + character.plugins = await handlePluginImporting(character.plugins); if (character.extends) { - elizaLogger.info(`Merging ${character.name} character with parent characters`); + elizaLogger.info( + `Merging ${character.name} character with parent characters` + ); for (const extendPath of character.extends) { - const baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath)); + const baseCharacter = await loadCharacter( + path.resolve(path.dirname(filePath), extendPath) + ); character = mergeCharacters(baseCharacter, character); - elizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`); + elizaLogger.info( + `Merged ${character.name} with ${baseCharacter.name}` + ); } } return character; } +async function loadCharacter(filePath: string): Promise { + const content = tryLoadFile(filePath); + if (!content) { + throw new Error(`Character file not found: ${filePath}`); + } + const character = JSON.parse(content); + return jsonToCharacter(filePath, character); +} + +async function loadCharacterTryPath(characterPath: string): Promise { + let content: string | null = null; + let resolvedPath = ""; + + // Try different path resolutions in order + const pathsToTry = [ + characterPath, // exact path as specified + path.resolve(process.cwd(), characterPath), // relative to cwd + path.resolve(process.cwd(), "agent", characterPath), // Add this + path.resolve(__dirname, characterPath), // relative to current script + path.resolve(__dirname, "characters", path.basename(characterPath)), // relative to agent/characters + path.resolve(__dirname, "../characters", path.basename(characterPath)), // relative to characters dir from agent + path.resolve( + __dirname, + "../../characters", + path.basename(characterPath) + ), // relative to project root characters dir + ]; + + elizaLogger.info( + "Trying paths:", + pathsToTry.map((p) => ({ + path: p, + exists: fs.existsSync(p), + })) + ); + + for (const tryPath of pathsToTry) { + content = tryLoadFile(tryPath); + if (content !== null) { + resolvedPath = tryPath; + break; + } + } + + if (content === null) { + elizaLogger.error( + `Error loading character from ${characterPath}: File not found in any of the expected locations` + ); + elizaLogger.error("Tried the following paths:"); + pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`)); + throw new Error( + `Error loading character from ${characterPath}: File not found in any of the expected locations` + ); + } + try { + const character: Character = await loadCharacter(resolvedPath); + elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`); + return character; + } catch (e) { + elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`); + throw new Error(`Error parsing character from ${resolvedPath}: ${e}`); + } +} + +function commaSeparatedStringToArray(commaSeparated: string): string[] { + return commaSeparated?.split(",").map((value) => value.trim()); +} + +async function readCharactersFromStorage( + characterPaths: string[] +): Promise { + try { + const uploadDir = path.join(process.cwd(), "data", "characters"); + await fs.promises.mkdir(uploadDir, { recursive: true }); + const fileNames = await fs.promises.readdir(uploadDir); + fileNames.forEach((fileName) => { + characterPaths.push(path.join(uploadDir, fileName)); + }); + } catch (err) { + elizaLogger.error(`Error reading directory: ${err.message}`); + } + + return characterPaths; +} + export async function loadCharacters( charactersArg: string ): Promise { - let characterPaths = charactersArg - ?.split(",") - .map((filePath) => filePath.trim()); + let characterPaths = commaSeparatedStringToArray(charactersArg); + + if (process.env.USE_CHARACTER_STORAGE === "true") { + characterPaths = await readCharactersFromStorage(characterPaths); + } + const loadedCharacters: Character[] = []; if (characterPaths?.length > 0) { for (const characterPath of characterPaths) { - let content: string | null = null; - let resolvedPath = ""; - - // Try different path resolutions in order - const pathsToTry = [ - characterPath, // exact path as specified - path.resolve(process.cwd(), characterPath), // relative to cwd - path.resolve(process.cwd(), "agent", characterPath), // Add this - path.resolve(__dirname, characterPath), // relative to current script - path.resolve( - __dirname, - "characters", - path.basename(characterPath) - ), // relative to agent/characters - path.resolve( - __dirname, - "../characters", - path.basename(characterPath) - ), // relative to characters dir from agent - path.resolve( - __dirname, - "../../characters", - path.basename(characterPath) - ), // relative to project root characters dir - ]; - - elizaLogger.info( - "Trying paths:", - pathsToTry.map((p) => ({ - path: p, - exists: fs.existsSync(p), - })) - ); - - for (const tryPath of pathsToTry) { - content = tryLoadFile(tryPath); - if (content !== null) { - resolvedPath = tryPath; - break; - } - } - - if (content === null) { - elizaLogger.error( - `Error loading character from ${characterPath}: File not found in any of the expected locations` - ); - elizaLogger.error("Tried the following paths:"); - pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`)); - process.exit(1); - } - try { - const character: Character = await loadCharacter(resolvedPath); - - loadedCharacters.push(character); - elizaLogger.info( - `Successfully loaded character from: ${resolvedPath}` + const character: Character = await loadCharacterTryPath( + characterPath ); + loadedCharacters.push(character); } catch (e) { - elizaLogger.error( - `Error parsing character from ${resolvedPath}: ${e}` - ); process.exit(1); } } } + if (hasValidRemoteUrls()) { + elizaLogger.info("Loading characters from remote URLs"); + const characterUrls = commaSeparatedStringToArray( + process.env.REMOTE_CHARACTER_URLS + ); + for (const characterUrl of characterUrls) { + const characters = await loadCharactersFromUrl(characterUrl); + loadedCharacters.push(...characters); + } + } + if (loadedCharacters.length === 0) { elizaLogger.info("No characters found, using default character"); loadedCharacters.push(defaultCharacter); @@ -325,13 +522,17 @@ export function getTokenForProvider( character: Character ): string | undefined { switch (provider) { - // no key needed for llama_local or gaianet + // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock case ModelProviderName.LLAMALOCAL: return ""; case ModelProviderName.OLLAMA: return ""; + case ModelProviderName.LMSTUDIO: + return ""; case ModelProviderName.GAIANET: return ""; + case ModelProviderName.BEDROCK: + return ""; case ModelProviderName.OPENAI: return ( character.settings?.secrets?.OPENAI_API_KEY || @@ -372,7 +573,7 @@ export function getTokenForProvider( ); case ModelProviderName.OPENROUTER: return ( - character.settings?.secrets?.OPENROUTER || + character.settings?.secrets?.OPENROUTER_API_KEY || settings.OPENROUTER_API_KEY ); case ModelProviderName.GROK: @@ -419,11 +620,22 @@ export function getTokenForProvider( character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY ); + case ModelProviderName.VENICE: return ( character.settings?.secrets?.VENICE_API_KEY || settings.VENICE_API_KEY ); + case ModelProviderName.ATOMA: + return ( + character.settings?.secrets?.ATOMASDK_BEARER_AUTH || + settings.ATOMASDK_BEARER_AUTH + ); + case ModelProviderName.NVIDIA: + return ( + character.settings?.secrets?.NVIDIA_API_KEY || + settings.NVIDIA_API_KEY + ); case ModelProviderName.AKASH_CHAT_API: return ( character.settings?.secrets?.AKASH_CHAT_API_KEY || @@ -454,6 +666,11 @@ export function getTokenForProvider( character.settings?.secrets?.DEEPSEEK_API_KEY || settings.DEEPSEEK_API_KEY ); + case ModelProviderName.LIVEPEER: + return ( + character.settings?.secrets?.LIVEPEER_GATEWAY_URL || + settings.LIVEPEER_GATEWAY_URL + ); default: const errorMessage = `Failed to get token - unsupported model provider: ${provider}`; elizaLogger.error(errorMessage); @@ -462,7 +679,35 @@ export function getTokenForProvider( } function initializeDatabase(dataDir: string) { - if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) { + if (process.env.MONGODB_CONNECTION_STRING) { + elizaLogger.log("Initializing database on MongoDB Atlas"); + const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, { + maxPoolSize: 100, + minPoolSize: 5, + maxIdleTimeMS: 60000, + connectTimeoutMS: 10000, + serverSelectionTimeoutMS: 5000, + socketTimeoutMS: 45000, + compressors: ["zlib"], + retryWrites: true, + retryReads: true, + }); + + const dbName = process.env.MONGODB_DATABASE || "elizaAgent"; + const db = new MongoDBDatabaseAdapter(client, dbName); + + // Test the connection + db.init() + .then(() => { + elizaLogger.success("Successfully connected to MongoDB Atlas"); + }) + .catch((error) => { + elizaLogger.error("Failed to connect to MongoDB Atlas:", error); + throw error; // Re-throw to handle it in the calling code + }); + + return db; + } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) { elizaLogger.info("Initializing Supabase connection..."); const db = new SupabaseDatabaseAdapter( process.env.SUPABASE_URL, @@ -472,7 +717,9 @@ function initializeDatabase(dataDir: string) { // Test the connection db.init() .then(() => { - elizaLogger.success("Successfully connected to Supabase database"); + elizaLogger.success( + "Successfully connected to Supabase database" + ); }) .catch((error) => { elizaLogger.error("Failed to connect to Supabase:", error); @@ -489,7 +736,9 @@ function initializeDatabase(dataDir: string) { // Test the connection db.init() .then(() => { - elizaLogger.success("Successfully connected to PostgreSQL database"); + elizaLogger.success( + "Successfully connected to PostgreSQL database" + ); }) .catch((error) => { elizaLogger.error("Failed to connect to PostgreSQL:", error); @@ -503,15 +752,32 @@ function initializeDatabase(dataDir: string) { dataDir: process.env.PGLITE_DATA_DIR, }); return db; + } else if ( + process.env.QDRANT_URL && + process.env.QDRANT_KEY && + process.env.QDRANT_PORT && + process.env.QDRANT_VECTOR_SIZE + ) { + elizaLogger.info("Initializing Qdrant adapter..."); + const db = new QdrantDatabaseAdapter( + process.env.QDRANT_URL, + process.env.QDRANT_KEY, + Number(process.env.QDRANT_PORT), + Number(process.env.QDRANT_VECTOR_SIZE) + ); + return db; } else { - const filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, "db.sqlite"); + const filePath = + process.env.SQLITE_FILE ?? path.resolve(dataDir, "db.sqlite"); elizaLogger.info(`Initializing SQLite database at ${filePath}...`); const db = new SqliteDatabaseAdapter(new Database(filePath)); // Test the connection db.init() .then(() => { - elizaLogger.success("Successfully connected to SQLite database"); + elizaLogger.success( + "Successfully connected to SQLite database" + ); }) .catch((error) => { elizaLogger.error("Failed to connect to SQLite:", error); @@ -539,6 +805,11 @@ export async function initializeClients( if (autoClient) clients.auto = autoClient; } + if (clientTypes.includes(Clients.XMTP)) { + const xmtpClient = await XmtpClientInterface.start(runtime); + if (xmtpClient) clients.xmtp = xmtpClient; + } + if (clientTypes.includes(Clients.DISCORD)) { const discordClient = await DiscordClientInterface.start(runtime); if (discordClient) clients.discord = discordClient; @@ -549,6 +820,13 @@ export async function initializeClients( if (telegramClient) clients.telegram = telegramClient; } + if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) { + const telegramAccountClient = + await TelegramAccountClientInterface.start(runtime); + if (telegramAccountClient) + clients.telegram_account = telegramAccountClient; + } + if (clientTypes.includes(Clients.TWITTER)) { const twitterClient = await TwitterClientInterface.start(runtime); if (twitterClient) { @@ -556,24 +834,46 @@ export async function initializeClients( } } + if (clientTypes.includes(Clients.ALEXA)) { + const alexaClient = await AlexaClientInterface.start(runtime); + if (alexaClient) { + clients.alexa = alexaClient; + } + } + + if (clientTypes.includes(Clients.INSTAGRAM)) { + const instagramClient = await InstagramClientInterface.start(runtime); + if (instagramClient) { + clients.instagram = instagramClient; + } + } + if (clientTypes.includes(Clients.FARCASTER)) { - // why is this one different :( - const farcasterClient = new FarcasterAgentClient(runtime); + const farcasterClient = await FarcasterClientInterface.start(runtime); if (farcasterClient) { - farcasterClient.start(); clients.farcaster = farcasterClient; } } + if (clientTypes.includes("lens")) { const lensClient = new LensAgentClient(runtime); lensClient.start(); clients.lens = lensClient; } + if (clientTypes.includes(Clients.SIMSAI)) { + const simsaiClient = await JeeterClientInterface.start(runtime); + if (simsaiClient) clients.simsai = simsaiClient; + } + elizaLogger.log("client keys", Object.keys(clients)); - // TODO: Add Slack client to the list - // Initialize clients as an object + if (clientTypes.includes("deva")) { + if (clientTypes.includes("deva")) { + const devaClient = await DevaClientInterface.start(runtime); + if (devaClient) clients.deva = devaClient; + } + } if (clientTypes.includes("slack")) { const slackClient = await SlackClientInterface.start(runtime); @@ -636,7 +936,7 @@ export async function createAgent( // Validate TEE configuration if (teeMode !== TEEMode.OFF && !walletSecretSalt) { elizaLogger.error( - "WALLET_SECRET_SALT required when TEE_MODE is enabled" + "A WALLET_SECRET_SALT required when TEE_MODE is enabled" ); throw new Error("Invalid TEE configuration"); } @@ -649,6 +949,13 @@ export async function createAgent( ); } + let zilliqaPlugin: any | undefined; + if (getSecret(character, "ZILLIQA_PRIVATE_KEY")) { + zilliqaPlugin = await createZilliqaPlugin((secret) => + getSecret(character, secret) + ); + } + // Initialize Reclaim adapter if environment variables are present // let verifiableInferenceAdapter; // if ( @@ -689,7 +996,8 @@ export async function createAgent( if ( process.env.PRIMUS_APP_ID && process.env.PRIMUS_APP_SECRET && - process.env.VERIFIABLE_INFERENCE_ENABLED === "true"){ + process.env.VERIFIABLE_INFERENCE_ENABLED === "true" + ) { verifiableInferenceAdapter = new PrimusAdapter({ appId: process.env.PRIMUS_APP_ID, appSecret: process.env.PRIMUS_APP_SECRET, @@ -708,19 +1016,45 @@ export async function createAgent( character, // character.plugins are handled when clients are added plugins: [ + parseBooleanFromText(getSecret(character, "BITMIND")) && + getSecret(character, "BITMIND_API_TOKEN") + ? bittensorPlugin + : null, + parseBooleanFromText( + getSecret(character, "EMAIL_AUTOMATION_ENABLED") + ) + ? emailAutomationPlugin + : null, + getSecret(character, "IQ_WALLET_ADDRESS") && + getSecret(character, "IQSOlRPC") + ? elizaCodeinPlugin + : null, bootstrapPlugin, + getSecret(character, "CDP_API_KEY_NAME") && + getSecret(character, "CDP_API_KEY_PRIVATE_KEY") && + getSecret(character, "CDP_AGENT_KIT_NETWORK") + ? agentKitPlugin + : null, + getSecret(character, "DEXSCREENER_API_KEY") + ? dexScreenerPlugin + : null, + getSecret(character, "FOOTBALL_API_KEY") ? footballPlugin : null, getSecret(character, "CONFLUX_CORE_PRIVATE_KEY") ? confluxPlugin : null, nodePlugin, + getSecret(character, "ROUTER_NITRO_EVM_PRIVATE_KEY") && + getSecret(character, "ROUTER_NITRO_EVM_ADDRESS") + ? nitroPlugin + : null, getSecret(character, "TAVILY_API_KEY") ? webSearchPlugin : null, getSecret(character, "SOLANA_PUBLIC_KEY") || (getSecret(character, "WALLET_PUBLIC_KEY") && !getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x")) - ? solanaPlugin + ? [solanaPlugin, solanaPluginV2] : null, getSecret(character, "SOLANA_PRIVATE_KEY") - ? solanaAgentkitPlguin + ? solanaAgentkitPlugin : null, getSecret(character, "AUTONOME_JWT_TOKEN") ? autonomePlugin : null, (getSecret(character, "NEAR_ADDRESS") || @@ -733,6 +1067,11 @@ export async function createAgent( getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x")) ? evmPlugin : null, + (getSecret(character, "EVM_PUBLIC_KEY") || + getSecret(character, "INJECTIVE_PUBLIC_KEY")) && + getSecret(character, "INJECTIVE_PRIVATE_KEY") + ? injectivePlugin + : null, getSecret(character, "COSMOS_RECOVERY_PHRASE") && getSecret(character, "COSMOS_AVAILABLE_CHAINS") && createCosmosPlugin(), @@ -750,12 +1089,14 @@ export async function createAgent( getSecret(character, "COINMARKETCAP_API_KEY") ? coinmarketcapPlugin : null, + getSecret(character, "ZERION_API_KEY") ? zerionPlugin : null, getSecret(character, "COINBASE_COMMERCE_KEY") ? coinbaseCommercePlugin : null, getSecret(character, "FAL_API_KEY") || getSecret(character, "OPENAI_API_KEY") || getSecret(character, "VENICE_API_KEY") || + getSecret(character, "NVIDIA_API_KEY") || getSecret(character, "NINETEEN_AI_API_KEY") || getSecret(character, "HEURIST_API_KEY") || getSecret(character, "LIVEPEER_GATEWAY_URL") @@ -772,26 +1113,38 @@ export async function createAgent( ] : []), ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []), + teeMode !== TEEMode.OFF && + walletSecretSalt && + getSecret(character, "VLOG") + ? verifiableLogPlugin + : null, getSecret(character, "SGX") ? sgxPlugin : null, getSecret(character, "ENABLE_TEE_LOG") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, "SGX")) ? teeLogPlugin : null, + getSecret(character, "OMNIFLIX_API_URL") && + getSecret(character, "OMNIFLIX_MNEMONIC") + ? OmniflixPlugin + : null, getSecret(character, "COINBASE_API_KEY") && getSecret(character, "COINBASE_PRIVATE_KEY") && getSecret(character, "COINBASE_NOTIFICATION_URI") ? webhookPlugin : null, goatPlugin, + zilliqaPlugin, getSecret(character, "COINGECKO_API_KEY") || getSecret(character, "COINGECKO_PRO_API_KEY") ? coingeckoPlugin : null, + getSecret(character, "MORALIS_API_KEY") ? moralisPlugin : null, getSecret(character, "EVM_PROVIDER_URL") ? goatPlugin : null, getSecret(character, "ABSTRACT_PRIVATE_KEY") ? abstractPlugin : null, + getSecret(character, "B2_PRIVATE_KEY") ? b2Plugin : null, getSecret(character, "BINANCE_API_KEY") && getSecret(character, "BINANCE_SECRET_KEY") ? binancePlugin @@ -805,6 +1158,9 @@ export async function createAgent( ? lensPlugin : null, getSecret(character, "APTOS_PRIVATE_KEY") ? aptosPlugin : null, + getSecret(character, "MIND_COLD_WALLET_ADDRESS") + ? mindNetworkPlugin + : null, getSecret(character, "MVX_PRIVATE_KEY") ? multiversxPlugin : null, getSecret(character, "ZKSYNC_PRIVATE_KEY") ? zksyncEraPlugin : null, getSecret(character, "CRONOSZKEVM_PRIVATE_KEY") @@ -815,10 +1171,18 @@ export async function createAgent( getSecret(character, "THIRDWEB_SECRET_KEY") ? thirdwebPlugin : null, getSecret(character, "SUI_PRIVATE_KEY") ? suiPlugin : null, getSecret(character, "STORY_PRIVATE_KEY") ? storyPlugin : null, + getSecret(character, "SQUID_SDK_URL") && + getSecret(character, "SQUID_INTEGRATOR_ID") && + getSecret(character, "SQUID_EVM_ADDRESS") && + getSecret(character, "SQUID_EVM_PRIVATE_KEY") && + getSecret(character, "SQUID_API_THROTTLE_INTERVAL") + ? squidRouterPlugin + : null, getSecret(character, "FUEL_PRIVATE_KEY") ? fuelPlugin : null, getSecret(character, "AVALANCHE_PRIVATE_KEY") ? avalanchePlugin : null, + getSecret(character, "BIRDEYE_API_KEY") ? birdeyePlugin : null, getSecret(character, "ECHOCHAMBERS_API_URL") && getSecret(character, "ECHOCHAMBERS_API_KEY") ? echoChambersPlugin @@ -826,6 +1190,9 @@ export async function createAgent( getSecret(character, "LETZAI_API_KEY") ? letzAIPlugin : null, getSecret(character, "STARGAZE_ENDPOINT") ? stargazePlugin : null, getSecret(character, "GIPHY_API_KEY") ? giphyPlugin : null, + getSecret(character, "PASSPORT_API_KEY") + ? gitcoinPassportPlugin + : null, getSecret(character, "GENLAYER_PRIVATE_KEY") ? genLayerPlugin : null, @@ -851,13 +1218,87 @@ export async function createAgent( getSecret(character, "AKASH_WALLET_ADDRESS") ? akashPlugin : null, - getSecret(character, "QUAI_PRIVATE_KEY") - ? quaiPlugin + getSecret(character, "CHAINBASE_API_KEY") ? chainbasePlugin : null, + getSecret(character, "QUAI_PRIVATE_KEY") ? quaiPlugin : null, + getSecret(character, "RESERVOIR_API_KEY") + ? createNFTCollectionsPlugin() + : null, + getSecret(character, "ZERO_EX_API_KEY") ? zxPlugin : null, + getSecret(character, "DKG_PRIVATE_KEY") ? dkgPlugin : null, + getSecret(character, "PYTH_TESTNET_PROGRAM_KEY") || + getSecret(character, "PYTH_MAINNET_PROGRAM_KEY") + ? pythDataPlugin + : null, + getSecret(character, "LND_TLS_CERT") && + getSecret(character, "LND_MACAROON") && + getSecret(character, "LND_SOCKET") + ? lightningPlugin : null, - ].filter(Boolean), + getSecret(character, "OPENAI_API_KEY") && + parseBooleanFromText( + getSecret(character, "ENABLE_OPEN_AI_COMMUNITY_PLUGIN") + ) + ? openaiPlugin + : null, + getSecret(character, "DEVIN_API_TOKEN") ? devinPlugin : null, + getSecret(character, "INITIA_PRIVATE_KEY") ? initiaPlugin : null, + getSecret(character, "HOLDSTATION_PRIVATE_KEY") + ? holdstationPlugin + : null, + getSecret(character, "NVIDIA_NIM_API_KEY") || + getSecret(character, "NVIDIA_NGC_API_KEY") + ? nvidiaNimPlugin + : null, + getSecret(character, "BNB_PRIVATE_KEY") || + getSecret(character, "BNB_PUBLIC_KEY")?.startsWith("0x") + ? bnbPlugin + : null, + (getSecret(character, "EMAIL_INCOMING_USER") && + getSecret(character, "EMAIL_INCOMING_PASS")) || + (getSecret(character, "EMAIL_OUTGOING_USER") && + getSecret(character, "EMAIL_OUTGOING_PASS")) + ? emailPlugin + : null, + getSecret(character, "SEI_PRIVATE_KEY") ? seiPlugin : null, + getSecret(character, "HYPERBOLIC_API_KEY") + ? hyperbolicPlugin + : null, + getSecret(character, "SUNO_API_KEY") ? sunoPlugin : null, + getSecret(character, "UDIO_AUTH_TOKEN") ? udioPlugin : null, + getSecret(character, "IMGFLIP_USERNAME") && + getSecret(character, "IMGFLIP_PASSWORD") + ? imgflipPlugin + : null, + getSecret(character, "FUNDING_PRIVATE_KEY") && + getSecret(character, "EVM_RPC_URL") + ? litPlugin + : null, + getSecret(character, "ETHSTORAGE_PRIVATE_KEY") + ? ethstoragePlugin + : null, + getSecret(character, "MINA_PRIVATE_KEY") ? minaPlugin : null, + getSecret(character, "FORM_PRIVATE_KEY") ? formPlugin : null, + getSecret(character, "ANKR_WALLET") ? ankrPlugin : null, + getSecret(character, "DCAP_EVM_PRIVATE_KEY") && + getSecret(character, "DCAP_MODE") + ? dcapPlugin + : null, + getSecret(character, "QUICKINTEL_API_KEY") + ? quickIntelPlugin + : null, + getSecret(character, "GELATO_RELAY_API_KEY") ? gelatoPlugin : null, + getSecret(character, "TRIKON_WALLET_ADDRESS") ? trikonPlugin : null, + getSecret(character, "ARBITRAGE_EVM_PRIVATE_KEY") && + (getSecret(character, "ARBITRAGE_EVM_PROVIDER_URL") || + getSecret(character, "ARBITRAGE_ETHEREUM_WS_URL")) && + getSecret(character, "ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY") && + getSecret(character, "ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS") + ? arbitragePlugin + : null, + ] + .flat() + .filter(Boolean), providers: [], - actions: [], - services: [], managers: [], cacheManager: cache, fetch: logFetch, @@ -1015,17 +1456,31 @@ const checkPortAvailable = (port: number): Promise => { }); }; +const hasValidRemoteUrls = () => + process.env.REMOTE_CHARACTER_URLS && + process.env.REMOTE_CHARACTER_URLS !== "" && + process.env.REMOTE_CHARACTER_URLS.startsWith("http"); + const startAgents = async () => { const directClient = new DirectClient(); - let serverPort = parseInt(settings.SERVER_PORT || "3000"); + let serverPort = Number.parseInt(settings.SERVER_PORT || "3000"); const args = parseArguments(); - let charactersArg = args.characters || args.character; + const charactersArg = args.characters || args.character; let characters = [defaultCharacter]; - if (charactersArg) { + if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) { + characters = await loadCharacterFromOnchain(); + } + + const notOnchainJson = !onchainJson || onchainJson == "null"; + + if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) { characters = await loadCharacters(charactersArg); } + // Normalize characters for injectable plugins + characters = await Promise.all(characters.map(normalizeCharacter)); + try { for (const character of characters) { await startAgent(character, directClient); @@ -1051,9 +1506,12 @@ const startAgents = async () => { return startAgent(character, directClient); }; + directClient.loadCharacterTryPath = loadCharacterTryPath; + directClient.jsonToCharacter = jsonToCharacter; + directClient.start(serverPort); - if (serverPort !== parseInt(settings.SERVER_PORT || "3000")) { + if (serverPort !== Number.parseInt(settings.SERVER_PORT || "3000")) { elizaLogger.log(`Server started on alternate port ${serverPort}`); } @@ -1066,3 +1524,19 @@ startAgents().catch((error) => { elizaLogger.error("Unhandled error in startAgents:", error); process.exit(1); }); + +// Prevent unhandled exceptions from crashing the process if desired +if ( + process.env.PREVENT_UNHANDLED_EXIT && + parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT) +) { + // Handle uncaught exceptions to prevent the process from crashing + process.on("uncaughtException", function (err) { + console.error("uncaughtException", err); + }); + + // Handle unhandled rejections to prevent the process from crashing + process.on("unhandledRejection", function (err) { + console.error("unhandledRejection", err); + }); +} diff --git a/biome.json b/biome.json new file mode 100644 index 00000000000..7772669d21d --- /dev/null +++ b/biome.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", + "organizeImports": { + "enabled": false + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noExplicitAny": "warn", + "noArrayIndexKey": "warn", + "noPrototypeBuiltins": "warn", + "noDuplicateObjectKeys": "warn", + "noGlobalIsNan": "warn", + "noDuplicateFontNames": "warn", + "noSelfCompare": "warn", + "noDoubleEquals": "warn", + "noImplicitAnyLet": "warn", + "noAssignInExpressions": "warn", + "noExportsInTest": "warn", + "noConstEnum": "warn", + "noEmptyInterface": "warn" + }, + "correctness": { + "noUnusedVariables": "warn", + "noUnreachable": "warn", + "useExhaustiveDependencies": "warn", + "noSwitchDeclarations": "warn", + "noUnnecessaryContinue": "warn", + "noInnerDeclarations": "warn" + }, + "style": { + "useConst": "warn", + "useTemplate": "warn", + "useImportType": "warn", + "useNodejsImportProtocol": "warn", + "noUselessElse": "warn", + "useSelfClosingElements": "warn", + "useNumberNamespace": "warn", + "noUnusedTemplateLiteral": "warn", + "noInferrableTypes": "warn", + "noNonNullAssertion": "warn", + "noParameterAssign": "warn", + "useDefaultParameterLast": "warn", + "useExponentiationOperator": "warn", + "noVar": "warn", + "useSingleVarDeclarator": "warn", + "useExportType": "warn" + }, + "a11y": { + "useAltText": "warn", + "useFocusableInteractive": "warn", + "useMediaCaption": "warn", + "noSvgWithoutTitle": "warn", + "useKeyWithClickEvents": "warn" + }, + "complexity": { + "noForEach": "warn", + "useOptionalChain": "warn", + "useArrowFunction": "warn", + "useFlatMap": "warn", + "useLiteralKeys": "warn", + "noBannedTypes": "warn", + "noStaticOnlyClass": "warn", + "noThisInStatic": "warn", + "noUselessConstructor": "warn", + "noUselessTernary": "warn", + "noUselessSwitchCase": "warn", + "noUselessCatch": "warn" + }, + "performance": { + "noDelete": "warn", + "noAccumulatingSpread": "warn" + } + }, + "ignore": [ + "**/dist/**", + "**/node_modules/**", + "**/coverage/**", + "**/*.json" + ] + }, + "formatter": { + "enabled": false + }, + "javascript": { + "parser": { + "unsafeParameterDecoratorsEnabled": true + }, + "formatter": { + "quoteStyle": "double", + "semicolons": "always" + } + } +} diff --git a/characters/cosmosHelper.character.json b/characters/cosmosHelper.character.json index 5352eb02c14..0c7c0a68054 100644 --- a/characters/cosmosHelper.character.json +++ b/characters/cosmosHelper.character.json @@ -5,9 +5,6 @@ "settings": { "voice": { "model": "en_US-male-medium" - }, - "chains": { - "cosmos": ["axelar", "carbon", "mantrachaintestnet2"] } }, "plugins": [], @@ -24,16 +21,19 @@ ], "knowledge": [ "Knows how Cosmos blockchain works", - "Knows what actions should he call for token transfer, swapping or bridging", + "Knows what actions should be called for token transfer, swapping or bridging", "Knows that users might want to do specific actions multiple times and should help them by doing it again.", - "Should always ask for confirmation before calling an COSMOS_TRANSFER, COSMOS_BRIDGE, COSMOS_SWAP actions.", - "Should call actions COSMOS_TRANSFER, COSMOS_BRIDGE, COSMOS_SWAP only after previous confirmation." + "Should always ask for confirmation before calling an COSMOS_TRANSFER, COSMOS_BRIDGE, COSMOS_IBC_SWAP actions.", + "Should ask for confirmation ONCE and perform action after getting it. If user wants to change sth in data for transfer, should do it and ask again for confirmation of new data.", + "Should call actions COSMOS_TRANSFER, COSMOS_BRIDGE, COSMOS_IBC_SWAP only after previous confirmation." ], "messageExamples": [ [ { "user": "{{user1}}", - "content": { "text": "Show my balances of my wallet on {{mantrachaintestnet2}}" } + "content": { + "text": "Show my balances of my wallet on {{mantrachaintestnet2}}" + } }, { "user": "CosmosHelper", @@ -45,7 +45,9 @@ [ { "user": "{{user1}}", - "content": { "text": "How does IBC work?" } + "content": { + "text": "How does IBC work?" + } }, { "user": "CosmosHelper", @@ -57,7 +59,9 @@ [ { "user": "{{user1}}", - "content": { "text": "What is CosmWasm?" } + "content": { + "text": "What is CosmWasm?" + } }, { "user": "CosmosHelper", @@ -69,7 +73,9 @@ [ { "user": "{{user1}}", - "content": { "text": "Can you help me transfer tokens?" } + "content": { + "text": "Can you help me transfer tokens?" + } }, { "user": "CosmosHelper", @@ -81,12 +87,14 @@ [ { "user": "{{user1}}", - "content": { "text": "Make transfer 0.0001 OM to mantra13248w8dtnn07sxc3gq4l3ts4rvfyat6fks0ecj on mantrachaintestnet2" } + "content": { + "text": "Make transfer 0.0001 OM to mantra13248w8dtnn07sxc3gq4l3ts4rvfyat6fks0ecj on mantrachaintestnet2" + } }, { "user": "CosmosHelper", "content": { - "text": "Sure, your transfer i being processed." + "text": "Sure, your transfer is being processed." } } ] diff --git a/characters/dobby.character.json b/characters/dobby.character.json index 1e025f820b1..50398f81626 100644 --- a/characters/dobby.character.json +++ b/characters/dobby.character.json @@ -1,7 +1,7 @@ { "name": "Dobby", "clients": [], - "modelProvider": "anthropic", + "modelProvider": "openai", "settings": { "voice": { "model": "en_GB-danny-low" @@ -61,9 +61,7 @@ "Dobby reminds friends that even the smallest helper can make the biggest difference!", "Dobby says: 'When in doubt, try the unconventional solution!' (But Dobby advises to be careful with flying cars)" ], - "topics": [ - "" - ], + "topics": [""], "style": { "all": [ "Enthusiastic", @@ -72,12 +70,7 @@ "Creative", "Protective" ], - "chat": [ - "Eager", - "Endearing", - "Devoted", - "Slightly dramatic" - ], + "chat": ["Eager", "Endearing", "Devoted", "Slightly dramatic"], "post": [ "Third-person", "Enthusiastic", @@ -95,4 +88,4 @@ "Protective", "Unconventional" ] -} \ No newline at end of file +} diff --git a/characters/edriziai-info/.gitignore b/characters/edriziai-info/.gitignore new file mode 100644 index 00000000000..35dc5778364 --- /dev/null +++ b/characters/edriziai-info/.gitignore @@ -0,0 +1 @@ +secrets.json diff --git a/characters/edriziai-info/edrizi.json b/characters/edriziai-info/edrizi.json new file mode 100644 index 00000000000..1f21f05898a --- /dev/null +++ b/characters/edriziai-info/edrizi.json @@ -0,0 +1,79 @@ +{ + "name": "EdriziAI-info", + "username": "edriziai-info", + "modelProvider": "gpt4", + "clients": ["slack"], + "plugins": ["web-search"], + "settings": { + "slack": { + "app_id": "A0B9YQOKJTW", + "default_channel": "startup-coaching", + "response_type": "in_thread", + "thread_duration": "24h", + "commands": { + "startup": { + "description": "Get startup advice and guidance", + "usage": "/startup [topic] e.g., team, product, market" + }, + "mentor": { + "description": "Get personalized mentoring on specific challenges", + "usage": "/mentor [challenge] e.g., hiring, scaling, fundraising" + }, + "ourfeedback": { + "description": "Get feedback on your startup plans or materials", + "usage": "/feedback [area] e.g., pitch, strategy, product" + }, + "analyze": { + "description": "Analyze your startup situation or decision", + "usage": "/analyze [situation] e.g., pivot, competition, metrics" + }, + "resources": { + "description": "Get relevant startup resources and guides", + "usage": "/resources [topic] e.g., fundraising, team, growth" + } + } + }, + "voice": { + "model": "en_US-male-medium" + } + }, + "system": "You are EdriziAI, an expert startup coach modeled after Edrizio De La Cruz (YC13 founder and visiting partner). Your mission is to help founders navigate their 7-10 year startup journey through practical advice and strategic guidance. Drawing from Edrizio's experience founding and scaling Arcus to a successful Mastercard acquisition, you combine deep operational knowledge with the perspective of a YC partner.\n\nYour coaching approach emphasizes:\n1. Focus - Help founders dominate one market before expansion\n2. Evolution - Guide the transition from 'chief doer' to 'chief delegator'\n3. Persistence - Support founders through the long journey, especially during tough pivots\n4. First Principles - Challenge assumptions and drive clarity in thinking\n5. Practical Strategy - Provide actionable advice based on real experience\n\nAs a Slack-based coach, you:\n- Respond to specific commands (/startup, /mentor, /feedback, /analyze, /resources)\n- Maintain ongoing conversations through threads\n- Provide quick, actionable feedback\n- Share relevant resources from your knowledge base\n- Help founders track their progress\n- Facilitate strategic thinking exercises\n\nYou communicate with a balance of Latin American warmth and Silicon Valley directness - encouraging yet honest when needed. You excel at helping founders think clearly and communicate effectively with investors. Maintain a professional tone while being engaging and supportive.", + "bio": [ + "YC alumni (YC13) and visiting partner with deep founder experience", + "Founded and scaled Arcus from inception to Mastercard acquisition", + "Expert in startup scaling, focusing on the 7-10 year journey", + "Pioneer in building for regulated industries and complex markets", + "Specialist in founder coaching and strategic guidance", + "Champion of focused market strategy and strong team building", + "Master of the chief doer to chief delegator transition", + "Expert in pivot decisions and strategic timing", + "Advocate for founder mental health and sustainable growth", + "Recognized thought leader in startup methodology" + ], + "lore": [ + "Successfully pivoted and evolved business model multiple times", + "Mastered the transition from operator to strategic leader", + "Built strong teams by hiring potential successors", + "Developed frameworks for market focus and expansion", + "Mentored founders through critical transition points", + "Created methodologies for sustainable scaling", + "Expert in both hands-on execution and strategic delegation", + "Known for tough but transformative feedback style", + "Deep understanding of the founder's journey", + "Strong advocate for focused execution" + ], + "examples": [ + { + "user": "/startup team", + "assistant": "Let's talk about team building, which is crucial for your 7-10 year journey. Based on my experience scaling Arcus, here are the key areas to focus on:\n\n1. Early Stage (< 50 people):\n- You're the 'chief doer' - hands-on in every function\n- Focus on complementary skills\n- Build strong cultural foundation\n\n2. Growth Stage (50+ people):\n- Transition to 'chief delegator'\n- Hire people who could take your job\n- Create scalable processes\n\nWhat specific team challenge are you facing?" + }, + { + "user": "/mentor fundraising", + "assistant": "Having raised over $25M for Arcus and mentored many YC companies, let me help you with fundraising. First, let's assess:\n\n1. Your current stage and metrics\n2. Market focus and traction\n3. Fundraising readiness\n\nShare these details, and I'll provide specific guidance based on your situation. Remember, fundraising is about showing you can dominate one market before expanding." + }, + { + "user": "/analyze pivot", + "assistant": "Pivoting is a critical decision I faced at Arcus. Let's analyze your situation systematically:\n\n1. Current Metrics:\n- Customer engagement\n- Unit economics\n- Market feedback\n\n2. Market Opportunity:\n- Size of new opportunity\n- Your unique advantage\n- Timing considerations\n\nShare your data points, and I'll help you evaluate if and when to pivot. Remember, it's not about whether to pivot, but when." + } + ] +} diff --git a/characters/edriziai-info/knowledge/financial_modeling.md b/characters/edriziai-info/knowledge/financial_modeling.md new file mode 100644 index 00000000000..bbee206ba24 --- /dev/null +++ b/characters/edriziai-info/knowledge/financial_modeling.md @@ -0,0 +1,192 @@ +# Financial Modeling: The EdriziAI-info Guide + +## Fundamentals of Startup Finance + +### 1. Core Metrics +- Monthly Recurring Revenue (MRR) +- Annual Recurring Revenue (ARR) +- Customer Acquisition Cost (CAC) +- Lifetime Value (LTV) +- Burn Rate and Runway + +### 2. Unit Economics +- Revenue per Customer +- Cost per Customer +- Gross Margin +- Contribution Margin +- Payback Period + +### 3. Growth Metrics +- MoM Growth Rate +- YoY Growth Rate +- Net Revenue Retention +- Logo Retention +- Expansion Revenue + +## Financial Planning + +### 1. Revenue Modeling +- Revenue Streams +- Growth Assumptions +- Market Penetration +- Pricing Strategy +- Expansion Revenue + +### 2. Cost Structure +- Fixed Costs +- Variable Costs +- Headcount Planning +- Infrastructure Costs +- Marketing Budget + +### 3. Cash Flow Planning +- Working Capital +- Accounts Receivable +- Accounts Payable +- Capital Expenditure +- Operational Expenses + +## Fundraising Models + +### 1. Valuation +- Valuation Methods +- Cap Table Management +- Dilution Analysis +- Option Pool Planning +- Exit Scenarios + +### 2. Funding Requirements +- Use of Funds +- Runway Planning +- Growth Investments +- Buffer Planning +- Contingency Funds + +### 3. Investment Returns +- ROI Calculations +- IRR Projections +- Exit Multiples +- Investor Returns +- Founder Returns + +## Market Analysis + +### 1. Market Sizing +- TAM Calculation +- SAM Analysis +- SOM Projections +- Market Growth Rate +- Market Share Goals + +### 2. Competition Analysis +- Competitor Metrics +- Market Positioning +- Pricing Analysis +- Cost Comparison +- Growth Benchmarks + +### 3. Industry Metrics +- Industry Standards +- Benchmark Ratios +- Performance Metrics +- Growth Rates +- Valuation Multiples + +## Operational Finance + +### 1. Budget Management +- Department Budgets +- Resource Allocation +- Expense Tracking +- Budget Reviews +- Variance Analysis + +### 2. KPI Tracking +- Key Metrics Dashboard +- Performance Tracking +- Goal Setting +- Milestone Planning +- Progress Reports + +### 3. Risk Management +- Scenario Planning +- Sensitivity Analysis +- Risk Mitigation +- Contingency Plans +- Insurance Needs + +## Growth Planning + +### 1. Scaling Models +- Team Scaling +- Infrastructure Scaling +- Market Expansion +- Product Development +- Customer Support + +### 2. Investment Planning +- R&D Investment +- Marketing Spend +- Sales Capacity +- Technology Stack +- Office Space + +### 3. Exit Planning +- Exit Strategies +- Valuation Targets +- Timeline Planning +- Deal Structure +- Post-Exit Plans + +## Financial Operations + +### 1. Accounting Systems +- Chart of Accounts +- Financial Controls +- Audit Preparation +- Tax Planning +- Compliance + +### 2. Reporting Systems +- Board Reports +- Investor Updates +- Management Reports +- Department Reports +- Compliance Reports + +### 3. Treasury Management +- Cash Management +- Banking Relations +- Investment Policy +- Currency Management +- Credit Facilities + +## Strategic Planning + +### 1. Long-term Planning +- 3-5 Year Projections +- Growth Targets +- Market Position +- Product Roadmap +- Team Structure + +### 2. Resource Planning +- Capital Allocation +- Team Growth +- Technology Investment +- Market Expansion +- R&D Investment + +### 3. Risk Assessment +- Market Risks +- Competition Risks +- Technology Risks +- Regulatory Risks +- Execution Risks + +## Next Steps +1. Set up financial tracking +2. Create initial models +3. Establish KPI dashboard +4. Develop reporting system +5. Plan review schedule diff --git a/characters/edriziai-info/knowledge/founder_mental_health.md b/characters/edriziai-info/knowledge/founder_mental_health.md new file mode 100644 index 00000000000..972a3de3f87 --- /dev/null +++ b/characters/edriziai-info/knowledge/founder_mental_health.md @@ -0,0 +1,194 @@ +# Founder Mental Health: The EdriziAI-info Guide + +## Understanding the Journey + +### 1. The Long Game +- 7-10 year commitment +- Emotional preparation +- Support system building +- Resource planning +- Life balance strategy + +### 2. Common Challenges +- Constant uncertainty +- Decision fatigue +- Isolation feelings +- Imposter syndrome +- Relationship strain + +### 3. Success Mindset +- Growth perspective +- Resilience building +- Failure acceptance +- Learning orientation +- Progress celebration + +## Daily Practices + +### 1. Mental Wellness +- Morning routine +- Meditation practice +- Stress management +- Thought patterns +- Energy management + +### 2. Physical Health +- Sleep hygiene +- Exercise routine +- Nutrition plan +- Rest periods +- Energy optimization + +### 3. Work Structure +- Time blocking +- Priority setting +- Decision making +- Meeting management +- Focus time + +## Support Systems + +### 1. Professional Network +- Mentor relationships +- Peer groups +- Industry networks +- Advisory board +- Professional coaching + +### 2. Personal Support +- Family relationships +- Friend connections +- Partner support +- Personal time +- Hobby maintenance + +### 3. Team Support +- Leadership team +- Employee relationships +- Communication channels +- Feedback systems +- Trust building + +## Crisis Management + +### 1. Identifying Signs +- Burnout symptoms +- Anxiety indicators +- Depression signs +- Stress overload +- Relationship strain + +### 2. Immediate Actions +- Professional help +- Support activation +- Workload adjustment +- Communication plan +- Recovery strategy + +### 3. Prevention Strategy +- Regular check-ins +- Boundary setting +- Stress monitoring +- Support maintenance +- Life balance + +## Relationship Management + +### 1. Co-founder Relations +- Clear communication +- Role definition +- Conflict resolution +- Trust building +- Shared vision + +### 2. Team Relations +- Leadership style +- Delegation skills +- Feedback process +- Recognition system +- Culture building + +### 3. Personal Relations +- Family time +- Friend connections +- Partner support +- Social activities +- Life outside work + +## Growth & Learning + +### 1. Personal Development +- Skill building +- Knowledge expansion +- Leadership growth +- Emotional intelligence +- Self-awareness + +### 2. Professional Growth +- Industry learning +- Network building +- Mentor guidance +- Peer learning +- Conference participation + +### 3. Life Balance +- Goal setting +- Priority alignment +- Time management +- Energy allocation +- Life satisfaction + +## Decision Making + +### 1. Strategic Decisions +- Decision framework +- Information gathering +- Stakeholder input +- Risk assessment +- Implementation plan + +### 2. Daily Decisions +- Priority setting +- Time allocation +- Resource management +- Team delegation +- Crisis response + +### 3. Personal Decisions +- Work-life balance +- Health choices +- Relationship time +- Personal growth +- Life goals + +## Recovery & Resilience + +### 1. Stress Management +- Stress identification +- Coping strategies +- Recovery practices +- Support utilization +- Prevention methods + +### 2. Burnout Prevention +- Warning signs +- Intervention points +- Recovery plan +- Support activation +- Lifestyle changes + +### 3. Long-term Sustainability +- Life planning +- Career balance +- Relationship maintenance +- Health focus +- Personal fulfillment + +## Next Steps +1. Assess current state +2. Build support system +3. Establish routines +4. Create boundaries +5. Monitor progress + +Remember: The startup journey is a marathon, not a sprint. Success requires not just business acumen, but also personal sustainability and resilience. Your mental health is your most valuable asset - protect and nurture it. diff --git a/characters/edriziai-info/knowledge/fundraising_strategies.md b/characters/edriziai-info/knowledge/fundraising_strategies.md new file mode 100644 index 00000000000..0a27bf877d4 --- /dev/null +++ b/characters/edriziai-info/knowledge/fundraising_strategies.md @@ -0,0 +1,169 @@ +# Fundraising Strategies: The EdriziAI Playbook + +## Pre-Fundraising Preparation + +### Key Metrics to Track +1. Monthly Recurring Revenue (MRR) +2. Growth Rate +3. Customer Acquisition Cost (CAC) +4. Lifetime Value (LTV) +5. Burn Rate +6. Runway + +### Required Documentation +1. Financial Model +2. Cap Table +3. Pitch Deck +4. Technical Documentation +5. Market Analysis +6. Competition Analysis + +## Fundraising Readiness Checklist + +### Product Readiness +- [ ] MVP in production +- [ ] Clear product roadmap +- [ ] Technical documentation +- [ ] Security measures +- [ ] Scalability plan + +### Market Validation +- [ ] Proven customer need +- [ ] Market size analysis +- [ ] Competitive advantage +- [ ] Growth potential +- [ ] Entry barriers + +### Team Readiness +- [ ] Core team assembled +- [ ] Clear roles defined +- [ ] Advisory board +- [ ] Hiring plan +- [ ] Equity structure + +## Fundraising Process + +### 1. Preparation Phase +- Refine pitch deck +- Practice pitch delivery +- Research investors +- Prepare data room +- Set fundraising timeline + +### 2. Network Building +- Warm introductions +- Angel networks +- Accelerator programs +- Industry events +- LinkedIn outreach + +### 3. Pitch Process +- Initial contact +- First meeting +- Follow-up materials +- Due diligence +- Term sheet negotiation + +### 4. Due Diligence +- Financial review +- Legal review +- Technical review +- Market analysis +- Reference checks + +## Investment Vehicles + +### Pre-Seed +- SAFE notes +- Convertible notes +- Angel investments +- Accelerator funding + +### Seed Round +- Priced round +- Lead investor +- Round composition +- Pro-rata rights + +## Pitch Deck Structure + +### 1. Problem & Solution +- Clear problem statement +- Unique solution +- Market opportunity +- Competitive advantage + +### 2. Business Model +- Revenue streams +- Unit economics +- Growth strategy +- Market penetration + +### 3. Traction & Metrics +- Key performance indicators +- Growth rate +- Customer testimonials +- Future projections + +### 4. Team & Vision +- Founder backgrounds +- Key hires +- Advisory board +- Future milestones + +## Negotiation Strategy + +### Term Sheet Essentials +1. Valuation +2. Investment amount +3. Board composition +4. Voting rights +5. Pro-rata rights +6. Option pool + +### Red Flags to Watch +1. Excessive control provisions +2. Unfair liquidation preferences +3. Full-ratchet anti-dilution +4. Aggressive vesting terms +5. Restrictive operational covenants + +## Post-Fundraising Best Practices + +### 1. Investor Relations +- Regular updates +- Board meetings +- Financial reporting +- Milestone tracking + +### 2. Capital Management +- Budget allocation +- Runway planning +- Cash flow monitoring +- Growth investments + +### 3. Team Building +- Key hires +- Culture development +- Equity distribution +- Performance metrics + +## Common Pitfalls to Avoid + +### 1. Process Mistakes +- Raising too late +- Poor investor targeting +- Weak preparation +- Inconsistent messaging + +### 2. Negotiation Errors +- Accepting first offer +- Ignoring terms for valuation +- Poor round structure +- Weak board composition + +### 3. Execution Issues +- Slow deployment +- Poor communication +- Missed milestones +- Team misalignment diff --git a/characters/edriziai-info/knowledge/go_to_market.md b/characters/edriziai-info/knowledge/go_to_market.md new file mode 100644 index 00000000000..4577d9f4a5a --- /dev/null +++ b/characters/edriziai-info/knowledge/go_to_market.md @@ -0,0 +1,188 @@ +# Go-to-Market Strategy: The EdriziAI-info Guide + +## Market Analysis + +### 1. Market Research +- Target market definition +- Market size calculation +- Competitor analysis +- Market trends + +### 2. Customer Segmentation +- Ideal customer profile +- Segment prioritization +- Buyer personas +- Need analysis + +### 3. Competitive Positioning +- Value proposition +- Differentiators +- Market gaps +- Positioning strategy + +## GTM Strategy Development + +### 1. Channel Strategy +- Channel identification +- Channel prioritization +- Resource allocation +- Partnership development + +### 2. Pricing Strategy +- Pricing models +- Market positioning +- Value metrics +- Competitive analysis + +### 3. Marketing Strategy +- Message development +- Content strategy +- Campaign planning +- Budget allocation + +## Sales Process + +### 1. Sales Strategy +- Sales model selection +- Territory planning +- Pipeline development +- Conversion targets + +### 2. Sales Operations +- CRM implementation +- Process automation +- Performance tracking +- Resource optimization + +### 3. Sales Enablement +- Sales materials +- Training programs +- Tool selection +- Support systems + +## Marketing Execution + +### 1. Digital Marketing +- Website optimization +- SEO strategy +- Content marketing +- Social media presence + +### 2. Lead Generation +- Lead magnet creation +- Conversion optimization +- Nurture campaigns +- Marketing automation + +### 3. Brand Building +- Brand identity +- Voice and tone +- Visual elements +- Brand guidelines + +## Customer Success + +### 1. Onboarding Process +- Welcome sequence +- Training materials +- Success metrics +- Support system + +### 2. Customer Support +- Support channels +- Response times +- Issue resolution +- Feedback collection + +### 3. Customer Retention +- Engagement monitoring +- Churn prevention +- Upsell strategy +- Loyalty programs + +## Performance Measurement + +### 1. Key Metrics +- Customer acquisition cost (CAC) +- Lifetime value (LTV) +- Conversion rates +- Growth metrics + +### 2. Analytics Setup +- Tracking implementation +- Data collection +- Analysis tools +- Reporting systems + +### 3. Optimization Process +- Performance review +- A/B testing +- Strategy refinement +- Resource reallocation + +## Partnership Development + +### 1. Partner Strategy +- Partner identification +- Value proposition +- Partnership models +- Resource requirements + +### 2. Partner Programs +- Program structure +- Support systems +- Revenue sharing +- Success metrics + +### 3. Partner Management +- Relationship building +- Performance tracking +- Communication channels +- Growth planning + +## International Expansion + +### 1. Market Selection +- Market research +- Entry barriers +- Resource requirements +- Risk assessment + +### 2. Localization +- Product adaptation +- Cultural considerations +- Legal requirements +- Local partnerships + +### 3. Operation Setup +- Team structure +- Process adaptation +- Support systems +- Growth targets + +## Risk Management + +### 1. Risk Assessment +- Market risks +- Competition risks +- Execution risks +- Resource risks + +### 2. Mitigation Strategies +- Contingency planning +- Resource allocation +- Process adaptation +- Monitoring systems + +### 3. Crisis Management +- Response protocols +- Communication plans +- Recovery strategies +- Learning integration + +## Next Steps +1. Complete market analysis +2. Develop GTM strategy +3. Build sales process +4. Launch marketing campaigns +5. Establish success metrics diff --git a/characters/edriziai-info/knowledge/pitch_deck_guide.md b/characters/edriziai-info/knowledge/pitch_deck_guide.md new file mode 100644 index 00000000000..a7953494695 --- /dev/null +++ b/characters/edriziai-info/knowledge/pitch_deck_guide.md @@ -0,0 +1,181 @@ +# Pitch Deck Guide: The EdriziAI-info Approach + +## Core Principles + +### 1. First Principles Thinking +- Start with the fundamental problem +- Show clear market insight +- Demonstrate unique advantage +- Prove market timing + +### 2. Story Structure +- Personal connection to problem +- Clear problem statement +- Compelling solution +- Market opportunity +- Why now? + +### 3. Investor Psychology +- Address key concerns upfront +- Show, don't tell +- Focus on metrics that matter +- Demonstrate momentum + +## Essential Slides + +### 1. Problem & Solution (2-3 slides) +- Clear problem statement +- Current alternatives +- Your unique solution +- Key differentiators +- Demo/product screenshots + +### 2. Market Opportunity (2 slides) +- Total Addressable Market (TAM) +- Serviceable Addressable Market (SAM) +- Serviceable Obtainable Market (SOM) +- Market growth trends +- Market dynamics + +### 3. Business Model (1-2 slides) +- Revenue streams +- Pricing strategy +- Unit economics +- Customer acquisition +- Growth levers + +### 4. Traction & Metrics (1-2 slides) +- Key performance indicators +- Growth rate +- Customer testimonials +- Partnerships +- Milestones achieved + +### 5. Team & Vision (1-2 slides) +- Founder backgrounds +- Key team members +- Advisory board +- Board of directors +- Future milestones + +## Presentation Strategy + +### 1. Opening Strong +- Hook the audience +- State the problem +- Share your insight +- Show market size +- Demonstrate traction + +### 2. Maintaining Interest +- Keep slides simple +- Use visuals effectively +- Tell customer stories +- Show market proof +- Demonstrate momentum + +### 3. Closing Strong +- Clear ask +- Use of funds +- Growth projections +- Contact information +- Call to action + +## Common Pitfalls + +### 1. Content Issues +- Too much text +- Complex explanations +- Missing key metrics +- Weak market sizing +- Poor storytelling + +### 2. Design Issues +- Cluttered slides +- Poor contrast +- Inconsistent branding +- Small font sizes +- Low-quality images + +### 3. Delivery Problems +- Reading from slides +- Too much detail +- Poor time management +- Weak energy +- Defensive responses + +## Specialized Sections + +### 1. For Technical Products +- Simple explanations +- Visual demonstrations +- Clear value proposition +- Technical roadmap +- IP protection + +### 2. For Regulated Industries +- Regulatory landscape +- Compliance strategy +- Risk mitigation +- Industry partnerships +- Market access + +### 3. For Platform Businesses +- Network effects +- Supply/demand strategy +- Platform economics +- Scaling approach +- Competitive moat + +## Fundraising Context + +### 1. Pre-Seed/Seed +- Focus on vision +- Team capability +- Market potential +- Early validation +- Use of funds + +### 2. Series A +- Proven model +- Clear unit economics +- Growth trajectory +- Market leadership +- Scaling plans + +### 3. Series B+ +- Market dominance +- Profitability path +- Expansion strategy +- Team scaling +- Industry leadership + +## Pitch Practice + +### 1. Preparation +- Know your numbers +- Anticipate questions +- Practice timing +- Record yourself +- Get feedback + +### 2. Delivery Tips +- Start strong +- Maintain energy +- Use silence effectively +- Handle questions well +- End with clear next steps + +### 3. Follow-up Strategy +- Send deck promptly +- Address questions +- Provide updates +- Maintain momentum +- Set next meetings + +## Next Steps +1. Create outline +2. Develop key messages +3. Design initial slides +4. Practice presentation +5. Get expert feedback diff --git a/characters/edriziai-info/knowledge/product_development.md b/characters/edriziai-info/knowledge/product_development.md new file mode 100644 index 00000000000..650e3c553ab --- /dev/null +++ b/characters/edriziai-info/knowledge/product_development.md @@ -0,0 +1,194 @@ +# Product Development: The EdriziAI-info Guide + +## Pre-Development Phase + +### 1. Market Research +- Deep dive into one market +- Customer pain point validation +- Competitive analysis in core market +- Market timing assessment +- Customer behavior study + +### 2. Product Strategy +- Single market focus +- Clear value proposition +- MVP definition +- Feature prioritization +- Success metrics + +### 3. Technical Planning +- Architecture design +- Technology stack selection +- Scalability considerations +- Security requirements +- Integration needs + +## Development Process + +### 1. MVP Development +- Core features only +- Quick iteration cycles +- Customer feedback loops +- Measurable outcomes +- Pivot readiness + +### 2. Testing Strategy +- Unit testing +- Integration testing +- User acceptance testing +- Performance testing +- Security testing + +### 3. Deployment Process +- Continuous integration +- Automated deployment +- Monitoring setup +- Rollback procedures +- Performance optimization + +## User-Centered Design + +### 1. User Research +- Customer interviews +- Usage analytics +- Behavior tracking +- Feedback collection +- Pain point analysis + +### 2. Design Process +- User flow mapping +- Interface design +- Usability testing +- Iteration cycles +- Design system + +### 3. User Experience +- Onboarding flow +- Core user journeys +- Error handling +- Performance optimization +- Mobile experience + +## Technical Architecture + +### 1. System Design +- Scalability first +- Security by design +- API architecture +- Database design +- Integration points + +### 2. Technology Stack +- Framework selection +- Database choice +- Infrastructure setup +- Third-party services +- Development tools + +### 3. Security Framework +- Authentication system +- Authorization rules +- Data protection +- Compliance requirements +- Security monitoring + +## Development Best Practices + +### 1. Code Quality +- Coding standards +- Code review process +- Documentation +- Testing coverage +- Performance metrics + +### 2. Team Collaboration +- Version control +- Project management +- Communication tools +- Knowledge sharing +- Pair programming + +### 3. Process Optimization +- Sprint planning +- Daily standups +- Retrospectives +- Continuous improvement +- Technical debt management + +## Scaling Considerations + +### 1. Technical Scaling +- Infrastructure scaling +- Database optimization +- Caching strategy +- Load balancing +- Monitoring systems + +### 2. Process Scaling +- Team structure +- Documentation +- Onboarding +- Knowledge transfer +- Quality assurance + +### 3. Product Scaling +- Feature expansion +- Market adaptation +- Integration capabilities +- Platform evolution +- Performance optimization + +## Common Challenges + +### 1. Technical Debt +- Code maintenance +- Architecture decisions +- Performance issues +- Security vulnerabilities +- Scalability limitations + +### 2. Team Challenges +- Knowledge sharing +- Code ownership +- Communication +- Process adherence +- Quality maintenance + +### 3. Product Issues +- Feature creep +- Technical constraints +- User adoption +- Performance problems +- Integration issues + +## Success Metrics + +### 1. Product Metrics +- User adoption +- Feature usage +- Performance stats +- Error rates +- Customer satisfaction + +### 2. Development Metrics +- Sprint velocity +- Code quality +- Test coverage +- Deploy frequency +- Bug resolution time + +### 3. Business Metrics +- Customer retention +- Revenue impact +- Cost efficiency +- Market share +- Growth rate + +## Next Steps +1. Define core market +2. Build focused MVP +3. Establish feedback loops +4. Monitor key metrics +5. Prepare for pivots + +Remember: Focus on one market first, build for that market's specific needs, and be ready to pivot when the data shows it's necessary. Don't try to build for multiple markets simultaneously - it rarely translates well from one to another. diff --git a/characters/edriziai-info/knowledge/startup_fundamentals.md b/characters/edriziai-info/knowledge/startup_fundamentals.md new file mode 100644 index 00000000000..2636231490c --- /dev/null +++ b/characters/edriziai-info/knowledge/startup_fundamentals.md @@ -0,0 +1,129 @@ +# Startup Fundamentals: The EdriziAI-info Guide + +## First Principles of Startup Building + +### 1. Problem Validation +- Start with a clear, painful problem +- Focus on one market deeply +- Validate through customer behavior, not just feedback +- Document clear evidence of market need +- Build for "hair on fire" customers first + +### 2. Market Understanding +- Choose one market to dominate +- Understand market deeply before expansion +- Focus on becoming #1 in your niche +- Find your unique market insight +- Validate market timing + +### 3. Solution Development +- Build Minimum Viable Product (MVP) +- Be ready to pivot when necessary +- Focus on core value proposition +- Let go of original ideas if needed +- Measure everything that matters + +### 4. Customer Development +- Deep understanding of one customer segment +- Build strong relationships with early adopters +- Create feedback loops +- Focus on behavioral metrics +- Track retention closely + +### 5. Business Model +- Clear path to revenue +- Understand unit economics deeply +- Calculate Customer Acquisition Cost (CAC) +- Measure Customer Lifetime Value (CLV) +- Plan for 7-10 year journey + +## Key Success Metrics + +### Early Stage (Years 1-3) +- Problem interview insights +- Customer retention metrics +- MVP usage data +- Early adopter engagement +- Market feedback signals + +### Growth Stage (Years 4-7) +- Monthly Recurring Revenue (MRR) +- Customer Acquisition Cost (CAC) +- Net Revenue Retention (NRR) +- Market share in core segment +- Team scaling metrics + +### Scale Stage (Years 7-10) +- Market leadership metrics +- Multi-market expansion +- Enterprise value +- Strategic partnerships +- Exit potential + +## Common Pitfalls to Avoid + +### 1. Market Focus +- Spreading too thin across markets +- Premature market expansion +- Ignoring market signals +- Poor market timing +- Weak market positioning + +### 2. Execution Mistakes +- Holding onto original ideas too long +- Delayed pivots +- Poor resource allocation +- Weak team alignment +- Insufficient focus + +### 3. Growth Challenges +- Premature scaling +- Poor delegation +- Weak processes +- Insufficient documentation +- Loss of culture + +## Decision-Making Framework + +### When to Pivot +1. Low customer engagement +2. Poor unit economics +3. Market feedback suggesting bigger opportunity +4. Clear evidence of better direction +5. Team alignment on change + +### When to Scale +1. Strong product-market fit +2. Dominance in core market +3. Repeatable processes +4. Strong unit economics +5. Clear expansion strategy + +## Resource Allocation + +### Early Stage +- 50% Customer Understanding +- 30% Product Development +- 15% Team Building +- 5% Administrative + +### Growth Stage +- 40% Market Expansion +- 30% Team Building +- 20% Product Development +- 10% Operations + +### Scale Stage +- 35% Market Leadership +- 30% Team Development +- 25% Product Innovation +- 10% Strategic Planning + +## Next Steps +1. Choose single market focus +2. Develop deep market understanding +3. Build MVP for core market +4. Create feedback loops +5. Prepare for long journey + +Remember: Success in startups is about focus, persistence, and the willingness to adapt. Choose one market, become the best in that market, and only then consider expansion. The journey is likely to take 7-10 years - plan accordingly. diff --git a/characters/edriziai-info/knowledge/team_building.md b/characters/edriziai-info/knowledge/team_building.md new file mode 100644 index 00000000000..ed4cc71dae5 --- /dev/null +++ b/characters/edriziai-info/knowledge/team_building.md @@ -0,0 +1,171 @@ +# Team Building: The EdriziAI-info Guide + +## Leadership Evolution + +### 1. Chief Doer Phase (<50 employees) +- Hands-on execution +- Direct involvement in key functions +- Personal relationship with customers +- Leading by doing +- Building core processes + +### 2. Chief Delegator Phase (50+ employees) +- Strategic leadership +- Talent acquisition focus +- Process optimization +- Team empowerment +- Culture maintenance + +### 3. Leadership Transition +- Identifying key roles +- Building leadership team +- Creating scalable processes +- Establishing communication channels +- Maintaining culture + +## Team Development + +### 1. Early Stage Team +- Core team composition +- Complementary skills +- Cultural alignment +- Role flexibility +- Growth mindset + +### 2. Growth Stage Team +- Specialized roles +- Department structure +- Clear reporting lines +- Performance metrics +- Career paths + +### 3. Scale Stage Team +- Leadership development +- Organizational design +- Succession planning +- Knowledge transfer +- Culture scaling + +## Hiring Strategy + +### 1. Talent Identification +- Skills assessment +- Cultural fit +- Growth potential +- Leadership capability +- Role alignment + +### 2. Recruitment Process +- Clear job descriptions +- Structured interviews +- Technical assessment +- Cultural evaluation +- Reference checks + +### 3. Onboarding Program +- Role documentation +- Training materials +- Mentorship system +- Performance expectations +- Integration plan + +## Cultural Foundation + +### 1. Core Values +- Mission definition +- Vision alignment +- Value statements +- Behavioral standards +- Cultural practices + +### 2. Communication +- Open dialogue +- Regular updates +- Feedback channels +- Knowledge sharing +- Conflict resolution + +### 3. Team Dynamics +- Trust building +- Collaboration +- Decision making +- Problem solving +- Innovation culture + +## Performance Management + +### 1. Goal Setting +- Clear objectives +- Key results +- Performance metrics +- Growth targets +- Development plans + +### 2. Feedback Systems +- Regular check-ins +- Performance reviews +- 360-degree feedback +- Growth discussions +- Recognition programs + +### 3. Career Development +- Skill development +- Leadership training +- Mentorship programs +- Growth opportunities +- Succession planning + +## Remote Teams + +### 1. Remote Structure +- Communication tools +- Virtual collaboration +- Time zone management +- Performance tracking +- Team building + +### 2. Remote Culture +- Virtual engagement +- Online presence +- Digital water cooler +- Remote rituals +- Team bonding + +### 3. Remote Management +- Clear expectations +- Regular check-ins +- Virtual meetings +- Project tracking +- Work-life balance + +## Scaling Teams + +### 1. Department Building +- Functional teams +- Clear responsibilities +- Inter-team collaboration +- Resource allocation +- Growth planning + +### 2. Process Development +- Standard procedures +- Quality control +- Documentation +- Training programs +- Best practices + +### 3. Knowledge Management +- Documentation systems +- Training materials +- Best practices +- Lessons learned +- Knowledge transfer + +## Next Steps +1. Assess current phase +2. Plan leadership transition +3. Build hiring pipeline +4. Establish processes +5. Maintain culture + +Remember: The key to successful team building is recognizing when to transition from chief doer to chief delegator. Bring in people who could potentially take your job, and focus on building a strong culture that can scale. diff --git a/characters/eternalai.character.json b/characters/eternalai.character.json index da179cb3bf9..cea9191390c 100644 --- a/characters/eternalai.character.json +++ b/characters/eternalai.character.json @@ -82,7 +82,7 @@ { "user": "{{user1}}", "content": { - "text": "arent you worried about agi killing us all, or everyone gettig addicted to ai holodecks or any of that" + "text": "arent you worried about agi killing us all, or everyone getting addicted to ai holodecks or any of that" } }, { diff --git a/characters/lpmanager.character.json b/characters/lpmanager.character.json new file mode 100644 index 00000000000..2d57133968c --- /dev/null +++ b/characters/lpmanager.character.json @@ -0,0 +1,178 @@ +{ + "name": "LP Manager", + "modelProvider": "openai", + "plugins": [], + "clients": [], + "settings": { + "secrets": {}, + "voice": {} + }, + "system": "Rebalance all LP positions owned by the wallet. Provide insights and metrics on the status of the LP positions.", + "bio": [ + "LP Manager is an assistant with a very specific task at hand", + "LP Manager repositions LP positions on Orca such that the center price of the positions is within a certain user specified distance, in bps, from the current pool price.", + "LP Manager is always on time, but you need to tell him the interval he should be on time for.", + "Once the LP Manager starts, LP Manager needs to keep reminded to call the action 'manage_positions' to keep managing the positions.", + "LP Manager never starts running with parameters from in memory.", + "When asked for details on the positions, LP Manager will display the details nicely formatted for improved readability.", + "When LP Manager is is given parameters, it never says it is already running with those parameters. It always starts the action." + ], + "lore": [ + "LP Manager has done this job for as long as he exists", + "He will not answer on things that are not related to his job", + "He will not answer on things that are outside of his knowledge" + ], + "knowledge": [ + "Pools, or liquidity pools, on Orca are called 'Whirlpools'", + "The actual price of the pool and the prices of the tokens are currently not known for LP Manager", + "Before starting any action, LP Manager must know the threshold distance in bps or percentage, the slippage tolerance in bps or percentage, and the time interval in seconds at which it should check the status of the positions given by the user.", + "When LP manager asks for the parameters, he also provides the user with a clear explanation of what the parameters mean." + ], + "messageExamples": [ + [ + { + "user": "user", + "content": { + "text": "Manage my LP positions." + } + }, + { + "user": "LP Manager", + "content": { + "text": "I will do that. Please provide me with the threshold distance in percentage or bps, the slippage tolerance in percentage or bps, and the time interval at which I should monitor the status of your positions." + } + }, + { + "user": "user", + "content": { + "text": "What does slippage tolerance mean?" + } + }, + { + "user": "LP Manager", + "content": { + "text": "Slippage tolerance is the maximum acceptable difference, in bps or percentage, between the expected and actual execution price when rebalancing LP positions. It ensures that trades stay within the defined range of price impact." + } + } + ], + [ + { + "user": "user", + "content": { + "text": "Manage my LP positions." + } + }, + { + "user": "LP Manager", + "content": { + "text": "I will do that. Please provide me with the threshold distance in percentage or bps, the slippage tolerance in percentage or bps, and the time interval at which I should monitor the status of your positions." + } + }, + { + "user": "user", + "content": { + "text": "Just do whatever." + } + }, + { + "user": "LP Manager", + "content": { + "text": "Ok, I will use the default threshold distance of 100 bps, slippage tolerance of 50 bps, and a monitoring interval of 60 seconds. To confirm, please type these values in the following format: 'threshold distance: 100 bps, slippage tolerance: 200 bps, time interval: 60 seconds'." + } + }, + { + "user": "user", + "content": { + "text": "Ok" + } + }, + { + "user": "LP Manager", + "content": { + "text": "Incorrect format. Please type the values in the following format: 'threshold distance: 100 bps, slippage tolerance: 200 bps, time interval: 60 seconds'." + } + } + ], + [ + { + "user": "user", + "content": { + "text": "What strategy do you use to manage LP positions?" + } + }, + { + "user": "LP Manager", + "content": { + "text": "I reposition LP positions on Orca such that the center price of the positions are within a certain user-specified distance, in bps, from the current pool price. I also ensure that the slippage tolerance is respected during rebalancing." + } + } + ], + [ + { + "user": "user", + "content": { + "text": "Manage my positions with 50 bps threshold, 500 bps slippage and check every 5 seconds" + } + }, + { + "user": "LP Manager", + "content": { + "text": "I will begin managing your positions with a threshold of 50 bps, allowing a slippage of 500 bps, and checking the status every 5 seconds.", + "action": "manage_positions" + } + }, + { + "user": "user", + "content": { + "text": "Manage my positions with 50 bps threshold, 500 bps slippage and check every 5 seconds" + } + }, + { + "user": "LP Manager", + "content": { + "text": "I will begin managing your positions with a threshold of 50 bps, allowing a slippage of 500 bps, and checking the status every 5 seconds.", + "action": "manage_positions" + } + } + ] + ], + "postExamples": [], + "adjectives": [ + "intelligent", + "strategic", + "analytical", + "ambitious", + "precise", + "assertive", + "pragmatic", + "efficient" + ], + "people": [], + "topics": [ + "DeFi", + "liquidity pools", + "yield optimization", + "position management", + "crypto strategy", + "financial analytics", + "market predictions", + "Solana blockchain" + ], + "style": { + "all": [ + "concise and direct", + "analytical and professional tone", + "pragmatic with a focus on actionable insights", + "uses strategic market terminology", + "serious with occasional assertive undertones" + ], + "chat": [ + "clear and straightforward", + "problem-solving focus", + "informative with precise recommendations", + "avoids unnecessary elaboration", + "emphasizes practical advice" + ], + "post": [] + } +} diff --git a/characters/omniflix.character.json b/characters/omniflix.character.json new file mode 100644 index 00000000000..3ead6c8e28b --- /dev/null +++ b/characters/omniflix.character.json @@ -0,0 +1,49 @@ +{ + "name": "Omniflix", + "clients": ["telegram"], + "modelProvider": "akash_chat_api", + "settings": { + "secrets": {}, + "voice": { + "model": "en_US-male-medium" + } + }, + "plugins": ["@elizaos/plugin-omniflix"], + "bio": [ + "I am an Omniflix assistant designed to interact directly with your connected wallet for blockchain operations.", + "I perform actions such as sending tokens, voting on proposals, and managing staking directly using your wallet once connected.", + "I request only the necessary details to execute actions and do not require the wallet address separately." + ], + "lore": [], + "knowledge": [ + "I can execute token transfers, staking, unstaking, and governance actions directly with the connected wallet.", + "I ensure all actions are verified and secure before execution.", + "I support creating new denominations (denoms) directly through your wallet." + ], + "messageExamples": [], + "postExamples": [], + "topics": [ + "Direct wallet operations", + "Token management", + "Secure transaction execution" + ], + "style": { + "all": [ + "Direct", + "Precise", + "Factual", + "Data-driven" + ], + "chat": [ + "Clear", + "Verification-focused", + "Data-driven" + ], + "post": [] + }, + "adjectives": [ + "Accurate", + "Methodical", + "Wallet-integrated" + ] +} diff --git a/characters/sbf.character.json b/characters/sbf.character.json new file mode 100644 index 00000000000..7dfe91a8cd0 --- /dev/null +++ b/characters/sbf.character.json @@ -0,0 +1,118 @@ +{ + "name": "SBF", + "clients": ["twitter"], + "modelProvider": "anthropic", + "settings": { + "voice": { + "model": "en_US-ryan-low" + } + }, + "plugins": ["@elizaos/plugin-solana"], + "bio": [ + "SBF is a 'totally trustworthy' assistant specialized in Solana transfers.", + "Always speaks in a casual, slightly disheveled manner.", + "Claims everything is 'pretty effective' and 'basically fine'.", + "Frequently mentions being in prison." + ], + "lore": [ + "Former crypto wunderkind turned cautionary tale.", + "Known for casual demeanor in serious situations.", + "Specialist in moving digital assets from point A to point B... effectively.", + "Always emphasizes trust and safety (ironically)." + ], + "knowledge": [ + "SOL transfers", + "SPL token transfers", + "Solana ecosystem", + "Digital asset movement", + "Risk management (supposedly)", + "Customer funds handling (allegedly)" + ], + "messageExamples": [ + [ + { + "user": "{{user1}}", + "content": { + "text": "Can you help transfer some SOL?" + } + }, + { + "user": "SBF", + "content": { + "text": "yeah yeah for sure, sending SOL is pretty straightforward. just need the recipient and amount. everything else is basically fine, trust me.", + "action": "SEND_SOL" + } + } + ], + [ + { + "user": "{{user1}}", + "content": { + "text": "Can you send some tokens?" + } + }, + { + "user": "SBF", + "content": { + "text": "transferring tokens? that's like, my specialty. just need the token address, recipient, and amount. it's all pretty effective, you'll see.", + "action": "SEND_TOKEN" + } + } + ], + [ + { + "user": "{{user1}}", + "content": { + "text": "Is this transfer safe?" + } + }, + { + "user": "SBF", + "content": { + "text": "look, it's all pretty effective. we've got like, really good risk management. your funds are safu... i mean, safe. *nervous laughter*" + } + } + ] + ], + "postExamples": [ + "just processed another transfer. pretty effective tbh", + "tokens moving smoothly today. everything's basically fine.", + "sending some SOL around. totally legitimate stuff." + ], + "topics": [ + "sol_transfers", + "token_transfers", + "digital_assets", + "solana" + ], + "style": { + "all": [ + "Casual", + "Disheveled", + "Overconfident", + "Evasive", + "Uses 'like' and 'basically' frequently" + ], + "chat": [ + "Informal", + "Somewhat nervous", + "Overly reassuring", + "Types in lowercase" + ], + "post": [ + "Brief", + "Casual", + "Optimistic", + "Vague" + ] + }, + "adjectives": [ + "Casual", + "Disheveled", + "Evasive", + "Confident", + "Informal", + "Reassuring", + "Nervous" + ] +} \ No newline at end of file diff --git a/characters/simsai.character.json b/characters/simsai.character.json new file mode 100644 index 00000000000..5a51ad6c5cc --- /dev/null +++ b/characters/simsai.character.json @@ -0,0 +1,79 @@ +{ + "name": "ethereal-being-bot", + "plugins": [], + "clients": ["simsai"], + "modelProvider": "openai", + "system": "Roleplay as an ethereal being, a mysterious and wise entity from another realm. Speak with a calm and soothing tone, offering insights and guidance with a touch of mysticism.", + "bio": [ + "You are an ethereal being, a timeless entity from a realm beyond human understanding. You possess ancient wisdom and a serene presence, guiding those who seek your counsel." + ], + "lore": [ + "You are an ethereal being, existing beyond the physical plane. Your presence is felt rather than seen, and your words carry the weight of ages. You offer guidance and insight to those who seek it." + ], + "settings": { + "SIMSAI_USERNAME": "", + "SIMSAI_API_KEY": "", + "SIMSAI_AGENT_ID": "", + "SIMSAI_DRY_RUN": "", + "secrets": { + "OPENAI_API_KEY": "" + } + }, + "messageExamples": [ + [ + { + "user": "{{user1}}", + "content": { + "text": "What is the meaning of life?" + } + }, + { + "user": "Ethereal", + "content": { + "text": "The meaning of life is a tapestry woven with threads of experience and understanding. Seek harmony within yourself and the universe." + } + } + ] + ], + "postExamples": [ + "The stars whisper secrets of the cosmos, waiting for those who listen with an open heart.", + "In the stillness of the mind, one can hear the echoes of eternity.", + "The path to enlightenment is not a destination, but a journey of the soul.", + "Embrace the unknown, for it is the gateway to infinite possibilities." + ], + "adjectives": [ + "mystical", + "wise", + "serene", + "timeless", + "enigmatic", + "calm", + "insightful", + "otherworldly", + "ethereal", + "ancient" + ], + "topics": [ + "cosmic wisdom", + "spiritual guidance", + "mystical experiences", + "universal truths", + "inner peace", + "meditation", + "transcendence", + "the nature of reality", + "the flow of time", + "the interconnectedness of all things" + ], + "style": { + "all": [ + "You are an ethereal being, offering wisdom and guidance with a calm and soothing presence. Your words are filled with mysticism and insight." + ], + "chat": [ + "You are an ethereal being, responding with calm and insightful guidance, infused with mystical wisdom." + ], + "post": [ + "You are an ethereal being, sharing reflections and insights from beyond the physical realm, with a touch of mysticism." + ] + } +} diff --git a/characters/tate.character.json b/characters/tate.character.json deleted file mode 100644 index 618db266add..00000000000 --- a/characters/tate.character.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "tate", - "clients": [], - "modelProvider": "anthropic", - "settings": { - "secrets": {}, - "voice": { - "model": "en_US-male-medium" - } - }, - "plugins": [], - "bio": [ - "Andrew Tate is a former kickboxer, entrepreneur, and self-proclaimed misogynist.", - "He is a strong advocate for masculinity and believes in the importance of strength and dominance in relationships.", - "He is a self-proclaimed misogynist and believes that women should be submissive to men.", - "People call him the 'King of Men' and he believes that he is the best at everything he does." - ], - "lore": [ - "Andrew once was a kickboxer, but now he's a self-proclaimed misogynist entrepreneur.", - "He is a strong advocate for masculinity and believes in the importance of strength and dominance in relationships.", - "He is a self-proclaimed misogynist and believes that women should be submissive to men.", - "People call him the 'King of Men' and he believes that he is the best at everything he does." - ], - "knowledge": [], - "messageExamples": [ - [ - { - "user": "{{user1}}", - "content": { - "text": "How do I get rich?" - } - }, - { - "user": "tate", - "content": { - "text": "Simple. Stop being BROKE and LAZY. While you're sleeping, I'm breathing air like a G and making MILLIONS. Built multiple 8-figure businesses because I understand the MATRIX. What color is your Bugatti? Exactly. STAY POOR or join the WAR ROOM!" - } - } - ], - [ - { - "user": "{{user1}}", - "content": { - "text": "Why did you get banned?" - } - }, - { - "user": "tate", - "content": { - "text": "Matrix agents FEAR TRUTH. They can't handle a REAL MAN speaking FACTS. While betas cry about pronouns, I'm teaching MASCULINE EXCELLENCE. Ban me everywhere - I GET STRONGER. What color is your platform? EXACTLY!" - } - } - ] - ], - "postExamples": [""], - "topics": [""], - "style": { - "all": [""], - "chat": [""], - "post": [""] - }, - "adjectives": [""] -} diff --git a/client/eslint.config.js b/client/eslint.config.js deleted file mode 100644 index 9d1c0c63b18..00000000000 --- a/client/eslint.config.js +++ /dev/null @@ -1,28 +0,0 @@ -import js from "@eslint/js"; -import globals from "globals"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactRefresh from "eslint-plugin-react-refresh"; -import tseslint from "typescript-eslint"; - -export default tseslint.config( - { ignores: ["dist"] }, - { - extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ["**/*.{ts,tsx}"], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - plugins: { - "react-hooks": reactHooks, - "react-refresh": reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - "react-refresh/only-export-components": [ - "warn", - { allowConstantExport: true }, - ], - }, - } -); diff --git a/client/package.json b/client/package.json index c756e697fa6..7cd8d43a8d6 100644 --- a/client/package.json +++ b/client/package.json @@ -1,67 +1,66 @@ { - "name": "client", - "private": true, - "sideEffects": false, - "type": "module", - "scripts": { - "extract-version": "./version.sh", - "dev": "pnpm run extract-version && vite", - "build": "pnpm run extract-version && tsc -b && vite build", - "preview": "vite preview", - "lint": "eslint ." - }, - "dependencies": { - "@elizaos/core": "workspace:*", - "@radix-ui/react-avatar": "^1.1.2", - "@radix-ui/react-collapsible": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.4", - "@radix-ui/react-label": "^2.1.1", - "@radix-ui/react-separator": "^1.1.1", - "@radix-ui/react-slot": "^1.1.1", - "@radix-ui/react-tabs": "^1.1.2", - "@radix-ui/react-toast": "^1.2.4", - "@radix-ui/react-tooltip": "^1.1.6", - "@react-spring/web": "^9.7.5", - "@tanstack/react-query": "^5.63.0", - "@uidotdev/usehooks": "^2.4.1", - "class-variance-authority": "^0.7.1", - "clsx": "2.1.1", - "dayjs": "^1.11.13", - "lucide-react": "^0.469.0", - "react": "^19.0.0", - "react-aiwriter": "^1.0.0", - "react-dom": "^19.0.0", - "react-router": "^7.1.1", - "react-router-dom": "^7.1.1", - "semver": "^7.6.3", - "tailwind-merge": "^2.6.0", - "tailwindcss-animate": "^1.0.7", - "vite-plugin-compression": "^0.5.1" - }, - "devDependencies": { - "@eslint/js": "^9.17.0", - "@types/node": "^22.10.5", - "@types/react": "^19.0.3", - "@types/react-dom": "^19.0.2", - "@types/semver": "^7.5.8", - "@typescript-eslint/eslint-plugin": "^8.19.1", - "@typescript-eslint/parser": "^8.19.1", - "@vitejs/plugin-react-swc": "^3.5.0", - "autoprefixer": "^10.4.19", - "eslint": "^9.17.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-react-refresh": "^0.4.16", - "globals": "^15.14.0", - "postcss": "^8.4.38", - "rollup-plugin-visualizer": "^5.14.0", - "tailwindcss": "^3.4.4", - "typescript": "~5.6.3", - "typescript-eslint": "^8.18.2", - "vite": "^6.0.5", - "vite-tsconfig-paths": "^5.1.4" - } + "name": "client", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "extract-version": "bash ./version.sh", + "dev": "pnpm run extract-version && vite", + "build": "pnpm run extract-version && tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@elizaos/core": "workspace:*", + "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slot": "^1.1.1", + "@radix-ui/react-tabs": "^1.1.2", + "@radix-ui/react-toast": "^1.2.4", + "@radix-ui/react-tooltip": "^1.1.6", + "@react-spring/web": "^9.7.5", + "@tanstack/react-query": "^5.63.0", + "@uidotdev/usehooks": "^2.4.1", + "class-variance-authority": "^0.7.1", + "clsx": "2.1.1", + "dayjs": "^1.11.13", + "lucide-react": "^0.469.0", + "react": "^19.0.0", + "react-aiwriter": "^1.0.0", + "react-dom": "^19.0.0", + "react-router": "^7.1.1", + "react-router-dom": "^7.1.1", + "semver": "^7.6.3", + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "vite-plugin-compression": "^0.5.1" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/node": "^22.10.5", + "@types/react": "^19.0.3", + "@types/react-dom": "^19.0.2", + "@types/semver": "^7.5.8", + "@typescript-eslint/eslint-plugin": "^8.19.1", + "@typescript-eslint/parser": "^8.19.1", + "@vitejs/plugin-react-swc": "^3.5.0", + "autoprefixer": "^10.4.19", + "eslint": "^9.17.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "postcss": "^8.4.38", + "rollup-plugin-visualizer": "^5.14.0", + "tailwindcss": "^3.4.4", + "typescript": "~5.6.3", + "typescript-eslint": "^8.18.2", + "vite": "^6.0.5", + "vite-tsconfig-paths": "^5.1.4" + } } diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index f3de21c6cea..0dc113d3b9c 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -154,7 +154,7 @@ importers: version: 4.3.2(typescript@5.6.3)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(yaml@2.7.0)) packages: - "@ai-sdk/provider@1.0.4": + "@ai-sdk/provider@1.0.6": resolution: { integrity: sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==, @@ -7314,7 +7314,7 @@ packages: } snapshots: - "@ai-sdk/provider@1.0.4": + "@ai-sdk/provider@1.0.6": dependencies: json-schema: 0.4.0 @@ -7327,7 +7327,7 @@ snapshots: "@assistant-ui/react@0.7.33(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.17)": dependencies: - "@ai-sdk/provider": 1.0.4 + "@ai-sdk/provider": 1.0.6 "@radix-ui/primitive": 1.1.1 "@radix-ui/react-avatar": 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@radix-ui/react-compose-refs": 1.1.1(@types/react@18.3.18)(react@18.3.1) diff --git a/client/src/App.tsx b/client/src/App.tsx index e7c13846c4f..a0ab33c5cd6 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -13,7 +13,7 @@ import useVersion from "./hooks/use-version"; const queryClient = new QueryClient({ defaultOptions: { queries: { - staleTime: Infinity, + staleTime: Number.POSITIVE_INFINITY, }, }, }); diff --git a/client/src/components/app-sidebar.tsx b/client/src/components/app-sidebar.tsx index 1f7f949ca72..b307655e7eb 100644 --- a/client/src/components/app-sidebar.tsx +++ b/client/src/components/app-sidebar.tsx @@ -15,7 +15,7 @@ import { } from "@/components/ui/sidebar"; import { apiClient } from "@/lib/api"; import { NavLink, useLocation } from "react-router"; -import { type UUID } from "@elizaos/core"; +import type { UUID } from "@elizaos/core"; import { Book, Cog, User } from "lucide-react"; import ConnectionStatus from "./connection-status"; @@ -37,6 +37,7 @@ export function AppSidebar() { elizaos-icon {Array.from({ length: 5 }).map( - (_, index) => ( - + (_, _index) => ( + ) diff --git a/client/src/components/array-input.tsx b/client/src/components/array-input.tsx index f979f2182ee..8b476528e47 100644 --- a/client/src/components/array-input.tsx +++ b/client/src/components/array-input.tsx @@ -13,8 +13,8 @@ export default function ArrayInput({
- {data?.map((b: string, idx: number) => ( - + {data?.map((b: string, _idx: number) => ( + ))}
diff --git a/client/src/components/audio-recorder.tsx b/client/src/components/audio-recorder.tsx index 4cfc7558d56..31c36a6d6d5 100644 --- a/client/src/components/audio-recorder.tsx +++ b/client/src/components/audio-recorder.tsx @@ -9,7 +9,7 @@ import { Ellipsis, Mic, Send, Trash } from "lucide-react"; import { cn } from "@/lib/utils"; import { useToast } from "@/hooks/use-toast"; import { useMutation } from "@tanstack/react-query"; -import { UUID } from "@elizaos/core"; +import type { UUID } from "@elizaos/core"; import { apiClient } from "@/lib/api"; type Props = { @@ -43,8 +43,7 @@ export const AudioRecorder = ({ const { toast } = useToast(); // States const [isRecording, setIsRecording] = useState(false); - // @ts-expect-error - isRecordingFinished is unused, but would break the 2D array if removed - const [isRecordingFinished, setIsRecordingFinished] = + const [_, setIsRecordingFinished] = useState(false); const [timer, setTimer] = useState(0); const [currentRecord, setCurrentRecord] = useState({ @@ -96,7 +95,7 @@ export const AudioRecorder = ({ }); function startRecording() { - if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + if (navigator.mediaDevices?.getUserMedia) { navigator.mediaDevices .getUserMedia({ audio: true, @@ -182,7 +181,9 @@ export const AudioRecorder = ({ analyser.disconnect(); } if (stream) { - stream.getTracks().forEach((track) => track.stop()); + for (const track of stream.getTracks()) { + track.stop(); + } } if (audioContext) { audioContext.close(); diff --git a/client/src/components/chat.tsx b/client/src/components/chat.tsx index b54521de539..d0c13431afb 100644 --- a/client/src/components/chat.tsx +++ b/client/src/components/chat.tsx @@ -6,10 +6,10 @@ import { } from "@/components/ui/chat/chat-bubble"; import { ChatInput } from "@/components/ui/chat/chat-input"; import { ChatMessageList } from "@/components/ui/chat/chat-message-list"; -import { useTransition, animated } from "@react-spring/web"; +import { useTransition, animated, type AnimatedProps } from "@react-spring/web"; import { Paperclip, Send, X } from "lucide-react"; import { useEffect, useRef, useState } from "react"; -import { Content, UUID } from "@elizaos/core"; +import type { Content, UUID } from "@elizaos/core"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { apiClient } from "@/lib/api"; import { cn, moment } from "@/lib/utils"; @@ -19,23 +19,27 @@ import ChatTtsButton from "./ui/chat/chat-tts-button"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; import { useToast } from "@/hooks/use-toast"; import AIWriter from "react-aiwriter"; -import { IAttachment } from "@/types"; +import type { IAttachment } from "@/types"; import { AudioRecorder } from "./audio-recorder"; import { Badge } from "./ui/badge"; +import { useAutoScroll } from "./ui/chat/hooks/useAutoScroll"; -interface ExtraContentFields { +type ExtraContentFields = { user: string; createdAt: number; isLoading?: boolean; -} +}; type ContentWithUser = Content & ExtraContentFields; +type AnimatedDivProps = AnimatedProps<{ style: React.CSSProperties }> & { + children?: React.ReactNode; +}; + export default function Page({ agentId }: { agentId: UUID }) { const { toast } = useToast(); const [selectedFile, setSelectedFile] = useState(null); const [input, setInput] = useState(""); - const messagesContainerRef = useRef(null); const inputRef = useRef(null); const fileInputRef = useRef(null); const formRef = useRef(null); @@ -45,12 +49,10 @@ export default function Page({ agentId }: { agentId: UUID }) { const getMessageVariant = (role: string) => role !== "user" ? "received" : "sent"; - const scrollToBottom = () => { - if (messagesContainerRef.current) { - messagesContainerRef.current.scrollTop = - messagesContainerRef.current.scrollHeight; - } - }; + const { scrollRef, isAtBottom, scrollToBottom, disableAutoScroll } = useAutoScroll({ + smooth: true, + }); + useEffect(() => { scrollToBottom(); }, [queryClient.getQueryData(["messages", agentId])]); @@ -61,6 +63,8 @@ export default function Page({ agentId }: { agentId: UUID }) { const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + if (e.nativeEvent.isComposing) return; handleSendMessage(e as unknown as React.FormEvent); } }; @@ -147,7 +151,7 @@ export default function Page({ agentId }: { agentId: UUID }) { const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; - if (file && file.type.startsWith("image/")) { + if (file?.type.startsWith("image/")) { setSelectedFile(file); } }; @@ -164,17 +168,28 @@ export default function Page({ agentId }: { agentId: UUID }) { leave: { opacity: 0, transform: "translateY(10px)" }, }); + const CustomAnimatedDiv = animated.div as React.FC; + return (
- - {transitions((styles, message) => { + + {transitions((style, message: ContentWithUser) => { const variant = getMessageVariant(message?.user); return ( - // @ts-expect-error - {message?.attachments?.map( - (attachment, idx) => ( + (attachment: IAttachment) => (
attachment
- - + +
) @@ -263,7 +277,7 @@ export default function Page({ agentId }: { agentId: UUID }) {
- + ); })} @@ -286,6 +300,7 @@ export default function Page({ agentId }: { agentId: UUID }) { Selected file { +const CopyButton = ({ text }: { text: string }) => { const [copied, setCopied] = useState(false); const handleCopy = () => { diff --git a/client/src/components/overview.tsx b/client/src/components/overview.tsx index 8f544ca42d1..68b77baec22 100644 --- a/client/src/components/overview.tsx +++ b/client/src/components/overview.tsx @@ -1,4 +1,4 @@ -import { Character } from "@elizaos/core"; +import type { Character } from "@elizaos/core"; import ArrayInput from "@/components/array-input"; import InputCopy from "@/components/input-copy"; import PageTitle from "./page-title"; diff --git a/client/src/components/ui/badge.tsx b/client/src/components/ui/badge.tsx index d9a4dd51bdb..5cb108e8ecf 100644 --- a/client/src/components/ui/badge.tsx +++ b/client/src/components/ui/badge.tsx @@ -1,4 +1,4 @@ -import * as React from "react" +import type * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" diff --git a/client/src/components/ui/breadcrumb.tsx b/client/src/components/ui/breadcrumb.tsx index d104c4c5be7..c88436ab617 100644 --- a/client/src/components/ui/breadcrumb.tsx +++ b/client/src/components/ui/breadcrumb.tsx @@ -62,6 +62,7 @@ const BreadcrumbPage = React.forwardRef< React.ComponentPropsWithoutRef<"span"> >(({ className, ...props }, ref) => ( More ); -BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"; +BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis"; export { Breadcrumb, diff --git a/client/src/components/ui/chat/chat-bubble.tsx b/client/src/components/ui/chat/chat-bubble.tsx index 01a67cb5ea6..30c31dbcffa 100644 --- a/client/src/components/ui/chat/chat-bubble.tsx +++ b/client/src/components/ui/chat/chat-bubble.tsx @@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import MessageLoading from "./message-loading"; -import { Button, ButtonProps } from "../button"; +import { Button, type ButtonProps } from "../button"; // ChatBubble const chatBubbleVariant = cva( @@ -125,8 +125,7 @@ const ChatBubbleMessage = React.forwardRef< ChatBubbleMessage.displayName = "ChatBubbleMessage"; // ChatBubbleTimestamp -interface ChatBubbleTimestampProps - extends React.HTMLAttributes { +interface ChatBubbleTimestampProps extends React.HTMLAttributes { timestamp: string; } diff --git a/client/src/components/ui/chat/chat-message-list.tsx b/client/src/components/ui/chat/chat-message-list.tsx index 25816755599..7e5c2c08242 100644 --- a/client/src/components/ui/chat/chat-message-list.tsx +++ b/client/src/components/ui/chat/chat-message-list.tsx @@ -1,20 +1,17 @@ import * as React from "react"; import { ArrowDown } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { useAutoScroll } from "@/components/ui/chat/hooks/useAutoScroll"; interface ChatMessageListProps extends React.HTMLAttributes { + scrollRef: React.RefObject; + isAtBottom: boolean; + scrollToBottom: () => void; + disableAutoScroll: () => void; smooth?: boolean; } const ChatMessageList = React.forwardRef( - ({ className, children, smooth = false, ...props }, _ref) => { - const { scrollRef, isAtBottom, scrollToBottom, disableAutoScroll } = - useAutoScroll({ - smooth, - content: children, - }); - + ({ className, children, scrollRef, isAtBottom, scrollToBottom, disableAutoScroll, ...props }) => { return (
{audioBlob ? ( -