Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/blankdotspace_justtom-eliza-starter.json
T

1 line
1.8 MiB
Plaintext

{"repo": "blankdotspace/justtom-eliza-starter", "files": {"agent/src/index.ts": {"f80a9c48151439680b200e712b171fe0f67c2f9c": {"t": 1785745598.1638641, "n": 60092, "h": "169049154a981cd4", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\n// import { edwinPlugin } from \"@elizaos/plugin-edwin\";\n// import { flowPlugin } from \"@elizaos/plugin-flow\";\n// import { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\n// import { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n elizaLogger.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n // getSecret(character, \"FLOW_ADDRESS\") &&\n // getSecret(character, \"FLOW_PRIVATE_KEY\")\n // ? flowPlugin\n // : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n // getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n // getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n // getSecret(character, \"EVM_RPC_URL\")\n // ? litPlugin\n // : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n // getSecret(character, \"QUICKINTEL_API_KEY\")\n // ? quickIntelPlugin\n // : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "b5999c35b0af72cf97bece69079ff11dec8566be": {"t": 1785754635.6067207, "n": 60092, "h": "169049154a981cd4", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\n// import { edwinPlugin } from \"@elizaos/plugin-edwin\";\n// import { flowPlugin } from \"@elizaos/plugin-flow\";\n// import { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\n// import { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n elizaLogger.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n // getSecret(character, \"FLOW_ADDRESS\") &&\n // getSecret(character, \"FLOW_PRIVATE_KEY\")\n // ? flowPlugin\n // : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n // getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n // getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n // getSecret(character, \"EVM_RPC_URL\")\n // ? litPlugin\n // : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n // getSecret(character, \"QUICKINTEL_API_KEY\")\n // ? quickIntelPlugin\n // : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "c86494a9a2be66caf198116e05e14c8d885526b6": {"t": 1785754637.3613846, "n": 59930, "h": "6fe8b4406370518a", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\n// import { edwinPlugin } from \"@elizaos/plugin-edwin\";\n// import { flowPlugin } from \"@elizaos/plugin-flow\";\n// import { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\n// import { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n elizaLogger.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n // getSecret(character, \"FLOW_ADDRESS\") &&\n // getSecret(character, \"FLOW_PRIVATE_KEY\")\n // ? flowPlugin\n // : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n // getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n // getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n // getSecret(character, \"EVM_RPC_URL\")\n // ? litPlugin\n // : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n // getSecret(character, \"QUICKINTEL_API_KEY\")\n // ? quickIntelPlugin\n // : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "7b8be58fc11ecc584dcb1630a88939eeadfa49a7": {"t": 1785754639.223842, "n": 59926, "h": "071202fe1871a8a1", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\n// import { edwinPlugin } from \"@elizaos/plugin-edwin\";\n// import { flowPlugin } from \"@elizaos/plugin-flow\";\n// import { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\n// import { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n // getSecret(character, \"FLOW_ADDRESS\") &&\n // getSecret(character, \"FLOW_PRIVATE_KEY\")\n // ? flowPlugin\n // : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n // getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n // getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n // getSecret(character, \"EVM_RPC_URL\")\n // ? litPlugin\n // : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n // getSecret(character, \"QUICKINTEL_API_KEY\")\n // ? quickIntelPlugin\n // : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "8547961c9cb1a9075f0dd70bc837f6b6798c22a7": {"t": 1785754641.1029248, "n": 59887, "h": "310f64e0d2fb9a35", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\n// import { edwinPlugin } from \"@elizaos/plugin-edwin\";\n// import { flowPlugin } from \"@elizaos/plugin-flow\";\n// import { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "34b07f8350bd5ae6fd304f1d187a79432f708dd1": {"t": 1785754642.8816757, "n": 59615, "h": "da24a01700244490", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { edwinPlugin } from \"@elizaos/plugin-edwin\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PRIVATE_KEY\") ||\n getSecret(character, \"SOLANA_PRIVATE_KEY\"))\n ? edwinPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "13aacf185312858665b2955455d3b041a9899d6a": {"t": 1785754644.318952, "n": 59532, "h": "565c8cf8eb198390", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { edwinPlugin } from \"@elizaos/plugin-edwin\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PRIVATE_KEY\") ||\n getSecret(character, \"SOLANA_PRIVATE_KEY\"))\n ? edwinPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n elizaLogger.info(`Server started on alternate port ${serverPort}`);\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "accfe6db0b981f93da85222d845b0a2c5ac52dc9": {"t": 1785754645.853515, "n": 59614, "h": "f0766fd4a70aa710", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { edwinPlugin } from \"@elizaos/plugin-edwin\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PRIVATE_KEY\") ||\n getSecret(character, \"SOLANA_PRIVATE_KEY\"))\n ? edwinPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "feda18ab14ca9f0340bcde732c00286471e4c185": {"t": 1785754647.569239, "n": 59362, "h": "6156935ab5f139db", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { edwinPlugin } from \"@elizaos/plugin-edwin\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PRIVATE_KEY\") ||\n getSecret(character, \"SOLANA_PRIVATE_KEY\"))\n ? edwinPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "39c78e804fbbbff43bc6b4d2903ef113369b9470": {"t": 1785754649.3448737, "n": 59805, "h": "83a47e103328998b", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\n// import { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\n// import { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\n// import { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n // getSecret(character, \"CDP_API_KEY_NAME\") &&\n // getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n // getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n // ? agentKitPlugin\n // : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "f83b02edb5fafb5be0d6abbd356b3e0b7b4e2a18": {"t": 1785754651.3073993, "n": 59781, "h": "2e471b68a2469833", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\n// import { akashPlugin } from \"@elizaos/plugin-akash\";\n// import { alloraPlugin } from \"@elizaos/plugin-allora\";\n// import { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\n// import { binancePlugin } from \"@elizaos/plugin-binance\";\n// import { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\n// import { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\n// import { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\n// import { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\n// import { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\n// import { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\n// import { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\n// import { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\n// import { solanaPlugin } from \"@elizaos/plugin-solana\";\n// import { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\n// import { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\n// import { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\n// import { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\n// import { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\n// import { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\n// import nitroPlugin from \"@elizaos/plugin-router-nitro\";\n// import { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n// import { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\n// import { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\n// import { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\n// import { emailPlugin } from \"@elizaos/plugin-email\";\n// import { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\n// import { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\n// import { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\n// import { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\n// import { trikonPlugin } from \"@elizaos/plugin-trikon\";\n// import arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n // const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n // maxPoolSize: 100,\n // minPoolSize: 5,\n // maxIdleTimeMS: 60000,\n // connectTimeoutMS: 10000,\n // serverSelectionTimeoutMS: 5000,\n // socketTimeoutMS: 45000,\n // compressors: [\"zlib\"],\n // retryWrites: true,\n // retryReads: true,\n // });\n\n // const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n // const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n // db.init()\n // .then(() => {\n // elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n // })\n // .catch((error) => {\n // elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n // throw error; // Re-throw to handle it in the calling code\n // });\n\n // return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n // parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n // getSecret(character, \"BITMIND_API_TOKEN\")\n // ? bittensorPlugin\n // : null,\n // parseBooleanFromText(\n // getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n // )\n // ? emailAutomationPlugin\n // : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n // getSecret(character, \"DEXSCREENER_API_KEY\")\n // ? dexScreenerPlugin\n // : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n // getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n // getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n // ? nitroPlugin\n // : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n // getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? [solanaPlugin, solanaPluginV2]\n // : null,\n // getSecret(character, \"SOLANA_PRIVATE_KEY\")\n // ? solanaAgentkitPlugin\n // : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n // getSecret(character, \"EVM_PUBLIC_KEY\") ||\n // (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n // getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n // ? evmPlugin\n // : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n // getSecret(character, \"COINGECKO_API_KEY\") ||\n // getSecret(character, \"COINGECKO_PRO_API_KEY\")\n // ? coingeckoPlugin\n // : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n // getSecret(character, \"BINANCE_API_KEY\") &&\n // getSecret(character, \"BINANCE_SECRET_KEY\")\n // ? binancePlugin\n // : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n // getSecret(character, \"LENS_PRIVATE_KEY\")\n // ? lensPlugin\n // : null,\n // getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n // getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n // getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n // getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n // getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n // getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n // getSecret(character, \"AKASH_MNEMONIC\") &&\n // getSecret(character, \"AKASH_WALLET_ADDRESS\")\n // ? akashPlugin\n // : null,\n // getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n // getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n // getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n // ? holdstationPlugin\n // : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n // getSecret(character, \"NVIDIA_NGC_API_KEY\")\n // ? nvidiaNimPlugin\n // : null,\n // getSecret(character, \"BNB_PRIVATE_KEY\") ||\n // getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n // ? bnbPlugin\n // : null,\n // (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n // getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n // (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n // getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n // ? emailPlugin\n // : null,\n // getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n // getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n // getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n // getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n // (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n // getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n // getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n // getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n // ? arbitragePlugin\n // : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "e1630b1c074b5415b022027627c9ef7198653631": {"t": 1785754652.923914, "n": 59379, "h": "0b2bfbf1cd3344f1", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\n// import { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\n\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "368aac1b468857a33e989b7211a5c2e0df882e06": {"t": 1785754654.712305, "n": 59057, "h": "51161304fac617c6", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n elizaLogger.info(`Server started on alternate port ${serverPort}`);\n\n elizaLogger.info(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "c206fa4fbfe077455ca5283ab5bc6b54c2befd6b": {"t": 1785754657.2722514, "n": 59391, "h": "670b943b7f65f2d0", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "8e3de759033b66f8a5d8cc68e5ed9bf337094ed5": {"t": 1785754659.6199746, "n": 59139, "h": "4a97739a47d16dbb", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "f23159efdad95ebded43d8b169f3f6233e7d4641": {"t": 1785754661.2613072, "n": 59440, "h": "716ec27386cfc1ec", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "376b25afba813423d023e370b97f5ecbff78805a": {"t": 1785754663.2637477, "n": 59791, "h": "915135d90cd3daea", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\n// import { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n // verifiableInferenceAdapter = new PrimusAdapter({\n // appId: process.env.PRIMUS_APP_ID,\n // appSecret: process.env.PRIMUS_APP_SECRET,\n // attMode: \"proxytls\",\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n // (getSecret(character, \"NEAR_ADDRESS\") ||\n // getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n // getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n // ? nearPlugin\n // : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n // getSecret(character, \"COINMARKETCAP_API_KEY\")\n // ? coinmarketcapPlugin\n // : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n // getSecret(character, \"ENABLE_TEE_LOG\") &&\n // ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n // getSecret(character, \"SGX\"))\n // ? teeLogPlugin\n // : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n // getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n // getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "3f1a79e2447bfa01c66527eac7e15f9147a826e5": {"t": 1785754667.1167748, "n": 59411, "h": "78870f8ca40b6e30", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { edwinPlugin } from \"@elizaos/plugin-edwin\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PRIVATE_KEY\") ||\n getSecret(character, \"SOLANA_PRIVATE_KEY\"))\n ? edwinPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "2eb5e84eb3611997f59187eb9b12bc6c226f7fd1": {"t": 1785754670.0001688, "n": 59188, "h": "713319796b1257cb", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "97ffb05cc52cd593aeacd045df9016b50bc5a0ae": {"t": 1785754671.6510801, "n": 59187, "h": "2806a14d9443f6dc", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "26a26f7c48baad1fc9a76930f14cd60300482728": {"t": 1785754673.305555, "n": 59391, "h": "bdacd9873c1ba0aa", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "4a3255115dc23e2ecb2d16122f97b622c89a0c8f": {"t": 1785754675.0651822, "n": 59350, "h": "0362c0ece9479eb2", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local or gaianet\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\") ||\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "4fae1399a1050275efd9b1876402a319f995c2a5": {"t": 1785754676.773615, "n": 59139, "h": "56afa2ceb3bc3064", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lens-network\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "5c0d0d6175c9ca6541c97f611096c9b768756bf4": {"t": 1785754678.6882923, "n": 59189, "h": "3ca81ade4640096d", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local, ollama, lmstudio, gaianet or bedrock\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.LMSTUDIO:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "4663502223b8419a42fdd85ded2456bcf2bea8eb": {"t": 1785754680.2633479, "n": 40256, "h": "84adb4101c951fd0", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { FarcasterAgentClient } from \"@elizaos/client-farcaster\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\n// import { ReclaimAdapter } from \"@elizaos/plugin-reclaim\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\n\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n Character,\n Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n IAgentRuntime,\n ICacheManager,\n IDatabaseAdapter,\n IDatabaseCacheAdapter,\n ModelProviderName,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaAgentkitPlguin } from \"@elizaos/plugin-solana-agentkit\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\n\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\n\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport {dominosPlugin} from \"@elizaos/plugin-dominos\";\n\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime: number = 1000, maxTime: number = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})]);\n keys.forEach(key => {\n if (typeof baseObj[key] === 'object' && typeof childObj[key] === 'object' && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {\n result[key] = [...(baseObj[key] || []), ...(childObj[key] || [])];\n } else {\n result[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n let character = JSON.parse(content);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(\n character.plugins\n );\n if (character.extends) {\n elizaLogger.info(`Merging ${character.name} character with parent characters`);\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath));\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`);\n }\n }\n return character;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = charactersArg\n ?.split(\",\")\n .map((filePath) => filePath.trim());\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(\n __dirname,\n \"characters\",\n path.basename(characterPath)\n ), // relative to agent/characters\n path.resolve(\n __dirname,\n \"../characters\",\n path.basename(characterPath)\n ), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n process.exit(1);\n }\n\n try {\n const character: Character = await loadCharacter(resolvedPath);\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${resolvedPath}`\n );\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${resolvedPath}: ${e}`\n );\n process.exit(1);\n }\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local or gaianet\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to Supabase database\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to PostgreSQL database\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else {\n const filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to SQLite database\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n // why is this one different :(\n const farcasterClient = new FarcasterAgentClient(runtime);\n if (farcasterClient) {\n farcasterClient.start();\n clients.farcaster = farcasterClient;\n }\n }\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n // TODO: Add Slack client to the list\n // Initialize clients as an object\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"){\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n bootstrapPlugin,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? solanaPlugin\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlguin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\")\n ? quaiPlugin\n : null,\n ].filter(Boolean),\n providers: [],\n actions: [],\n services: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n let charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (charactersArg) {\n characters = await loadCharacters(charactersArg);\n }\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.start(serverPort);\n\n if (serverPort !== parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n"}, "8c0e77c70b0ae9964f9bb100c29d25ca6edafdff": {"t": 1785754683.8486164, "n": 59408, "h": "c4b05622690da8ce", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { deskExchangePlugin } from \"@elizaos/plugin-desk-exchange\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local or gaianet\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_PRIVATE_KEY\")\n ? deskExchangePlugin\n : null,\n getSecret(character, \"DESK_EXCHANGE_NETWORK\")\n ? deskExchangePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "4a25b385313befdd645ad1febb4105b65cd595a5": {"t": 1785754685.7681587, "n": 59098, "h": "af5b48c01438cec9", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\";\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\";\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\";\nimport { RedisClient } from \"@elizaos/adapter-redis\";\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\";\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\";\nimport { AutoClientInterface } from \"@elizaos/client-auto\";\nimport { DiscordClientInterface } from \"@elizaos/client-discord\";\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\";\nimport { LensAgentClient } from \"@elizaos/client-lens\";\nimport { SlackClientInterface } from \"@elizaos/client-slack\";\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\";\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\";\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\";\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\";\nimport { DevaClientInterface } from \"@elizaos/client-deva\";\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\";\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\";\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\";\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\";\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\";\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\";\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\";\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\";\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\";\nimport {\n AgentRuntime,\n CacheManager,\n CacheStore,\n type Character,\n type Client,\n Clients,\n DbCacheAdapter,\n defaultCharacter,\n elizaLogger,\n FsCacheAdapter,\n type IAgentRuntime,\n type ICacheManager,\n type IDatabaseAdapter,\n type IDatabaseCacheAdapter,\n ModelProviderName,\n parseBooleanFromText,\n settings,\n stringToUuid,\n validateCharacterConfig,\n} from \"@elizaos/core\";\nimport { zgPlugin } from \"@elizaos/plugin-0g\";\nimport { footballPlugin } from \"@elizaos/plugin-football\";\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\";\nimport { normalizeCharacter } from \"@elizaos/plugin-di\";\nimport createGoatPlugin from \"@elizaos/plugin-goat\";\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\";\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\";\nimport { akashPlugin } from \"@elizaos/plugin-akash\";\nimport { alloraPlugin } from \"@elizaos/plugin-allora\";\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\";\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\";\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\";\nimport { availPlugin } from \"@elizaos/plugin-avail\";\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\";\nimport { b2Plugin } from \"@elizaos/plugin-b2\";\nimport { binancePlugin } from \"@elizaos/plugin-binance\";\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\";\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\";\nimport {\n advancedTradePlugin,\n coinbaseCommercePlugin,\n coinbaseMassPaymentsPlugin,\n tokenContractPlugin,\n tradePlugin,\n webhookPlugin,\n} from \"@elizaos/plugin-coinbase\";\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\";\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\";\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\";\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\";\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\";\nimport { evmPlugin } from \"@elizaos/plugin-evm\";\nimport { flowPlugin } from \"@elizaos/plugin-flow\";\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\";\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\";\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\";\nimport { initiaPlugin } from \"@elizaos/plugin-initia\";\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\";\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\";\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\";\nimport { nearPlugin } from \"@elizaos/plugin-near\";\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\";\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\";\nimport { createNodePlugin } from \"@elizaos/plugin-node\";\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\";\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\";\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\";\nimport { quaiPlugin } from \"@elizaos/plugin-quai\";\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\";\nimport { solanaPlugin } from \"@elizaos/plugin-solana\";\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\";\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\";\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\";\nimport { storyPlugin } from \"@elizaos/plugin-story\";\nimport { suiPlugin } from \"@elizaos/plugin-sui\";\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\";\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\";\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\";\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\";\nimport { tonPlugin } from \"@elizaos/plugin-ton\";\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\";\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\";\nimport { injectivePlugin } from \"@elizaos/plugin-injective\";\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\";\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\";\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\";\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\";\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\";\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\";\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\";\nimport { openaiPlugin } from \"@elizaos/plugin-openai\";\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\";\nimport { devinPlugin } from \"@elizaos/plugin-devin\";\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\";\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\";\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\";\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\";\nimport { zxPlugin } from \"@elizaos/plugin-0x\";\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\";\nimport { litPlugin } from \"@elizaos/plugin-lit\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport yargs from \"yargs\";\nimport { emailPlugin } from \"@elizaos/plugin-email\";\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\";\nimport { sunoPlugin } from \"@elizaos/plugin-suno\";\nimport { udioPlugin } from \"@elizaos/plugin-udio\";\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\";\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\";\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\";\nimport { minaPlugin } from \"@elizaos/plugin-mina\";\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\";\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\";\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\";\nconst __filename = fileURLToPath(import.meta.url); // get the resolved path to the file\nconst __dirname = path.dirname(__filename); // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n const waitTime =\n Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;\n return new Promise((resolve) => setTimeout(resolve, waitTime));\n};\n\nconst logFetch = async (url: string, options: any) => {\n elizaLogger.debug(`Fetching ${url}`);\n // Disabled to avoid disclosure of sensitive information such as API keys\n // elizaLogger.debug(JSON.stringify(options, null, 2));\n return fetch(url, options);\n};\n\nexport function parseArguments(): {\n character?: string;\n characters?: string;\n} {\n try {\n return yargs(process.argv.slice(3))\n .option(\"character\", {\n type: \"string\",\n description: \"Path to the character JSON file\",\n })\n .option(\"characters\", {\n type: \"string\",\n description:\n \"Comma separated list of paths to character JSON files\",\n })\n .parseSync();\n } catch (error) {\n elizaLogger.error(\"Error parsing arguments:\", error);\n return {};\n }\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch (e) {\n return null;\n }\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n const mergeObjects = (baseObj: any, childObj: any) => {\n const result: any = {};\n const keys = new Set([\n ...Object.keys(baseObj || {}),\n ...Object.keys(childObj || {}),\n ]);\n keys.forEach((key) => {\n if (\n typeof baseObj[key] === \"object\" &&\n typeof childObj[key] === \"object\" &&\n !Array.isArray(baseObj[key]) &&\n !Array.isArray(childObj[key])\n ) {\n result[key] = mergeObjects(baseObj[key], childObj[key]);\n } else if (\n Array.isArray(baseObj[key]) ||\n Array.isArray(childObj[key])\n ) {\n result[key] = [\n ...(baseObj[key] || []),\n ...(childObj[key] || []),\n ];\n } else {\n result[key] =\n childObj[key] !== undefined ? childObj[key] : baseObj[key];\n }\n });\n return result;\n };\n return mergeObjects(base, child);\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n return Array.isArray(arr) && arr.every((item) => typeof item === \"string\");\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n const jsonText = onchainJson;\n\n console.log(\"JSON:\", jsonText);\n if (!jsonText) return [];\n const loadedCharacters = [];\n try {\n const character = JSON.parse(jsonText);\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n settings[settingKey] = value;\n return settings;\n }, {});\n\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n\n // Handle plugins\n if (isAllStrings(character.plugins)) {\n elizaLogger.info(\"Plugins are: \", character.plugins);\n const importedPlugins = await Promise.all(\n character.plugins.map(async (plugin) => {\n const importedPlugin = await import(plugin);\n return importedPlugin.default;\n })\n );\n character.plugins = importedPlugins;\n }\n\n loadedCharacters.push(character);\n elizaLogger.info(\n `Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`\n );\n return loadedCharacters;\n } catch (e) {\n elizaLogger.error(\n `Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`\n );\n process.exit(1);\n }\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n try {\n const response = await fetch(url);\n const responseJson = await response.json();\n\n let characters: Character[] = [];\n if (Array.isArray(responseJson)) {\n characters = await Promise.all(\n responseJson.map((character) => jsonToCharacter(url, character))\n );\n } else {\n const character = await jsonToCharacter(url, responseJson);\n characters.push(character);\n }\n return characters;\n } catch (e) {\n elizaLogger.error(`Error loading character(s) from ${url}: ${e}`);\n process.exit(1);\n }\n}\n\nasync function jsonToCharacter(\n filePath: string,\n character: any\n): Promise<Character> {\n validateCharacterConfig(character);\n\n // .id isn't really valid\n const characterId = character.id || character.name;\n const characterPrefix = `CHARACTER.${characterId\n .toUpperCase()\n .replace(/ /g, \"_\")}.`;\n const characterSettings = Object.entries(process.env)\n .filter(([key]) => key.startsWith(characterPrefix))\n .reduce((settings, [key, value]) => {\n const settingKey = key.slice(characterPrefix.length);\n return { ...settings, [settingKey]: value };\n }, {});\n if (Object.keys(characterSettings).length > 0) {\n character.settings = character.settings || {};\n character.settings.secrets = {\n ...characterSettings,\n ...character.settings.secrets,\n };\n }\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n if (character.extends) {\n elizaLogger.info(\n `Merging ${character.name} character with parent characters`\n );\n for (const extendPath of character.extends) {\n const baseCharacter = await loadCharacter(\n path.resolve(path.dirname(filePath), extendPath)\n );\n character = mergeCharacters(baseCharacter, character);\n elizaLogger.info(\n `Merged ${character.name} with ${baseCharacter.name}`\n );\n }\n }\n return character;\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n const content = tryLoadFile(filePath);\n if (!content) {\n throw new Error(`Character file not found: ${filePath}`);\n }\n const character = JSON.parse(content);\n return jsonToCharacter(filePath, character);\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n let content: string | null = null;\n let resolvedPath = \"\";\n\n // Try different path resolutions in order\n const pathsToTry = [\n characterPath, // exact path as specified\n path.resolve(process.cwd(), characterPath), // relative to cwd\n path.resolve(process.cwd(), \"agent\", characterPath), // Add this\n path.resolve(__dirname, characterPath), // relative to current script\n path.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n path.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n path.resolve(\n __dirname,\n \"../../characters\",\n path.basename(characterPath)\n ), // relative to project root characters dir\n ];\n\n elizaLogger.info(\n \"Trying paths:\",\n pathsToTry.map((p) => ({\n path: p,\n exists: fs.existsSync(p),\n }))\n );\n\n for (const tryPath of pathsToTry) {\n content = tryLoadFile(tryPath);\n if (content !== null) {\n resolvedPath = tryPath;\n break;\n }\n }\n\n if (content === null) {\n elizaLogger.error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n elizaLogger.error(\"Tried the following paths:\");\n pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));\n throw new Error(\n `Error loading character from ${characterPath}: File not found in any of the expected locations`\n );\n }\n try {\n const character: Character = await loadCharacter(resolvedPath);\n elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);\n return character;\n } catch (e) {\n elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);\n throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);\n }\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n return commaSeparated?.split(\",\").map((value) => value.trim());\n}\n\nasync function readCharactersFromStorage(\n characterPaths: string[]\n): Promise<string[]> {\n try {\n const uploadDir = path.join(process.cwd(), \"data\", \"characters\");\n await fs.promises.mkdir(uploadDir, { recursive: true });\n const fileNames = await fs.promises.readdir(uploadDir);\n fileNames.forEach((fileName) => {\n characterPaths.push(path.join(uploadDir, fileName));\n });\n } catch (err) {\n elizaLogger.error(`Error reading directory: ${err.message}`);\n }\n\n return characterPaths;\n}\n\nexport async function loadCharacters(\n charactersArg: string\n): Promise<Character[]> {\n let characterPaths = commaSeparatedStringToArray(charactersArg);\n\n if (process.env.USE_CHARACTER_STORAGE === \"true\") {\n characterPaths = await readCharactersFromStorage(characterPaths);\n }\n\n const loadedCharacters: Character[] = [];\n\n if (characterPaths?.length > 0) {\n for (const characterPath of characterPaths) {\n try {\n const character: Character = await loadCharacterTryPath(\n characterPath\n );\n loadedCharacters.push(character);\n } catch (e) {\n process.exit(1);\n }\n }\n }\n\n if (hasValidRemoteUrls()) {\n elizaLogger.info(\"Loading characters from remote URLs\");\n const characterUrls = commaSeparatedStringToArray(\n process.env.REMOTE_CHARACTER_URLS\n );\n for (const characterUrl of characterUrls) {\n const characters = await loadCharactersFromUrl(characterUrl);\n loadedCharacters.push(...characters);\n }\n }\n\n if (loadedCharacters.length === 0) {\n elizaLogger.info(\"No characters found, using default character\");\n loadedCharacters.push(defaultCharacter);\n }\n\n return loadedCharacters;\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n if (plugins.length > 0) {\n elizaLogger.info(\"Plugins are: \", plugins);\n const importedPlugins = await Promise.all(\n plugins.map(async (plugin) => {\n try {\n const importedPlugin = await import(plugin);\n const functionName =\n plugin\n .replace(\"@elizaos/plugin-\", \"\")\n .replace(/-./g, (x) => x[1].toUpperCase()) +\n \"Plugin\"; // Assumes plugin function is camelCased with Plugin suffix\n return (\n importedPlugin.default || importedPlugin[functionName]\n );\n } catch (importError) {\n elizaLogger.error(\n `Failed to import plugin: ${plugin}`,\n importError\n );\n return []; // Return null for failed imports\n }\n })\n );\n return importedPlugins;\n } else {\n return [];\n }\n}\n\nexport function getTokenForProvider(\n provider: ModelProviderName,\n character: Character\n): string | undefined {\n switch (provider) {\n // no key needed for llama_local or gaianet\n case ModelProviderName.LLAMALOCAL:\n return \"\";\n case ModelProviderName.OLLAMA:\n return \"\";\n case ModelProviderName.GAIANET:\n return \"\";\n case ModelProviderName.BEDROCK:\n return \"\";\n case ModelProviderName.OPENAI:\n return (\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.ETERNALAI:\n return (\n character.settings?.secrets?.ETERNALAI_API_KEY ||\n settings.ETERNALAI_API_KEY\n );\n case ModelProviderName.NINETEEN_AI:\n return (\n character.settings?.secrets?.NINETEEN_AI_API_KEY ||\n settings.NINETEEN_AI_API_KEY\n );\n case ModelProviderName.LLAMACLOUD:\n case ModelProviderName.TOGETHER:\n return (\n character.settings?.secrets?.LLAMACLOUD_API_KEY ||\n settings.LLAMACLOUD_API_KEY ||\n character.settings?.secrets?.TOGETHER_API_KEY ||\n settings.TOGETHER_API_KEY ||\n character.settings?.secrets?.OPENAI_API_KEY ||\n settings.OPENAI_API_KEY\n );\n case ModelProviderName.CLAUDE_VERTEX:\n case ModelProviderName.ANTHROPIC:\n return (\n character.settings?.secrets?.ANTHROPIC_API_KEY ||\n character.settings?.secrets?.CLAUDE_API_KEY ||\n settings.ANTHROPIC_API_KEY ||\n settings.CLAUDE_API_KEY\n );\n case ModelProviderName.REDPILL:\n return (\n character.settings?.secrets?.REDPILL_API_KEY ||\n settings.REDPILL_API_KEY\n );\n case ModelProviderName.OPENROUTER:\n return (\n character.settings?.secrets?.OPENROUTER_API_KEY ||\n settings.OPENROUTER_API_KEY\n );\n case ModelProviderName.GROK:\n return (\n character.settings?.secrets?.GROK_API_KEY ||\n settings.GROK_API_KEY\n );\n case ModelProviderName.HEURIST:\n return (\n character.settings?.secrets?.HEURIST_API_KEY ||\n settings.HEURIST_API_KEY\n );\n case ModelProviderName.GROQ:\n return (\n character.settings?.secrets?.GROQ_API_KEY ||\n settings.GROQ_API_KEY\n );\n case ModelProviderName.GALADRIEL:\n return (\n character.settings?.secrets?.GALADRIEL_API_KEY ||\n settings.GALADRIEL_API_KEY\n );\n case ModelProviderName.FAL:\n return (\n character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n );\n case ModelProviderName.ALI_BAILIAN:\n return (\n character.settings?.secrets?.ALI_BAILIAN_API_KEY ||\n settings.ALI_BAILIAN_API_KEY\n );\n case ModelProviderName.VOLENGINE:\n return (\n character.settings?.secrets?.VOLENGINE_API_KEY ||\n settings.VOLENGINE_API_KEY\n );\n case ModelProviderName.NANOGPT:\n return (\n character.settings?.secrets?.NANOGPT_API_KEY ||\n settings.NANOGPT_API_KEY\n );\n case ModelProviderName.HYPERBOLIC:\n return (\n character.settings?.secrets?.HYPERBOLIC_API_KEY ||\n settings.HYPERBOLIC_API_KEY\n );\n\n case ModelProviderName.VENICE:\n return (\n character.settings?.secrets?.VENICE_API_KEY ||\n settings.VENICE_API_KEY\n );\n case ModelProviderName.ATOMA:\n return (\n character.settings?.secrets?.ATOMASDK_BEARER_AUTH ||\n settings.ATOMASDK_BEARER_AUTH\n );\n case ModelProviderName.NVIDIA:\n return (\n character.settings?.secrets?.NVIDIA_API_KEY ||\n settings.NVIDIA_API_KEY\n );\n case ModelProviderName.AKASH_CHAT_API:\n return (\n character.settings?.secrets?.AKASH_CHAT_API_KEY ||\n settings.AKASH_CHAT_API_KEY\n );\n case ModelProviderName.GOOGLE:\n return (\n character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY ||\n settings.GOOGLE_GENERATIVE_AI_API_KEY\n );\n case ModelProviderName.MISTRAL:\n return (\n character.settings?.secrets?.MISTRAL_API_KEY ||\n settings.MISTRAL_API_KEY\n );\n case ModelProviderName.LETZAI:\n return (\n character.settings?.secrets?.LETZAI_API_KEY ||\n settings.LETZAI_API_KEY\n );\n case ModelProviderName.INFERA:\n return (\n character.settings?.secrets?.INFERA_API_KEY ||\n settings.INFERA_API_KEY\n );\n case ModelProviderName.DEEPSEEK:\n return (\n character.settings?.secrets?.DEEPSEEK_API_KEY ||\n settings.DEEPSEEK_API_KEY\n );\n case ModelProviderName.LIVEPEER:\n return (\n character.settings?.secrets?.LIVEPEER_GATEWAY_URL ||\n settings.LIVEPEER_GATEWAY_URL\n );\n default:\n const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;\n elizaLogger.error(errorMessage);\n throw new Error(errorMessage);\n }\n}\n\nfunction initializeDatabase(dataDir: string) {\n if (process.env.MONGODB_CONNECTION_STRING) {\n elizaLogger.log(\"Initializing database on MongoDB Atlas\");\n const client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n maxPoolSize: 100,\n minPoolSize: 5,\n maxIdleTimeMS: 60000,\n connectTimeoutMS: 10000,\n serverSelectionTimeoutMS: 5000,\n socketTimeoutMS: 45000,\n compressors: [\"zlib\"],\n retryWrites: true,\n retryReads: true,\n });\n\n const dbName = process.env.MONGODB_DATABASE || \"elizaAgent\";\n const db = new MongoDBDatabaseAdapter(client, dbName);\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\"Successfully connected to MongoDB Atlas\");\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n throw error; // Re-throw to handle it in the calling code\n });\n\n return db;\n } else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n elizaLogger.info(\"Initializing Supabase connection...\");\n const db = new SupabaseDatabaseAdapter(\n process.env.SUPABASE_URL,\n process.env.SUPABASE_ANON_KEY\n );\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to Supabase database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to Supabase:\", error);\n });\n\n return db;\n } else if (process.env.POSTGRES_URL) {\n elizaLogger.info(\"Initializing PostgreSQL connection...\");\n const db = new PostgresDatabaseAdapter({\n connectionString: process.env.POSTGRES_URL,\n parseInputs: true,\n });\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to PostgreSQL database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to PostgreSQL:\", error);\n });\n\n return db;\n } else if (process.env.PGLITE_DATA_DIR) {\n elizaLogger.info(\"Initializing PgLite adapter...\");\n // `dataDir: memory://` for in memory pg\n const db = new PGLiteDatabaseAdapter({\n dataDir: process.env.PGLITE_DATA_DIR,\n });\n return db;\n } else if (\n process.env.QDRANT_URL &&\n process.env.QDRANT_KEY &&\n process.env.QDRANT_PORT &&\n process.env.QDRANT_VECTOR_SIZE\n ) {\n elizaLogger.info(\"Initializing Qdrant adapter...\");\n const db = new QdrantDatabaseAdapter(\n process.env.QDRANT_URL,\n process.env.QDRANT_KEY,\n Number(process.env.QDRANT_PORT),\n Number(process.env.QDRANT_VECTOR_SIZE)\n );\n return db;\n } else {\n const filePath =\n process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\");\n elizaLogger.info(`Initializing SQLite database at ${filePath}...`);\n const db = new SqliteDatabaseAdapter(new Database(filePath));\n\n // Test the connection\n db.init()\n .then(() => {\n elizaLogger.success(\n \"Successfully connected to SQLite database\"\n );\n })\n .catch((error) => {\n elizaLogger.error(\"Failed to connect to SQLite:\", error);\n });\n\n return db;\n }\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(\n character: Character,\n runtime: IAgentRuntime\n) {\n // each client can only register once\n // and if we want two we can explicitly support it\n const clients: Record<string, any> = {};\n const clientTypes: string[] =\n character.clients?.map((str) => str.toLowerCase()) || [];\n elizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name);\n\n // Start Auto Client if \"auto\" detected as a configured client\n if (clientTypes.includes(Clients.AUTO)) {\n const autoClient = await AutoClientInterface.start(runtime);\n if (autoClient) clients.auto = autoClient;\n }\n\n if (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n if (clientTypes.includes(Clients.DISCORD)) {\n const discordClient = await DiscordClientInterface.start(runtime);\n if (discordClient) clients.discord = discordClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM)) {\n const telegramClient = await TelegramClientInterface.start(runtime);\n if (telegramClient) clients.telegram = telegramClient;\n }\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient =\n await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient)\n clients.telegram_account = telegramAccountClient;\n }\n\n if (clientTypes.includes(Clients.TWITTER)) {\n const twitterClient = await TwitterClientInterface.start(runtime);\n if (twitterClient) {\n clients.twitter = twitterClient;\n }\n }\n\n if (clientTypes.includes(Clients.ALEXA)) {\n const alexaClient = await AlexaClientInterface.start(runtime);\n if (alexaClient) {\n clients.alexa = alexaClient;\n }\n }\n\n if (clientTypes.includes(Clients.INSTAGRAM)) {\n const instagramClient = await InstagramClientInterface.start(runtime);\n if (instagramClient) {\n clients.instagram = instagramClient;\n }\n }\n\n if (clientTypes.includes(Clients.FARCASTER)) {\n const farcasterClient = await FarcasterClientInterface.start(runtime);\n if (farcasterClient) {\n clients.farcaster = farcasterClient;\n }\n }\n\n if (clientTypes.includes(\"lens\")) {\n const lensClient = new LensAgentClient(runtime);\n lensClient.start();\n clients.lens = lensClient;\n }\n\n if (clientTypes.includes(Clients.SIMSAI)) {\n const simsaiClient = await JeeterClientInterface.start(runtime);\n if (simsaiClient) clients.simsai = simsaiClient;\n }\n\n elizaLogger.log(\"client keys\", Object.keys(clients));\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n if (clientTypes.includes(\"slack\")) {\n const slackClient = await SlackClientInterface.start(runtime);\n if (slackClient) clients.slack = slackClient; // Use object property instead of push\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n // Check constructor name\n const constructorName = client.constructor?.name;\n if (constructorName && !constructorName.includes(\"Object\")) {\n return constructorName.toLowerCase().replace(\"client\", \"\");\n }\n\n // Fallback: Generate a unique identifier\n return `client_${Date.now()}`;\n }\n\n if (character.plugins?.length > 0) {\n for (const plugin of character.plugins) {\n if (plugin.clients) {\n for (const client of plugin.clients) {\n const startedClient = await client.start(runtime);\n const clientType = determineClientType(client);\n elizaLogger.debug(\n `Initializing client of type: ${clientType}`\n );\n clients[clientType] = startedClient;\n }\n }\n }\n }\n\n return clients;\n}\n\nfunction getSecret(character: Character, secret: string) {\n return character.settings?.secrets?.[secret] || process.env[secret];\n}\n\nlet nodePlugin: any | undefined;\n\nexport async function createAgent(\n character: Character,\n db: IDatabaseAdapter,\n cache: ICacheManager,\n token: string\n): Promise<AgentRuntime> {\n elizaLogger.log(`Creating runtime for character ${character.name}`);\n\n nodePlugin ??= createNodePlugin();\n\n const teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\";\n const walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\");\n\n // Validate TEE configuration\n if (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n elizaLogger.error(\n \"A WALLET_SECRET_SALT required when TEE_MODE is enabled\"\n );\n throw new Error(\"Invalid TEE configuration\");\n }\n\n let goatPlugin: any | undefined;\n\n if (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n goatPlugin = await createGoatPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n // Initialize Reclaim adapter if environment variables are present\n // let verifiableInferenceAdapter;\n // if (\n // process.env.RECLAIM_APP_ID &&\n // process.env.RECLAIM_APP_SECRET &&\n // process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n // ) {\n // verifiableInferenceAdapter = new ReclaimAdapter({\n // appId: process.env.RECLAIM_APP_ID,\n // appSecret: process.env.RECLAIM_APP_SECRET,\n // modelProvider: character.modelProvider,\n // token,\n // });\n // elizaLogger.log(\"Verifiable inference adapter initialized\");\n // }\n // Initialize Opacity adapter if environment variables are present\n let verifiableInferenceAdapter;\n if (\n process.env.OPACITY_TEAM_ID &&\n process.env.OPACITY_CLOUDFLARE_NAME &&\n process.env.OPACITY_PROVER_URL &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new OpacityAdapter({\n teamId: process.env.OPACITY_TEAM_ID,\n teamName: process.env.OPACITY_CLOUDFLARE_NAME,\n opacityProverUrl: process.env.OPACITY_PROVER_URL,\n modelProvider: character.modelProvider,\n token: token,\n });\n elizaLogger.log(\"Verifiable inference adapter initialized\");\n elizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID);\n elizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME);\n elizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL);\n elizaLogger.log(\"modelProvider\", character.modelProvider);\n elizaLogger.log(\"token\", token);\n }\n if (\n process.env.PRIMUS_APP_ID &&\n process.env.PRIMUS_APP_SECRET &&\n process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n ) {\n verifiableInferenceAdapter = new PrimusAdapter({\n appId: process.env.PRIMUS_APP_ID,\n appSecret: process.env.PRIMUS_APP_SECRET,\n attMode: \"proxytls\",\n modelProvider: character.modelProvider,\n token,\n });\n elizaLogger.log(\"Verifiable inference primus adapter initialized\");\n }\n\n return new AgentRuntime({\n databaseAdapter: db,\n token,\n modelProvider: character.modelProvider,\n evaluators: [],\n character,\n // character.plugins are handled when clients are added\n plugins: [\n parseBooleanFromText(getSecret(character, \"BITMIND\")) &&\n getSecret(character, \"BITMIND_API_TOKEN\")\n ? bittensorPlugin\n : null,\n parseBooleanFromText(\n getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")\n )\n ? emailAutomationPlugin\n : null,\n getSecret(character, \"IQ_WALLET_ADDRESS\") &&\n getSecret(character, \"IQSOlRPC\")\n ? elizaCodeinPlugin\n : null,\n bootstrapPlugin,\n getSecret(character, \"CDP_API_KEY_NAME\") &&\n getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") &&\n getSecret(character, \"CDP_AGENT_KIT_NETWORK\")\n ? agentKitPlugin\n : null,\n getSecret(character, \"DEXSCREENER_API_KEY\")\n ? dexScreenerPlugin\n : null,\n getSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n getSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\")\n ? confluxPlugin\n : null,\n nodePlugin,\n getSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\")\n ? nitroPlugin\n : null,\n getSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? [solanaPlugin, solanaPluginV2]\n : null,\n getSecret(character, \"SOLANA_PRIVATE_KEY\")\n ? solanaAgentkitPlugin\n : null,\n getSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n (getSecret(character, \"NEAR_ADDRESS\") ||\n getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) &&\n getSecret(character, \"NEAR_WALLET_SECRET_KEY\")\n ? nearPlugin\n : null,\n getSecret(character, \"EVM_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))\n ? evmPlugin\n : null,\n (getSecret(character, \"EVM_PUBLIC_KEY\") ||\n getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) &&\n getSecret(character, \"INJECTIVE_PRIVATE_KEY\")\n ? injectivePlugin\n : null,\n getSecret(character, \"COSMOS_RECOVERY_PHRASE\") &&\n getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") &&\n createCosmosPlugin(),\n (getSecret(character, \"SOLANA_PUBLIC_KEY\") ||\n (getSecret(character, \"WALLET_PUBLIC_KEY\") &&\n !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\n \"0x\"\n ))) &&\n getSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n getSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n getSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n ? nftGenerationPlugin\n : null,\n getSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n getSecret(character, \"COINMARKETCAP_API_KEY\")\n ? coinmarketcapPlugin\n : null,\n getSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n getSecret(character, \"COINBASE_COMMERCE_KEY\")\n ? coinbaseCommercePlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ||\n getSecret(character, \"OPENAI_API_KEY\") ||\n getSecret(character, \"VENICE_API_KEY\") ||\n getSecret(character, \"NVIDIA_API_KEY\") ||\n getSecret(character, \"NINETEEN_AI_API_KEY\") ||\n getSecret(character, \"HEURIST_API_KEY\") ||\n getSecret(character, \"LIVEPEER_GATEWAY_URL\")\n ? imageGenerationPlugin\n : null,\n getSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n ...(getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\")\n ? [\n coinbaseMassPaymentsPlugin,\n tradePlugin,\n tokenContractPlugin,\n advancedTradePlugin,\n ]\n : []),\n ...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n teeMode !== TEEMode.OFF &&\n walletSecretSalt &&\n getSecret(character, \"VLOG\")\n ? verifiableLogPlugin\n : null,\n getSecret(character, \"SGX\") ? sgxPlugin : null,\n getSecret(character, \"ENABLE_TEE_LOG\") &&\n ((teeMode !== TEEMode.OFF && walletSecretSalt) ||\n getSecret(character, \"SGX\"))\n ? teeLogPlugin\n : null,\n getSecret(character, \"OMNIFLIX_API_URL\") &&\n getSecret(character, \"OMNIFLIX_MNEMONIC\")\n ? OmniflixPlugin\n : null,\n getSecret(character, \"COINBASE_API_KEY\") &&\n getSecret(character, \"COINBASE_PRIVATE_KEY\") &&\n getSecret(character, \"COINBASE_NOTIFICATION_URI\")\n ? webhookPlugin\n : null,\n goatPlugin,\n zilliqaPlugin,\n getSecret(character, \"COINGECKO_API_KEY\") ||\n getSecret(character, \"COINGECKO_PRO_API_KEY\")\n ? coingeckoPlugin\n : null,\n getSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n getSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n getSecret(character, \"ABSTRACT_PRIVATE_KEY\")\n ? abstractPlugin\n : null,\n getSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n getSecret(character, \"BINANCE_API_KEY\") &&\n getSecret(character, \"BINANCE_SECRET_KEY\")\n ? binancePlugin\n : null,\n getSecret(character, \"FLOW_ADDRESS\") &&\n getSecret(character, \"FLOW_PRIVATE_KEY\")\n ? flowPlugin\n : null,\n getSecret(character, \"LENS_ADDRESS\") &&\n getSecret(character, \"LENS_PRIVATE_KEY\")\n ? lensPlugin\n : null,\n getSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n getSecret(character, \"MIND_COLD_WALLET_ADDRESS\")\n ? mindNetworkPlugin\n : null,\n getSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n getSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n getSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\")\n ? cronosZkEVMPlugin\n : null,\n getSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n getSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n getSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n getSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n getSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n getSecret(character, \"SQUID_SDK_URL\") &&\n getSecret(character, \"SQUID_INTEGRATOR_ID\") &&\n getSecret(character, \"SQUID_EVM_ADDRESS\") &&\n getSecret(character, \"SQUID_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"SQUID_API_THROTTLE_INTERVAL\")\n ? squidRouterPlugin\n : null,\n getSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n getSecret(character, \"AVALANCHE_PRIVATE_KEY\")\n ? avalanchePlugin\n : null,\n getSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n getSecret(character, \"ECHOCHAMBERS_API_URL\") &&\n getSecret(character, \"ECHOCHAMBERS_API_KEY\")\n ? echoChambersPlugin\n : null,\n getSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n getSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n getSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n getSecret(character, \"PASSPORT_API_KEY\")\n ? gitcoinPassportPlugin\n : null,\n getSecret(character, \"GENLAYER_PRIVATE_KEY\")\n ? genLayerPlugin\n : null,\n getSecret(character, \"AVAIL_SEED\") &&\n getSecret(character, \"AVAIL_APP_ID\")\n ? availPlugin\n : null,\n getSecret(character, \"OPEN_WEATHER_API_KEY\")\n ? openWeatherPlugin\n : null,\n getSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n getSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\")\n ? artheraPlugin\n : null,\n getSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n getSecret(character, \"HYPERLIQUID_PRIVATE_KEY\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"HYPERLIQUID_TESTNET\")\n ? hyperliquidPlugin\n : null,\n getSecret(character, \"AKASH_MNEMONIC\") &&\n getSecret(character, \"AKASH_WALLET_ADDRESS\")\n ? akashPlugin\n : null,\n getSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n getSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n getSecret(character, \"RESERVOIR_API_KEY\")\n ? createNFTCollectionsPlugin()\n : null,\n getSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n getSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n getSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") ||\n getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\")\n ? pythDataPlugin\n : null,\n getSecret(character, \"LND_TLS_CERT\") &&\n getSecret(character, \"LND_MACAROON\") &&\n getSecret(character, \"LND_SOCKET\")\n ? lightningPlugin\n : null,\n getSecret(character, \"OPENAI_API_KEY\") &&\n parseBooleanFromText(\n getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")\n )\n ? openaiPlugin\n : null,\n getSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n getSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n getSecret(character, \"HOLDSTATION_PRIVATE_KEY\")\n ? holdstationPlugin\n : null,\n getSecret(character, \"NVIDIA_NIM_API_KEY\") ||\n getSecret(character, \"NVIDIA_NGC_API_KEY\")\n ? nvidiaNimPlugin\n : null,\n getSecret(character, \"BNB_PRIVATE_KEY\") ||\n getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\")\n ? bnbPlugin\n : null,\n (getSecret(character, \"EMAIL_INCOMING_USER\") &&\n getSecret(character, \"EMAIL_INCOMING_PASS\")) ||\n (getSecret(character, \"EMAIL_OUTGOING_USER\") &&\n getSecret(character, \"EMAIL_OUTGOING_PASS\"))\n ? emailPlugin\n : null,\n getSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n getSecret(character, \"HYPERBOLIC_API_KEY\")\n ? hyperbolicPlugin\n : null,\n getSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n getSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n getSecret(character, \"IMGFLIP_USERNAME\") &&\n getSecret(character, \"IMGFLIP_PASSWORD\")\n ? imgflipPlugin\n : null,\n getSecret(character, \"FUNDING_PRIVATE_KEY\") &&\n getSecret(character, \"EVM_RPC_URL\")\n ? litPlugin\n : null,\n getSecret(character, \"ETHSTORAGE_PRIVATE_KEY\")\n ? ethstoragePlugin\n : null,\n getSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n getSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n getSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n getSecret(character, \"DCAP_EVM_PRIVATE_KEY\") &&\n getSecret(character, \"DCAP_MODE\")\n ? dcapPlugin\n : null,\n getSecret(character, \"QUICKINTEL_API_KEY\")\n ? quickIntelPlugin\n : null,\n getSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n getSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n getSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") &&\n (getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\") ||\n getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) &&\n getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") &&\n getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\")\n ? arbitragePlugin\n : null,\n ]\n .flat()\n .filter(Boolean),\n providers: [],\n managers: [],\n cacheManager: cache,\n fetch: logFetch,\n verifiableInferenceAdapter,\n });\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cacheDir = path.resolve(baseDir, character.id, \"cache\");\n\n const cache = new CacheManager(new FsCacheAdapter(cacheDir));\n return cache;\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n if (!character?.id) {\n throw new Error(\n \"initializeFsCache requires id to be set in character definition\"\n );\n }\n const cache = new CacheManager(new DbCacheAdapter(db, character.id));\n return cache;\n}\n\nfunction initializeCache(\n cacheStore: string,\n character: Character,\n baseDir?: string,\n db?: IDatabaseCacheAdapter\n) {\n switch (cacheStore) {\n case CacheStore.REDIS:\n if (process.env.REDIS_URL) {\n elizaLogger.info(\"Connecting to Redis...\");\n const redisClient = new RedisClient(process.env.REDIS_URL);\n if (!character?.id) {\n throw new Error(\n \"CacheStore.REDIS requires id to be set in character definition\"\n );\n }\n return new CacheManager(\n new DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n );\n } else {\n throw new Error(\"REDIS_URL environment variable is not set.\");\n }\n\n case CacheStore.DATABASE:\n if (db) {\n elizaLogger.info(\"Using Database Cache...\");\n return initializeDbCache(character, db);\n } else {\n throw new Error(\n \"Database adapter is not provided for CacheStore.Database.\"\n );\n }\n\n case CacheStore.FILESYSTEM:\n elizaLogger.info(\"Using File System Cache...\");\n if (!baseDir) {\n throw new Error(\n \"baseDir must be provided for CacheStore.FILESYSTEM.\"\n );\n }\n return initializeFsCache(baseDir, character);\n\n default:\n throw new Error(\n `Invalid cache store: ${cacheStore} or required configuration missing.`\n );\n }\n}\n\nasync function startAgent(\n character: Character,\n directClient: DirectClient\n): Promise<AgentRuntime> {\n let db: IDatabaseAdapter & IDatabaseCacheAdapter;\n try {\n character.id ??= stringToUuid(character.name);\n character.username ??= character.name;\n\n const token = getTokenForProvider(character.modelProvider, character);\n const dataDir = path.join(__dirname, \"../data\");\n\n if (!fs.existsSync(dataDir)) {\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n db = initializeDatabase(dataDir) as IDatabaseAdapter &\n IDatabaseCacheAdapter;\n\n await db.init();\n\n const cache = initializeCache(\n process.env.CACHE_STORE ?? CacheStore.DATABASE,\n character,\n \"\",\n db\n ); // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n const runtime: AgentRuntime = await createAgent(\n character,\n db,\n cache,\n token\n );\n\n // start services/plugins/process knowledge\n await runtime.initialize();\n\n // start assigned clients\n runtime.clients = await initializeClients(character, runtime);\n\n // add to container\n directClient.registerAgent(runtime);\n\n // report to console\n elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);\n\n return runtime;\n } catch (error) {\n elizaLogger.error(\n `Error starting agent for character ${character.name}:`,\n error\n );\n elizaLogger.error(error);\n if (db) {\n await db.close();\n }\n throw error;\n }\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n};\n\nconst hasValidRemoteUrls = () =>\n process.env.REMOTE_CHARACTER_URLS &&\n process.env.REMOTE_CHARACTER_URLS !== \"\" &&\n process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\");\n\nconst startAgents = async () => {\n const directClient = new DirectClient();\n let serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\");\n const args = parseArguments();\n const charactersArg = args.characters || args.character;\n let characters = [defaultCharacter];\n\n if (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n characters = await loadCharacterFromOnchain();\n }\n\n const notOnchainJson = !onchainJson || onchainJson == \"null\";\n\n if ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n characters = await loadCharacters(charactersArg);\n }\n\n // Normalize characters for injectable plugins\n characters = await Promise.all(characters.map(normalizeCharacter));\n\n try {\n for (const character of characters) {\n await startAgent(character, directClient);\n }\n } catch (error) {\n elizaLogger.error(\"Error starting agents:\", error);\n }\n\n // Find available port\n while (!(await checkPortAvailable(serverPort))) {\n elizaLogger.warn(\n `Port ${serverPort} is in use, trying ${serverPort + 1}`\n );\n serverPort++;\n }\n\n // upload some agent functionality into directClient\n directClient.startAgent = async (character) => {\n // Handle plugins\n character.plugins = await handlePluginImporting(character.plugins);\n\n // wrap it so we don't have to inject directClient later\n return startAgent(character, directClient);\n };\n\n directClient.loadCharacterTryPath = loadCharacterTryPath;\n directClient.jsonToCharacter = jsonToCharacter;\n\n directClient.start(serverPort);\n\n if (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n elizaLogger.log(`Server started on alternate port ${serverPort}`);\n }\n\n elizaLogger.log(\n \"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\"\n );\n};\n\nstartAgents().catch((error) => {\n elizaLogger.error(\"Unhandled error in startAgents:\", error);\n process.exit(1);\n});\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n process.env.PREVENT_UNHANDLED_EXIT &&\n parseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n // Handle uncaught exceptions to prevent the process from crashing\n process.on(\"uncaughtException\", function (err) {\n console.error(\"uncaughtException\", err);\n });\n\n // Handle unhandled rejections to prevent the process from crashing\n process.on(\"unhandledRejection\", function (err) {\n console.error(\"unhandledRejection\", err);\n });\n}\n"}, "ffc81c80f1058bfa2dce306c48654fd7e2b7ae13": {"t": 1785754689.0604386, "n": 48081, "h": "8821d553adda47fd", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\"\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\"\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\"\nimport { RedisClient } from \"@elizaos/adapter-redis\"\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\"\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\"\nimport { AutoClientInterface } from \"@elizaos/client-auto\"\nimport { DiscordClientInterface } from \"@elizaos/client-discord\"\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\"\nimport { LensAgentClient } from \"@elizaos/client-lens\"\nimport { SlackClientInterface } from \"@elizaos/client-slack\"\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\"\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\"\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\"\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\"\nimport { DevaClientInterface } from \"@elizaos/client-deva\"\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\"\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\"\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\"\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\"\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\"\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\"\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\"\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\"\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\"\nimport {\n\tAgentRuntime,\n\tCacheManager,\n\tCacheStore,\n\ttype Character,\n\ttype Client,\n\tClients,\n\tDbCacheAdapter,\n\tdefaultCharacter,\n\telizaLogger,\n\tFsCacheAdapter,\n\ttype IAgentRuntime,\n\ttype ICacheManager,\n\ttype IDatabaseAdapter,\n\ttype IDatabaseCacheAdapter,\n\tModelProviderName,\n\tparseBooleanFromText,\n\tsettings,\n\tstringToUuid,\n\tvalidateCharacterConfig,\n} from \"@elizaos/core\"\nimport { zgPlugin } from \"@elizaos/plugin-0g\"\nimport { footballPlugin } from \"@elizaos/plugin-football\"\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\"\nimport { normalizeCharacter } from \"@elizaos/plugin-di\"\nimport createGoatPlugin from \"@elizaos/plugin-goat\"\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\"\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\"\nimport { akashPlugin } from \"@elizaos/plugin-akash\"\nimport { alloraPlugin } from \"@elizaos/plugin-allora\"\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\"\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\"\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\"\nimport { availPlugin } from \"@elizaos/plugin-avail\"\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\"\nimport { b2Plugin } from \"@elizaos/plugin-b2\"\nimport { binancePlugin } from \"@elizaos/plugin-binance\"\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\"\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\"\nimport { advancedTradePlugin, coinbaseCommercePlugin, coinbaseMassPaymentsPlugin, tokenContractPlugin, tradePlugin, webhookPlugin } from \"@elizaos/plugin-coinbase\"\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\"\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\"\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\"\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\"\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\"\nimport { evmPlugin } from \"@elizaos/plugin-evm\"\nimport { flowPlugin } from \"@elizaos/plugin-flow\"\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\"\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\"\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\"\nimport { initiaPlugin } from \"@elizaos/plugin-initia\"\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\"\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\"\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\"\nimport { nearPlugin } from \"@elizaos/plugin-near\"\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\"\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\"\nimport { createNodePlugin } from \"@elizaos/plugin-node\"\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\"\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\"\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\"\nimport { quaiPlugin } from \"@elizaos/plugin-quai\"\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\"\nimport { solanaPlugin } from \"@elizaos/plugin-solana\"\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\"\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\"\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\"\nimport { storyPlugin } from \"@elizaos/plugin-story\"\nimport { suiPlugin } from \"@elizaos/plugin-sui\"\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\"\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\"\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\"\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\"\nimport { tonPlugin } from \"@elizaos/plugin-ton\"\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\"\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\"\nimport { injectivePlugin } from \"@elizaos/plugin-injective\"\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\"\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\"\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\"\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\"\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\"\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\"\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\"\nimport { openaiPlugin } from \"@elizaos/plugin-openai\"\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\"\nimport { devinPlugin } from \"@elizaos/plugin-devin\"\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\"\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\"\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\"\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\"\nimport { zxPlugin } from \"@elizaos/plugin-0x\"\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\"\nimport { litPlugin } from \"@elizaos/plugin-lit\"\nimport Database from \"better-sqlite3\"\nimport fs from \"fs\"\nimport net from \"net\"\nimport path from \"path\"\nimport { fileURLToPath } from \"url\"\nimport yargs from \"yargs\"\nimport { emailPlugin } from \"@elizaos/plugin-email\"\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\"\nimport { sunoPlugin } from \"@elizaos/plugin-suno\"\nimport { udioPlugin } from \"@elizaos/plugin-udio\"\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\"\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\"\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\"\nimport { minaPlugin } from \"@elizaos/plugin-mina\"\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\"\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\"\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\"\nconst __filename = fileURLToPath(import.meta.url) // get the resolved path to the file\nconst __dirname = path.dirname(__filename) // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n\tconst waitTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime\n\treturn new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\nconst logFetch = async (url: string, options: any) => {\n\telizaLogger.debug(`Fetching ${url}`)\n\t// Disabled to avoid disclosure of sensitive information such as API keys\n\t// elizaLogger.debug(JSON.stringify(options, null, 2));\n\treturn fetch(url, options)\n}\n\nexport function parseArguments(): {\n\tcharacter?: string\n\tcharacters?: string\n} {\n\ttry {\n\t\treturn yargs(process.argv.slice(3))\n\t\t\t.option(\"character\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Path to the character JSON file\",\n\t\t\t})\n\t\t\t.option(\"characters\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Comma separated list of paths to character JSON files\",\n\t\t\t})\n\t\t\t.parseSync()\n\t} catch (error) {\n\t\telizaLogger.error(\"Error parsing arguments:\", error)\n\t\treturn {}\n\t}\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n\ttry {\n\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t} catch (e) {\n\t\treturn null\n\t}\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n\tconst mergeObjects = (baseObj: any, childObj: any) => {\n\t\tconst result: any = {}\n\t\tconst keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})])\n\t\tkeys.forEach((key) => {\n\t\t\tif (typeof baseObj[key] === \"object\" && typeof childObj[key] === \"object\" && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = mergeObjects(baseObj[key], childObj[key])\n\t\t\t} else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = [...(baseObj[key] || []), ...(childObj[key] || [])]\n\t\t\t} else {\n\t\t\t\tresult[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key]\n\t\t\t}\n\t\t})\n\t\treturn result\n\t}\n\treturn mergeObjects(base, child)\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n\treturn Array.isArray(arr) && arr.every((item) => typeof item === \"string\")\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n\tconst jsonText = onchainJson\n\n\tconsole.log(\"JSON:\", jsonText)\n\tif (!jsonText) return []\n\tconst loadedCharacters = []\n\ttry {\n\t\tconst character = JSON.parse(jsonText)\n\t\tvalidateCharacterConfig(character)\n\n\t\t// .id isn't really valid\n\t\tconst characterId = character.id || character.name\n\t\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\n\t\tconst characterSettings = Object.entries(process.env)\n\t\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t\t.reduce((settings, [key, value]) => {\n\t\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\t\tsettings[settingKey] = value\n\t\t\t\treturn settings\n\t\t\t}, {})\n\n\t\tif (Object.keys(characterSettings).length > 0) {\n\t\t\tcharacter.settings = character.settings || {}\n\t\t\tcharacter.settings.secrets = {\n\t\t\t\t...characterSettings,\n\t\t\t\t...character.settings.secrets,\n\t\t\t}\n\t\t}\n\n\t\t// Handle plugins\n\t\tif (isAllStrings(character.plugins)) {\n\t\t\telizaLogger.info(\"Plugins are: \", character.plugins)\n\t\t\tconst importedPlugins = await Promise.all(\n\t\t\t\tcharacter.plugins.map(async (plugin) => {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\treturn importedPlugin.default\n\t\t\t\t})\n\t\t\t)\n\t\t\tcharacter.plugins = importedPlugins\n\t\t}\n\n\t\tloadedCharacters.push(character)\n\t\telizaLogger.info(`Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`)\n\t\treturn loadedCharacters\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n\ttry {\n\t\tconst response = await fetch(url)\n\t\tconst responseJson = await response.json()\n\n\t\tlet characters: Character[] = []\n\t\tif (Array.isArray(responseJson)) {\n\t\t\tcharacters = await Promise.all(responseJson.map((character) => jsonToCharacter(url, character)))\n\t\t} else {\n\t\t\tconst character = await jsonToCharacter(url, responseJson)\n\t\t\tcharacters.push(character)\n\t\t}\n\t\treturn characters\n\t} catch (e) {\n\t\telizaLogger.error(`Error loading character(s) from ${url}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function jsonToCharacter(filePath: string, character: any): Promise<Character> {\n\tvalidateCharacterConfig(character)\n\n\t// .id isn't really valid\n\tconst characterId = character.id || character.name\n\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\tconst characterSettings = Object.entries(process.env)\n\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t.reduce((settings, [key, value]) => {\n\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\treturn { ...settings, [settingKey]: value }\n\t\t}, {})\n\tif (Object.keys(characterSettings).length > 0) {\n\t\tcharacter.settings = character.settings || {}\n\t\tcharacter.settings.secrets = {\n\t\t\t...characterSettings,\n\t\t\t...character.settings.secrets,\n\t\t}\n\t}\n\t// Handle plugins\n\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\tif (character.extends) {\n\t\telizaLogger.info(`Merging ${character.name} character with parent characters`)\n\t\tfor (const extendPath of character.extends) {\n\t\t\tconst baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath))\n\t\t\tcharacter = mergeCharacters(baseCharacter, character)\n\t\t\telizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`)\n\t\t}\n\t}\n\treturn character\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n\tconst content = tryLoadFile(filePath)\n\tif (!content) {\n\t\tthrow new Error(`Character file not found: ${filePath}`)\n\t}\n\tconst character = JSON.parse(content)\n\treturn jsonToCharacter(filePath, character)\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n\tlet content: string | null = null\n\tlet resolvedPath = \"\"\n\n\t// Try different path resolutions in order\n\tconst pathsToTry = [\n\t\tcharacterPath, // exact path as specified\n\t\tpath.resolve(process.cwd(), characterPath), // relative to cwd\n\t\tpath.resolve(process.cwd(), \"agent\", characterPath), // Add this\n\t\tpath.resolve(__dirname, characterPath), // relative to current script\n\t\tpath.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n\t\tpath.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n\t\tpath.resolve(__dirname, \"../../characters\", path.basename(characterPath)), // relative to project root characters dir\n\t]\n\n\telizaLogger.info(\n\t\t\"Trying paths:\",\n\t\tpathsToTry.map((p) => ({\n\t\t\tpath: p,\n\t\t\texists: fs.existsSync(p),\n\t\t}))\n\t)\n\n\tfor (const tryPath of pathsToTry) {\n\t\tcontent = tryLoadFile(tryPath)\n\t\tif (content !== null) {\n\t\t\tresolvedPath = tryPath\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (content === null) {\n\t\telizaLogger.error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t\telizaLogger.error(\"Tried the following paths:\")\n\t\tpathsToTry.forEach((p) => elizaLogger.error(` - ${p}`))\n\t\tthrow new Error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t}\n\ttry {\n\t\tconst character: Character = await loadCharacter(resolvedPath)\n\t\telizaLogger.info(`Successfully loaded character from: ${resolvedPath}`)\n\t\treturn character\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t\tthrow new Error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t}\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n\treturn commaSeparated?.split(\",\").map((value) => value.trim())\n}\n\nasync function readCharactersFromStorage(characterPaths: string[]): Promise<string[]> {\n\ttry {\n\t\tconst uploadDir = path.join(process.cwd(), \"data\", \"characters\")\n\t\tawait fs.promises.mkdir(uploadDir, { recursive: true })\n\t\tconst fileNames = await fs.promises.readdir(uploadDir)\n\t\tfileNames.forEach((fileName) => {\n\t\t\tcharacterPaths.push(path.join(uploadDir, fileName))\n\t\t})\n\t} catch (err) {\n\t\telizaLogger.error(`Error reading directory: ${err.message}`)\n\t}\n\n\treturn characterPaths\n}\n\nexport async function loadCharacters(charactersArg: string): Promise<Character[]> {\n\tlet characterPaths = commaSeparatedStringToArray(charactersArg)\n\n\tif (process.env.USE_CHARACTER_STORAGE === \"true\") {\n\t\tcharacterPaths = await readCharactersFromStorage(characterPaths)\n\t}\n\n\tconst loadedCharacters: Character[] = []\n\n\tif (characterPaths?.length > 0) {\n\t\tfor (const characterPath of characterPaths) {\n\t\t\ttry {\n\t\t\t\tconst character: Character = await loadCharacterTryPath(characterPath)\n\t\t\t\tloadedCharacters.push(character)\n\t\t\t} catch (e) {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasValidRemoteUrls()) {\n\t\telizaLogger.info(\"Loading characters from remote URLs\")\n\t\tconst characterUrls = commaSeparatedStringToArray(process.env.REMOTE_CHARACTER_URLS)\n\t\tfor (const characterUrl of characterUrls) {\n\t\t\tconst characters = await loadCharactersFromUrl(characterUrl)\n\t\t\tloadedCharacters.push(...characters)\n\t\t}\n\t}\n\n\tif (loadedCharacters.length === 0) {\n\t\telizaLogger.info(\"No characters found, using default character\")\n\t\tloadedCharacters.push(defaultCharacter)\n\t}\n\n\treturn loadedCharacters\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n\tif (plugins.length > 0) {\n\t\telizaLogger.info(\"Plugins are: \", plugins)\n\t\tconst importedPlugins = await Promise.all(\n\t\t\tplugins.map(async (plugin) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\tconst functionName = plugin.replace(\"@elizaos/plugin-\", \"\").replace(/-./g, (x) => x[1].toUpperCase()) + \"Plugin\" // Assumes plugin function is camelCased with Plugin suffix\n\t\t\t\t\treturn importedPlugin.default || importedPlugin[functionName]\n\t\t\t\t} catch (importError) {\n\t\t\t\t\telizaLogger.error(`Failed to import plugin: ${plugin}`, importError)\n\t\t\t\t\treturn [] // Return null for failed imports\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\treturn importedPlugins\n\t} else {\n\t\treturn []\n\t}\n}\n\nexport function getTokenForProvider(provider: ModelProviderName, character: Character): string | undefined {\n\tswitch (provider) {\n\t\t// no key needed for llama_local or gaianet\n\t\tcase ModelProviderName.LLAMALOCAL:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OLLAMA:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.GAIANET:\n\t\t\treturn \"\";\n\t\tcase ModelProviderName.BEDROCK:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OPENAI:\n\t\t\treturn character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.ETERNALAI:\n\t\t\treturn character.settings?.secrets?.ETERNALAI_API_KEY || settings.ETERNALAI_API_KEY\n\t\tcase ModelProviderName.NINETEEN_AI:\n\t\t\treturn character.settings?.secrets?.NINETEEN_AI_API_KEY || settings.NINETEEN_AI_API_KEY\n\t\tcase ModelProviderName.LLAMACLOUD:\n\t\tcase ModelProviderName.TOGETHER:\n\t\t\treturn character.settings?.secrets?.LLAMACLOUD_API_KEY || settings.LLAMACLOUD_API_KEY || character.settings?.secrets?.TOGETHER_API_KEY || settings.TOGETHER_API_KEY || character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.CLAUDE_VERTEX:\n\t\tcase ModelProviderName.ANTHROPIC:\n\t\t\treturn character.settings?.secrets?.ANTHROPIC_API_KEY || character.settings?.secrets?.CLAUDE_API_KEY || settings.ANTHROPIC_API_KEY || settings.CLAUDE_API_KEY\n\t\tcase ModelProviderName.REDPILL:\n\t\t\treturn character.settings?.secrets?.REDPILL_API_KEY || settings.REDPILL_API_KEY\n\t\tcase ModelProviderName.OPENROUTER:\n\t\t\treturn character.settings?.secrets?.OPENROUTER_API_KEY || settings.OPENROUTER_API_KEY\n\t\tcase ModelProviderName.GROK:\n\t\t\treturn character.settings?.secrets?.GROK_API_KEY || settings.GROK_API_KEY\n\t\tcase ModelProviderName.HEURIST:\n\t\t\treturn character.settings?.secrets?.HEURIST_API_KEY || settings.HEURIST_API_KEY\n\t\tcase ModelProviderName.GROQ:\n\t\t\treturn character.settings?.secrets?.GROQ_API_KEY || settings.GROQ_API_KEY\n\t\tcase ModelProviderName.GALADRIEL:\n\t\t\treturn character.settings?.secrets?.GALADRIEL_API_KEY || settings.GALADRIEL_API_KEY\n\t\tcase ModelProviderName.FAL:\n\t\t\treturn character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n\t\tcase ModelProviderName.ALI_BAILIAN:\n\t\t\treturn character.settings?.secrets?.ALI_BAILIAN_API_KEY || settings.ALI_BAILIAN_API_KEY\n\t\tcase ModelProviderName.VOLENGINE:\n\t\t\treturn character.settings?.secrets?.VOLENGINE_API_KEY || settings.VOLENGINE_API_KEY\n\t\tcase ModelProviderName.NANOGPT:\n\t\t\treturn character.settings?.secrets?.NANOGPT_API_KEY || settings.NANOGPT_API_KEY\n\t\tcase ModelProviderName.HYPERBOLIC:\n\t\t\treturn character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY\n\n\t\tcase ModelProviderName.VENICE:\n\t\t\treturn character.settings?.secrets?.VENICE_API_KEY || settings.VENICE_API_KEY\n\t\tcase ModelProviderName.ATOMA:\n\t\t\treturn character.settings?.secrets?.ATOMASDK_BEARER_AUTH || settings.ATOMASDK_BEARER_AUTH\n\t\tcase ModelProviderName.NVIDIA:\n\t\t\treturn character.settings?.secrets?.NVIDIA_API_KEY || settings.NVIDIA_API_KEY\n\t\tcase ModelProviderName.AKASH_CHAT_API:\n\t\t\treturn character.settings?.secrets?.AKASH_CHAT_API_KEY || settings.AKASH_CHAT_API_KEY\n\t\tcase ModelProviderName.GOOGLE:\n\t\t\treturn character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY || settings.GOOGLE_GENERATIVE_AI_API_KEY\n\t\tcase ModelProviderName.MISTRAL:\n\t\t\treturn character.settings?.secrets?.MISTRAL_API_KEY || settings.MISTRAL_API_KEY\n\t\tcase ModelProviderName.LETZAI:\n\t\t\treturn character.settings?.secrets?.LETZAI_API_KEY || settings.LETZAI_API_KEY\n\t\tcase ModelProviderName.INFERA:\n\t\t\treturn character.settings?.secrets?.INFERA_API_KEY || settings.INFERA_API_KEY\n\t\tcase ModelProviderName.DEEPSEEK:\n\t\t\treturn character.settings?.secrets?.DEEPSEEK_API_KEY || settings.DEEPSEEK_API_KEY\n\t\tcase ModelProviderName.LIVEPEER:\n\t\t\treturn character.settings?.secrets?.LIVEPEER_GATEWAY_URL || settings.LIVEPEER_GATEWAY_URL\n\t\tdefault:\n\t\t\tconst errorMessage = `Failed to get token - unsupported model provider: ${provider}`\n\t\t\telizaLogger.error(errorMessage)\n\t\t\tthrow new Error(errorMessage)\n\t}\n}\n\nfunction initializeDatabase(dataDir: string) {\n\tif (process.env.MONGODB_CONNECTION_STRING) {\n\t\telizaLogger.log(\"Initializing database on MongoDB Atlas\");\n\t\tconst client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n\t\t\tmaxPoolSize: 100,\n\t\t\tminPoolSize: 5,\n\t\t\tmaxIdleTimeMS: 60000,\n\t\t\tconnectTimeoutMS: 10000,\n\t\t\tserverSelectionTimeoutMS: 5000,\n\t\t\tsocketTimeoutMS: 45000,\n\t\t\tcompressors: ['zlib'],\n\t\t\tretryWrites: true,\n\t\t\tretryReads: true\n\t\t});\n\n\t\tconst dbName = process.env.MONGODB_DATABASE || 'elizaAgent';\n\t\tconst db = new MongoDBDatabaseAdapter(client, dbName);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\n\t\t\t\t\t\"Successfully connected to MongoDB Atlas\"\n\t\t\t\t);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n\t\t\t\tthrow error; // Re-throw to handle it in the calling code\n\t\t\t});\n\n\t\treturn db;\n\t} else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n\t\telizaLogger.info(\"Initializing Supabase connection...\");\n\t\tconst db = new SupabaseDatabaseAdapter(\n\t\t\tprocess.env.SUPABASE_URL,\n\t\t\tprocess.env.SUPABASE_ANON_KEY,\n\t\t);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to Supabase database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to Supabase:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.POSTGRES_URL) {\n\t\telizaLogger.info(\"Initializing PostgreSQL connection...\")\n\t\tconst db = new PostgresDatabaseAdapter({\n\t\t\tconnectionString: process.env.POSTGRES_URL,\n\t\t\tparseInputs: true,\n\t\t})\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to PostgreSQL database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to PostgreSQL:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.PGLITE_DATA_DIR) {\n\t\telizaLogger.info(\"Initializing PgLite adapter...\")\n\t\t// `dataDir: memory://` for in memory pg\n\t\tconst db = new PGLiteDatabaseAdapter({\n\t\t\tdataDir: process.env.PGLITE_DATA_DIR,\n\t\t})\n\t\treturn db\n\t} else if (\n\t\tprocess.env.QDRANT_URL && process.env.QDRANT_KEY && process.env.QDRANT_PORT && process.env.QDRANT_VECTOR_SIZE) {\n\t\telizaLogger.info(\"Initializing Qdrant adapter...\")\n\t\tconst db = new QdrantDatabaseAdapter(process.env.QDRANT_URL, process.env.QDRANT_KEY, Number(process.env.QDRANT_PORT), Number(process.env.QDRANT_VECTOR_SIZE),)\n\t\treturn db\n\t} else {\n\t\tconst filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\")\n\t\telizaLogger.info(`Initializing SQLite database at ${filePath}...`)\n\t\tconst db = new SqliteDatabaseAdapter(new Database(filePath))\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to SQLite database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to SQLite:\", error)\n\t\t\t})\n\n\t\treturn db\n\t}\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(character: Character, runtime: IAgentRuntime) {\n\t// each client can only register once\n\t// and if we want two we can explicitly support it\n\tconst clients: Record<string, any> = {}\n\tconst clientTypes: string[] = character.clients?.map((str) => str.toLowerCase()) || []\n\telizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name)\n\n\n\t// Start Auto Client if \"auto\" detected as a configured client\n\tif (clientTypes.includes(Clients.AUTO)) {\n\t\tconst autoClient = await AutoClientInterface.start(runtime)\n\t\tif (autoClient) clients.auto = autoClient\n\t}\n\n\tif (clientTypes.includes(Clients.XMTP)) {\n\t\tconst xmtpClient = await XmtpClientInterface.start(runtime);\n\t\tif (xmtpClient) clients.xmtp = xmtpClient;\n\t}\n\n\tif (clientTypes.includes(Clients.DISCORD)) {\n\t\tconst discordClient = await DiscordClientInterface.start(runtime)\n\t\tif (discordClient) clients.discord = discordClient\n\t}\n\n\tif (clientTypes.includes(Clients.TELEGRAM)) {\n\t\tconst telegramClient = await TelegramClientInterface.start(runtime)\n\t\tif (telegramClient) clients.telegram = telegramClient\n\t}\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient = await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient) clients.telegram_account = telegramAccountClient;\n }\n\n\tif (clientTypes.includes(Clients.TWITTER)) {\n\t\tconst twitterClient = await TwitterClientInterface.start(runtime)\n\t\tif (twitterClient) {\n\t\t\tclients.twitter = twitterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.ALEXA)) {\n\t\tconst alexaClient = await AlexaClientInterface.start(runtime);\n\t\tif (alexaClient) {\n\t\t\tclients.alexa = alexaClient;\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.INSTAGRAM)) {\n\t\tconst instagramClient = await InstagramClientInterface.start(runtime)\n\t\tif (instagramClient) {\n\t\t\tclients.instagram = instagramClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.FARCASTER)) {\n\t\tconst farcasterClient = await FarcasterClientInterface.start(runtime)\n\t\tif (farcasterClient) {\n\t\t\tclients.farcaster = farcasterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(\"lens\")) {\n\t\tconst lensClient = new LensAgentClient(runtime)\n\t\tlensClient.start()\n\t\tclients.lens = lensClient\n\t}\n\n\tif (clientTypes.includes(Clients.SIMSAI)) {\n\t\tconst simsaiClient = await JeeterClientInterface.start(runtime)\n\t\tif (simsaiClient) clients.simsai = simsaiClient\n\t}\n\n\telizaLogger.log(\"client keys\", Object.keys(clients))\n\n if (clientTypes.includes(\"deva\")) {\n if (clientTypes.includes(\"deva\")) {\n const devaClient = await DevaClientInterface.start(runtime);\n if (devaClient) clients.deva = devaClient;\n }\n }\n\n function determineClientType(client: Client): string {\n // Check if client has a direct type identifier\n if (\"type\" in client) {\n return (client as any).type;\n }\n\n\t\t// TODO: Add Slack client to the list\n\t\t// Initialize clients as an object\n\n\tif (clientTypes.includes(\"slack\")) {\n\t\tconst slackClient = await SlackClientInterface.start(runtime)\n\t\tif (slackClient) clients.slack = slackClient // Use object property instead of push\n\t}\n\n\tfunction determineClientType(client: Client): string {\n\t\t// Check if client has a direct type identifier\n\t\tif (\"type\" in client) {\n\t\t\treturn (client as any).type\n\t\t}\n\n\t\t// Check constructor name\n\t\tconst constructorName = client.constructor?.name\n\t\tif (constructorName && !constructorName.includes(\"Object\")) {\n\t\t\treturn constructorName.toLowerCase().replace(\"client\", \"\")\n\t\t}\n\n\t\t// Fallback: Generate a unique identifier\n\t\treturn `client_${Date.now()}`\n\t}\n\n\tif (character.plugins?.length > 0) {\n\t\tfor (const plugin of character.plugins) {\n\t\t\tif (plugin.clients) {\n\t\t\t\tfor (const client of plugin.clients) {\n\t\t\t\t\tconst startedClient = await client.start(runtime)\n\t\t\t\t\tconst clientType = determineClientType(client)\n\t\t\t\t\telizaLogger.debug(`Initializing client of type: ${clientType}`)\n\t\t\t\t\tclients[clientType] = startedClient\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn clients\n}\n\nfunction getSecret(character: Character, secret: string) {\n\treturn character.settings?.secrets?.[secret] || process.env[secret]\n}\n\nlet nodePlugin: any | undefined\n\nexport async function createAgent(character: Character, db: IDatabaseAdapter, cache: ICacheManager, token: string): Promise<AgentRuntime> {\n\telizaLogger.log(`Creating runtime for character ${character.name}`)\n\n\tnodePlugin ??= createNodePlugin()\n\n\tconst teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\"\n\tconst walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\")\n\n\t// Validate TEE configuration\n\tif (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n\t\telizaLogger.error(\"A WALLET_SECRET_SALT required when TEE_MODE is enabled\")\n\t\tthrow new Error(\"Invalid TEE configuration\")\n\t}\n\n\tlet goatPlugin: any | undefined\n\n\tif (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n\t\tgoatPlugin = await createGoatPlugin((secret) => getSecret(character, secret))\n\t}\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n\t// Initialize Reclaim adapter if environment variables are present\n\t// let verifiableInferenceAdapter;\n\t// if (\n\t// process.env.RECLAIM_APP_ID &&\n\t// process.env.RECLAIM_APP_SECRET &&\n\t// process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n\t// ) {\n\t// verifiableInferenceAdapter = new ReclaimAdapter({\n\t// appId: process.env.RECLAIM_APP_ID,\n\t// appSecret: process.env.RECLAIM_APP_SECRET,\n\t// modelProvider: character.modelProvider,\n\t// token,\n\t// });\n\t// elizaLogger.log(\"Verifiable inference adapter initialized\");\n\t// }\n\t// Initialize Opacity adapter if environment variables are present\n\tlet verifiableInferenceAdapter\n\tif (process.env.OPACITY_TEAM_ID && process.env.OPACITY_CLOUDFLARE_NAME && process.env.OPACITY_PROVER_URL && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new OpacityAdapter({\n\t\t\tteamId: process.env.OPACITY_TEAM_ID,\n\t\t\tteamName: process.env.OPACITY_CLOUDFLARE_NAME,\n\t\t\topacityProverUrl: process.env.OPACITY_PROVER_URL,\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken: token,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference adapter initialized\")\n\t\telizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID)\n\t\telizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME)\n\t\telizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL)\n\t\telizaLogger.log(\"modelProvider\", character.modelProvider)\n\t\telizaLogger.log(\"token\", token)\n\t}\n\tif (process.env.PRIMUS_APP_ID && process.env.PRIMUS_APP_SECRET && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new PrimusAdapter({\n\t\t\tappId: process.env.PRIMUS_APP_ID,\n\t\t\tappSecret: process.env.PRIMUS_APP_SECRET,\n\t\t\tattMode: \"proxytls\",\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference primus adapter initialized\")\n\t}\n\n\treturn new AgentRuntime({\n\t\tdatabaseAdapter: db,\n\t\ttoken,\n\t\tmodelProvider: character.modelProvider,\n\t\tevaluators: [],\n\t\tcharacter,\n\t\t// character.plugins are handled when clients are added\n\t\tplugins: [\n\t\t\tparseBooleanFromText(getSecret(character, \"BITMIND\")) && getSecret(character, \"BITMIND_API_TOKEN\") ? bittensorPlugin : null,\n\t\t\tparseBooleanFromText(getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")) ? emailAutomationPlugin : null,\n\t\t\tgetSecret(character, \"IQ_WALLET_ADDRESS\") && getSecret(character, \"IQSOlRPC\") ? elizaCodeinPlugin : null,\n\t\t\tbootstrapPlugin,\n\t\t\tgetSecret(character, \"CDP_API_KEY_NAME\") && getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") && getSecret(character, \"CDP_AGENT_KIT_NETWORK\") ? agentKitPlugin : null,\n\t\t\tgetSecret(character, \"DEXSCREENER_API_KEY\") ? dexScreenerPlugin : null,\n\t\t\tgetSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n\t\t\tgetSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\") ? confluxPlugin : null,\n\t\t\tnodePlugin,\n\t\t\tgetSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") && getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\") ? nitroPlugin : null,\n\t\t\tgetSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n\t\t\tgetSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? [solanaPlugin, solanaPluginV2] : null,\n\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") ? solanaAgentkitPlugin : null,\n\t\t\tgetSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n\t\t\t(getSecret(character, \"NEAR_ADDRESS\") || getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) && getSecret(character, \"NEAR_WALLET_SECRET_KEY\") ? nearPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? evmPlugin : null,\n\t\t\t(getSecret(character, \"EVM_PUBLIC_KEY\") || getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) && getSecret(character, \"INJECTIVE_PRIVATE_KEY\") ? injectivePlugin : null,\n\t\t\tgetSecret(character, \"COSMOS_RECOVERY_PHRASE\") && getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") && createCosmosPlugin(),\n\t\t\t(getSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))) &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n\t\t\t\t? nftGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n\t\t\tgetSecret(character, \"COINMARKETCAP_API_KEY\") ? coinmarketcapPlugin : null,\n\t\t\tgetSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_COMMERCE_KEY\") ? coinbaseCommercePlugin : null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"OPENAI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"VENICE_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NVIDIA_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NINETEEN_AI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"HEURIST_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"LIVEPEER_GATEWAY_URL\")\n\t\t\t\t? imageGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n\t\t\t...(getSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") ? [coinbaseMassPaymentsPlugin, tradePlugin, tokenContractPlugin, advancedTradePlugin] : []),\n\t\t\t...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n\t\t\tteeMode !== TEEMode.OFF && walletSecretSalt && getSecret(character, \"VLOG\") ? verifiableLogPlugin : null,\n\t\t\tgetSecret(character, \"SGX\") ? sgxPlugin : null,\n\t\t\tgetSecret(character, \"ENABLE_TEE_LOG\") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, \"SGX\")) ? teeLogPlugin : null,\n\t\t\tgetSecret(character, \"OMNIFLIX_API_URL\") && getSecret(character, \"OMNIFLIX_MNEMONIC\") ? OmniflixPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") && getSecret(character, \"COINBASE_NOTIFICATION_URI\") ? webhookPlugin : null,\n \t\t goatPlugin,\n zilliqaPlugin,\n\t\t\tgetSecret(character, \"COINGECKO_API_KEY\") || getSecret(character, \"COINGECKO_PRO_API_KEY\") ? coingeckoPlugin : null,\n\t\t\tgetSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n\t\t\tgetSecret(character, \"ABSTRACT_PRIVATE_KEY\") ? abstractPlugin : null,\n\t\t\tgetSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n\t\t\tgetSecret(character, \"BINANCE_API_KEY\") && getSecret(character, \"BINANCE_SECRET_KEY\") ? binancePlugin : null,\n\t\t\tgetSecret(character, \"FLOW_ADDRESS\") && getSecret(character, \"FLOW_PRIVATE_KEY\") ? flowPlugin : null,\n\t\t\tgetSecret(character, \"LENS_ADDRESS\") && getSecret(character, \"LENS_PRIVATE_KEY\") ? lensPlugin : null,\n\t\t\tgetSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n\t\t\tgetSecret(character, \"MIND_COLD_WALLET_ADDRESS\") ? mindNetworkPlugin : null,\n\t\t\tgetSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n\t\t\tgetSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n\t\t\tgetSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\") ? cronosZkEVMPlugin : null,\n\t\t\tgetSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n\t\t\tgetSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n\t\t\tgetSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n\t\t\tgetSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n\t\t\tgetSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n\t\t\tgetSecret(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\")\n\t\t\t\t? squidRouterPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n\t\t\tgetSecret(character, \"AVALANCHE_PRIVATE_KEY\") ? avalanchePlugin : null,\n\t\t\tgetSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n\t\t\tgetSecret(character, \"ECHOCHAMBERS_API_URL\") && getSecret(character, \"ECHOCHAMBERS_API_KEY\") ? echoChambersPlugin : null,\n\t\t\tgetSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n\t\t\tgetSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n\t\t\tgetSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n\t\t\tgetSecret(character, \"PASSPORT_API_KEY\") ? gitcoinPassportPlugin : null,\n\t\t\tgetSecret(character, \"GENLAYER_PRIVATE_KEY\") ? genLayerPlugin : null,\n\t\t\tgetSecret(character, \"AVAIL_SEED\") && getSecret(character, \"AVAIL_APP_ID\") ? availPlugin : null,\n\t\t\tgetSecret(character, \"OPEN_WEATHER_API_KEY\") ? openWeatherPlugin : null,\n\t\t\tgetSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n\t\t\tgetSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\") ? artheraPlugin : null,\n\t\t\tgetSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_PRIVATE_KEY\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_TESTNET\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"AKASH_MNEMONIC\") && getSecret(character, \"AKASH_WALLET_ADDRESS\") ? akashPlugin : null,\n\t\t\tgetSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n\t\t\tgetSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n\t\t\tgetSecret(character, \"RESERVOIR_API_KEY\") ? createNFTCollectionsPlugin() : null,\n\t\t\tgetSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n\t\t\tgetSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n\t\t\tgetSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") || getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\") ? pythDataPlugin : null,\n\t\t\tgetSecret(character, \"LND_TLS_CERT\") && getSecret(character, \"LND_MACAROON\") && getSecret(character, \"LND_SOCKET\") ? lightningPlugin : null,\n\t\t\tgetSecret(character, \"OPENAI_API_KEY\") && parseBooleanFromText(getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")) ? openaiPlugin : null,\n\t\t\tgetSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n\t\t\tgetSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n\t\t\tgetSecret(character, \"HOLDSTATION_PRIVATE_KEY\") ? holdstationPlugin : null,\n\t\t\tgetSecret(character, \"NVIDIA_NIM_API_KEY\") || getSecret(character, \"NVIDIA_NGC_API_KEY\") ? nvidiaNimPlugin : null,\n\t\t\tgetSecret(character, \"BNB_PRIVATE_KEY\") || getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\") ? bnbPlugin : null,\n\t\t\t(getSecret(character, \"EMAIL_INCOMING_USER\") && getSecret(character, \"EMAIL_INCOMING_PASS\")) || (getSecret(character, \"EMAIL_OUTGOING_USER\") && getSecret(character, \"EMAIL_OUTGOING_PASS\")) ? emailPlugin : null,\n\t\t\tgetSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n\t\t\tgetSecret(character, \"HYPERBOLIC_API_KEY\") ? hyperbolicPlugin : null,\n\t\t\tgetSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n\t\t\tgetSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n\t\t\tgetSecret(character, \"IMGFLIP_USERNAME\") && getSecret(character, \"IMGFLIP_PASSWORD\") ? imgflipPlugin : null,\n\t\t\tgetSecret(character, \"FUNDING_PRIVATE_KEY\") && getSecret(character, \"EVM_RPC_URL\") ? litPlugin : null,\n\t\t\tgetSecret(character, \"ETHSTORAGE_PRIVATE_KEY\") ? ethstoragePlugin : null,\n\t\t\tgetSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n\t\t\tgetSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n\t\t\tgetSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n\t\t\tgetSecret(character, \"DCAP_EVM_PRIVATE_KEY\") && getSecret(character, \"DCAP_MODE\") ? dcapPlugin : null,\n\t\t\tgetSecret(character, \"QUICKINTEL_API_KEY\") ? quickIntelPlugin : null,\n\t\t\tgetSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n\t\t\tgetSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n\t\t\tgetSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") && \n\t\t\t(getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\")\n\t\t\t\t|| getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) \n\t\t\t\t&& getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") \n\t\t\t\t&& getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\") ? arbitragePlugin : null,\n\t\t].flat().filter(Boolean),\n\t\tproviders: [],\n\t\tmanagers: [],\n\t\tcacheManager: cache,\n\t\tfetch: logFetch,\n\t\tverifiableInferenceAdapter,\n\t})\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cacheDir = path.resolve(baseDir, character.id, \"cache\")\n\n\tconst cache = new CacheManager(new FsCacheAdapter(cacheDir))\n\treturn cache\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cache = new CacheManager(new DbCacheAdapter(db, character.id))\n\treturn cache\n}\n\nfunction initializeCache(cacheStore: string, character: Character, baseDir?: string, db?: IDatabaseCacheAdapter) {\n\tswitch (cacheStore) {\n\t\tcase CacheStore.REDIS:\n\t\t\tif (process.env.REDIS_URL) {\n\t\t\t\telizaLogger.info(\"Connecting to Redis...\")\n\t\t\t\tconst redisClient = new RedisClient(process.env.REDIS_URL)\n\t\t\t\tif (!character?.id) {\n\t\t\t\t\tthrow new Error(\"CacheStore.REDIS requires id to be set in character definition\")\n\t\t\t\t}\n\t\t\t\treturn new CacheManager(\n\t\t\t\t\tnew DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"REDIS_URL environment variable is not set.\")\n\t\t\t}\n\n\t\tcase CacheStore.DATABASE:\n\t\t\tif (db) {\n\t\t\t\telizaLogger.info(\"Using Database Cache...\")\n\t\t\t\treturn initializeDbCache(character, db)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Database adapter is not provided for CacheStore.Database.\")\n\t\t\t}\n\n\t\tcase CacheStore.FILESYSTEM:\n\t\t\telizaLogger.info(\"Using File System Cache...\")\n\t\t\tif (!baseDir) {\n\t\t\t\tthrow new Error(\"baseDir must be provided for CacheStore.FILESYSTEM.\")\n\t\t\t}\n\t\t\treturn initializeFsCache(baseDir, character)\n\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid cache store: ${cacheStore} or required configuration missing.`)\n\t}\n}\n\nasync function startAgent(character: Character, directClient: DirectClient): Promise<AgentRuntime> {\n\tlet db: IDatabaseAdapter & IDatabaseCacheAdapter\n\ttry {\n\t\tcharacter.id ??= stringToUuid(character.name)\n\t\tcharacter.username ??= character.name\n\n\t\tconst token = getTokenForProvider(character.modelProvider, character)\n\t\tconst dataDir = path.join(__dirname, \"../data\")\n\n\t\tif (!fs.existsSync(dataDir)) {\n\t\t\tfs.mkdirSync(dataDir, { recursive: true })\n\t\t}\n\n\t\tdb = initializeDatabase(dataDir) as IDatabaseAdapter & IDatabaseCacheAdapter\n\n\t\tawait db.init()\n\n\t\tconst cache = initializeCache(process.env.CACHE_STORE ?? CacheStore.DATABASE, character, \"\", db) // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n\t\tconst runtime: AgentRuntime = await createAgent(character, db, cache, token)\n\n\t\t// start services/plugins/process knowledge\n\t\tawait runtime.initialize()\n\n\t\t// start assigned clients\n\t\truntime.clients = await initializeClients(character, runtime)\n\n\t\t// add to container\n\t\tdirectClient.registerAgent(runtime)\n\n\t\t// report to console\n\t\telizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`)\n\n\t\treturn runtime\n\t} catch (error) {\n\t\telizaLogger.error(`Error starting agent for character ${character.name}:`, error)\n\t\telizaLogger.error(error)\n\t\tif (db) {\n\t\t\tawait db.close()\n\t\t}\n\t\tthrow error\n\t}\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\n\t\tserver.once(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\tresolve(false)\n\t\t\t}\n\t\t})\n\n\t\tserver.once(\"listening\", () => {\n\t\t\tserver.close()\n\t\t\tresolve(true)\n\t\t})\n\n\t\tserver.listen(port)\n\t})\n}\n\nconst hasValidRemoteUrls = () => process.env.REMOTE_CHARACTER_URLS && process.env.REMOTE_CHARACTER_URLS !== \"\" && process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\")\n\nconst startAgents = async () => {\n\tconst directClient = new DirectClient()\n\tlet serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\")\n\tconst args = parseArguments()\n\tconst charactersArg = args.characters || args.character\n\tlet characters = [defaultCharacter]\n\n\tif (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n\t\tcharacters = await loadCharacterFromOnchain()\n\t}\n\n\tconst notOnchainJson = !onchainJson || onchainJson == \"null\"\n\n\tif ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n\t\tcharacters = await loadCharacters(charactersArg)\n\t}\n\n\t// Normalize characters for injectable plugins\n\tcharacters = await Promise.all(characters.map(normalizeCharacter))\n\n\ttry {\n\t\tfor (const character of characters) {\n\t\t\tawait startAgent(character, directClient)\n\t\t}\n\t} catch (error) {\n\t\telizaLogger.error(\"Error starting agents:\", error)\n\t}\n\n\t// Find available port\n\twhile (!(await checkPortAvailable(serverPort))) {\n\t\telizaLogger.warn(`Port ${serverPort} is in use, trying ${serverPort + 1}`)\n\t\tserverPort++\n\t}\n\n\t// upload some agent functionality into directClient\n\tdirectClient.startAgent = async (character) => {\n\t\t// Handle plugins\n\t\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\n\t\t// wrap it so we don't have to inject directClient later\n\t\treturn startAgent(character, directClient)\n\t}\n\n\tdirectClient.loadCharacterTryPath = loadCharacterTryPath\n\tdirectClient.jsonToCharacter = jsonToCharacter\n\n\tdirectClient.start(serverPort)\n\n\tif (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n\t\telizaLogger.log(`Server started on alternate port ${serverPort}`)\n\t}\n\n\telizaLogger.log(\"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\")\n}\n\nstartAgents().catch((error) => {\n\telizaLogger.error(\"Unhandled error in startAgents:\", error)\n\tprocess.exit(1)\n})\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n\tprocess.env.PREVENT_UNHANDLED_EXIT &&\n\tparseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n\t// Handle uncaught exceptions to prevent the process from crashing\n\tprocess.on(\"uncaughtException\", function (err) {\n\t\tconsole.error(\"uncaughtException\", err);\n\t});\n\n\t// Handle unhandled rejections to prevent the process from crashing\n\tprocess.on(\"unhandledRejection\", function (err) {\n\t\tconsole.error(\"unhandledRejection\", err);\n\t});\n}\n"}, "8cb28307c9ed14dbfdbd3a9e43afaf8dff633694": {"t": 1785754691.8817623, "n": 47592, "h": "e241c6f9a82f8ec0", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\"\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\"\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\"\nimport { RedisClient } from \"@elizaos/adapter-redis\"\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\"\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\"\nimport { AutoClientInterface } from \"@elizaos/client-auto\"\nimport { DiscordClientInterface } from \"@elizaos/client-discord\"\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\"\nimport { LensAgentClient } from \"@elizaos/client-lens\"\nimport { SlackClientInterface } from \"@elizaos/client-slack\"\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\"\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\"\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\"\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\"\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\"\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\"\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\"\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\"\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\"\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\"\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\"\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\"\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\"\nimport {\n\tAgentRuntime,\n\tCacheManager,\n\tCacheStore,\n\ttype Character,\n\ttype Client,\n\tClients,\n\tDbCacheAdapter,\n\tdefaultCharacter,\n\telizaLogger,\n\tFsCacheAdapter,\n\ttype IAgentRuntime,\n\ttype ICacheManager,\n\ttype IDatabaseAdapter,\n\ttype IDatabaseCacheAdapter,\n\tModelProviderName,\n\tparseBooleanFromText,\n\tsettings,\n\tstringToUuid,\n\tvalidateCharacterConfig,\n} from \"@elizaos/core\"\nimport { zgPlugin } from \"@elizaos/plugin-0g\"\nimport { footballPlugin } from \"@elizaos/plugin-football\"\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\"\nimport { normalizeCharacter } from \"@elizaos/plugin-di\"\nimport createGoatPlugin from \"@elizaos/plugin-goat\"\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\"\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\"\nimport { akashPlugin } from \"@elizaos/plugin-akash\"\nimport { alloraPlugin } from \"@elizaos/plugin-allora\"\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\"\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\"\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\"\nimport { availPlugin } from \"@elizaos/plugin-avail\"\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\"\nimport { b2Plugin } from \"@elizaos/plugin-b2\"\nimport { binancePlugin } from \"@elizaos/plugin-binance\"\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\"\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\"\nimport { advancedTradePlugin, coinbaseCommercePlugin, coinbaseMassPaymentsPlugin, tokenContractPlugin, tradePlugin, webhookPlugin } from \"@elizaos/plugin-coinbase\"\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\"\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\"\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\"\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\"\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\"\nimport { evmPlugin } from \"@elizaos/plugin-evm\"\nimport { flowPlugin } from \"@elizaos/plugin-flow\"\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\"\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\"\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\"\nimport { initiaPlugin } from \"@elizaos/plugin-initia\"\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\"\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\"\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\"\nimport { nearPlugin } from \"@elizaos/plugin-near\"\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\"\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\"\nimport { createNodePlugin } from \"@elizaos/plugin-node\"\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\"\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\"\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\"\nimport { quaiPlugin } from \"@elizaos/plugin-quai\"\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\"\nimport { solanaPlugin } from \"@elizaos/plugin-solana\"\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\"\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\"\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\"\nimport { storyPlugin } from \"@elizaos/plugin-story\"\nimport { suiPlugin } from \"@elizaos/plugin-sui\"\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\"\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\"\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\"\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\"\nimport { tonPlugin } from \"@elizaos/plugin-ton\"\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\"\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\"\nimport { injectivePlugin } from \"@elizaos/plugin-injective\"\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\"\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\"\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\"\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\"\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\"\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\"\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\"\nimport { openaiPlugin } from \"@elizaos/plugin-openai\"\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\"\nimport { devinPlugin } from \"@elizaos/plugin-devin\"\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\"\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\"\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\"\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\"\nimport { zxPlugin } from \"@elizaos/plugin-0x\"\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\"\nimport { litPlugin } from \"@elizaos/plugin-lit\"\nimport Database from \"better-sqlite3\"\nimport fs from \"fs\"\nimport net from \"net\"\nimport path from \"path\"\nimport { fileURLToPath } from \"url\"\nimport yargs from \"yargs\"\nimport { emailPlugin } from \"@elizaos/plugin-email\"\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\"\nimport { sunoPlugin } from \"@elizaos/plugin-suno\"\nimport { udioPlugin } from \"@elizaos/plugin-udio\"\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\"\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\"\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\"\nimport { minaPlugin } from \"@elizaos/plugin-mina\"\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\"\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\"\nimport arbitragePlugin from \"@elizaos/plugin-arbitrage\"\nconst __filename = fileURLToPath(import.meta.url) // get the resolved path to the file\nconst __dirname = path.dirname(__filename) // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n\tconst waitTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime\n\treturn new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\nconst logFetch = async (url: string, options: any) => {\n\telizaLogger.debug(`Fetching ${url}`)\n\t// Disabled to avoid disclosure of sensitive information such as API keys\n\t// elizaLogger.debug(JSON.stringify(options, null, 2));\n\treturn fetch(url, options)\n}\n\nexport function parseArguments(): {\n\tcharacter?: string\n\tcharacters?: string\n} {\n\ttry {\n\t\treturn yargs(process.argv.slice(3))\n\t\t\t.option(\"character\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Path to the character JSON file\",\n\t\t\t})\n\t\t\t.option(\"characters\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Comma separated list of paths to character JSON files\",\n\t\t\t})\n\t\t\t.parseSync()\n\t} catch (error) {\n\t\telizaLogger.error(\"Error parsing arguments:\", error)\n\t\treturn {}\n\t}\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n\ttry {\n\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t} catch (e) {\n\t\treturn null\n\t}\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n\tconst mergeObjects = (baseObj: any, childObj: any) => {\n\t\tconst result: any = {}\n\t\tconst keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})])\n\t\tkeys.forEach((key) => {\n\t\t\tif (typeof baseObj[key] === \"object\" && typeof childObj[key] === \"object\" && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = mergeObjects(baseObj[key], childObj[key])\n\t\t\t} else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = [...(baseObj[key] || []), ...(childObj[key] || [])]\n\t\t\t} else {\n\t\t\t\tresult[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key]\n\t\t\t}\n\t\t})\n\t\treturn result\n\t}\n\treturn mergeObjects(base, child)\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n\treturn Array.isArray(arr) && arr.every((item) => typeof item === \"string\")\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n\tconst jsonText = onchainJson\n\n\tconsole.log(\"JSON:\", jsonText)\n\tif (!jsonText) return []\n\tconst loadedCharacters = []\n\ttry {\n\t\tconst character = JSON.parse(jsonText)\n\t\tvalidateCharacterConfig(character)\n\n\t\t// .id isn't really valid\n\t\tconst characterId = character.id || character.name\n\t\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\n\t\tconst characterSettings = Object.entries(process.env)\n\t\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t\t.reduce((settings, [key, value]) => {\n\t\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\t\tsettings[settingKey] = value\n\t\t\t\treturn settings\n\t\t\t}, {})\n\n\t\tif (Object.keys(characterSettings).length > 0) {\n\t\t\tcharacter.settings = character.settings || {}\n\t\t\tcharacter.settings.secrets = {\n\t\t\t\t...characterSettings,\n\t\t\t\t...character.settings.secrets,\n\t\t\t}\n\t\t}\n\n\t\t// Handle plugins\n\t\tif (isAllStrings(character.plugins)) {\n\t\t\telizaLogger.info(\"Plugins are: \", character.plugins)\n\t\t\tconst importedPlugins = await Promise.all(\n\t\t\t\tcharacter.plugins.map(async (plugin) => {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\treturn importedPlugin.default\n\t\t\t\t})\n\t\t\t)\n\t\t\tcharacter.plugins = importedPlugins\n\t\t}\n\n\t\tloadedCharacters.push(character)\n\t\telizaLogger.info(`Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`)\n\t\treturn loadedCharacters\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n\ttry {\n\t\tconst response = await fetch(url)\n\t\tconst responseJson = await response.json()\n\n\t\tlet characters: Character[] = []\n\t\tif (Array.isArray(responseJson)) {\n\t\t\tcharacters = await Promise.all(responseJson.map((character) => jsonToCharacter(url, character)))\n\t\t} else {\n\t\t\tconst character = await jsonToCharacter(url, responseJson)\n\t\t\tcharacters.push(character)\n\t\t}\n\t\treturn characters\n\t} catch (e) {\n\t\telizaLogger.error(`Error loading character(s) from ${url}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function jsonToCharacter(filePath: string, character: any): Promise<Character> {\n\tvalidateCharacterConfig(character)\n\n\t// .id isn't really valid\n\tconst characterId = character.id || character.name\n\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\tconst characterSettings = Object.entries(process.env)\n\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t.reduce((settings, [key, value]) => {\n\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\treturn { ...settings, [settingKey]: value }\n\t\t}, {})\n\tif (Object.keys(characterSettings).length > 0) {\n\t\tcharacter.settings = character.settings || {}\n\t\tcharacter.settings.secrets = {\n\t\t\t...characterSettings,\n\t\t\t...character.settings.secrets,\n\t\t}\n\t}\n\t// Handle plugins\n\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\tif (character.extends) {\n\t\telizaLogger.info(`Merging ${character.name} character with parent characters`)\n\t\tfor (const extendPath of character.extends) {\n\t\t\tconst baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath))\n\t\t\tcharacter = mergeCharacters(baseCharacter, character)\n\t\t\telizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`)\n\t\t}\n\t}\n\treturn character\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n\tconst content = tryLoadFile(filePath)\n\tif (!content) {\n\t\tthrow new Error(`Character file not found: ${filePath}`)\n\t}\n\tconst character = JSON.parse(content)\n\treturn jsonToCharacter(filePath, character)\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n\tlet content: string | null = null\n\tlet resolvedPath = \"\"\n\n\t// Try different path resolutions in order\n\tconst pathsToTry = [\n\t\tcharacterPath, // exact path as specified\n\t\tpath.resolve(process.cwd(), characterPath), // relative to cwd\n\t\tpath.resolve(process.cwd(), \"agent\", characterPath), // Add this\n\t\tpath.resolve(__dirname, characterPath), // relative to current script\n\t\tpath.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n\t\tpath.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n\t\tpath.resolve(__dirname, \"../../characters\", path.basename(characterPath)), // relative to project root characters dir\n\t]\n\n\telizaLogger.info(\n\t\t\"Trying paths:\",\n\t\tpathsToTry.map((p) => ({\n\t\t\tpath: p,\n\t\t\texists: fs.existsSync(p),\n\t\t}))\n\t)\n\n\tfor (const tryPath of pathsToTry) {\n\t\tcontent = tryLoadFile(tryPath)\n\t\tif (content !== null) {\n\t\t\tresolvedPath = tryPath\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (content === null) {\n\t\telizaLogger.error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t\telizaLogger.error(\"Tried the following paths:\")\n\t\tpathsToTry.forEach((p) => elizaLogger.error(` - ${p}`))\n\t\tthrow new Error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t}\n\ttry {\n\t\tconst character: Character = await loadCharacter(resolvedPath)\n\t\telizaLogger.info(`Successfully loaded character from: ${resolvedPath}`)\n\t\treturn character\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t\tthrow new Error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t}\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n\treturn commaSeparated?.split(\",\").map((value) => value.trim())\n}\n\nasync function readCharactersFromStorage(characterPaths: string[]): Promise<string[]> {\n\ttry {\n\t\tconst uploadDir = path.join(process.cwd(), \"data\", \"characters\")\n\t\tawait fs.promises.mkdir(uploadDir, { recursive: true })\n\t\tconst fileNames = await fs.promises.readdir(uploadDir)\n\t\tfileNames.forEach((fileName) => {\n\t\t\tcharacterPaths.push(path.join(uploadDir, fileName))\n\t\t})\n\t} catch (err) {\n\t\telizaLogger.error(`Error reading directory: ${err.message}`)\n\t}\n\n\treturn characterPaths\n}\n\nexport async function loadCharacters(charactersArg: string): Promise<Character[]> {\n\tlet characterPaths = commaSeparatedStringToArray(charactersArg)\n\n\tif (process.env.USE_CHARACTER_STORAGE === \"true\") {\n\t\tcharacterPaths = await readCharactersFromStorage(characterPaths)\n\t}\n\n\tconst loadedCharacters: Character[] = []\n\n\tif (characterPaths?.length > 0) {\n\t\tfor (const characterPath of characterPaths) {\n\t\t\ttry {\n\t\t\t\tconst character: Character = await loadCharacterTryPath(characterPath)\n\t\t\t\tloadedCharacters.push(character)\n\t\t\t} catch (e) {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasValidRemoteUrls()) {\n\t\telizaLogger.info(\"Loading characters from remote URLs\")\n\t\tconst characterUrls = commaSeparatedStringToArray(process.env.REMOTE_CHARACTER_URLS)\n\t\tfor (const characterUrl of characterUrls) {\n\t\t\tconst characters = await loadCharactersFromUrl(characterUrl)\n\t\t\tloadedCharacters.push(...characters)\n\t\t}\n\t}\n\n\tif (loadedCharacters.length === 0) {\n\t\telizaLogger.info(\"No characters found, using default character\")\n\t\tloadedCharacters.push(defaultCharacter)\n\t}\n\n\treturn loadedCharacters\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n\tif (plugins.length > 0) {\n\t\telizaLogger.info(\"Plugins are: \", plugins)\n\t\tconst importedPlugins = await Promise.all(\n\t\t\tplugins.map(async (plugin) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\tconst functionName = plugin.replace(\"@elizaos/plugin-\", \"\").replace(/-./g, (x) => x[1].toUpperCase()) + \"Plugin\" // Assumes plugin function is camelCased with Plugin suffix\n\t\t\t\t\treturn importedPlugin.default || importedPlugin[functionName]\n\t\t\t\t} catch (importError) {\n\t\t\t\t\telizaLogger.error(`Failed to import plugin: ${plugin}`, importError)\n\t\t\t\t\treturn [] // Return null for failed imports\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\treturn importedPlugins\n\t} else {\n\t\treturn []\n\t}\n}\n\nexport function getTokenForProvider(provider: ModelProviderName, character: Character): string | undefined {\n\tswitch (provider) {\n\t\t// no key needed for llama_local or gaianet\n\t\tcase ModelProviderName.LLAMALOCAL:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OLLAMA:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.GAIANET:\n\t\t\treturn \"\";\n\t\tcase ModelProviderName.BEDROCK:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OPENAI:\n\t\t\treturn character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.ETERNALAI:\n\t\t\treturn character.settings?.secrets?.ETERNALAI_API_KEY || settings.ETERNALAI_API_KEY\n\t\tcase ModelProviderName.NINETEEN_AI:\n\t\t\treturn character.settings?.secrets?.NINETEEN_AI_API_KEY || settings.NINETEEN_AI_API_KEY\n\t\tcase ModelProviderName.LLAMACLOUD:\n\t\tcase ModelProviderName.TOGETHER:\n\t\t\treturn character.settings?.secrets?.LLAMACLOUD_API_KEY || settings.LLAMACLOUD_API_KEY || character.settings?.secrets?.TOGETHER_API_KEY || settings.TOGETHER_API_KEY || character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.CLAUDE_VERTEX:\n\t\tcase ModelProviderName.ANTHROPIC:\n\t\t\treturn character.settings?.secrets?.ANTHROPIC_API_KEY || character.settings?.secrets?.CLAUDE_API_KEY || settings.ANTHROPIC_API_KEY || settings.CLAUDE_API_KEY\n\t\tcase ModelProviderName.REDPILL:\n\t\t\treturn character.settings?.secrets?.REDPILL_API_KEY || settings.REDPILL_API_KEY\n\t\tcase ModelProviderName.OPENROUTER:\n\t\t\treturn character.settings?.secrets?.OPENROUTER_API_KEY || settings.OPENROUTER_API_KEY\n\t\tcase ModelProviderName.GROK:\n\t\t\treturn character.settings?.secrets?.GROK_API_KEY || settings.GROK_API_KEY\n\t\tcase ModelProviderName.HEURIST:\n\t\t\treturn character.settings?.secrets?.HEURIST_API_KEY || settings.HEURIST_API_KEY\n\t\tcase ModelProviderName.GROQ:\n\t\t\treturn character.settings?.secrets?.GROQ_API_KEY || settings.GROQ_API_KEY\n\t\tcase ModelProviderName.GALADRIEL:\n\t\t\treturn character.settings?.secrets?.GALADRIEL_API_KEY || settings.GALADRIEL_API_KEY\n\t\tcase ModelProviderName.FAL:\n\t\t\treturn character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n\t\tcase ModelProviderName.ALI_BAILIAN:\n\t\t\treturn character.settings?.secrets?.ALI_BAILIAN_API_KEY || settings.ALI_BAILIAN_API_KEY\n\t\tcase ModelProviderName.VOLENGINE:\n\t\t\treturn character.settings?.secrets?.VOLENGINE_API_KEY || settings.VOLENGINE_API_KEY\n\t\tcase ModelProviderName.NANOGPT:\n\t\t\treturn character.settings?.secrets?.NANOGPT_API_KEY || settings.NANOGPT_API_KEY\n\t\tcase ModelProviderName.HYPERBOLIC:\n\t\t\treturn character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY\n\n\t\tcase ModelProviderName.VENICE:\n\t\t\treturn character.settings?.secrets?.VENICE_API_KEY || settings.VENICE_API_KEY\n\t\tcase ModelProviderName.ATOMA:\n\t\t\treturn character.settings?.secrets?.ATOMASDK_BEARER_AUTH || settings.ATOMASDK_BEARER_AUTH\n\t\tcase ModelProviderName.NVIDIA:\n\t\t\treturn character.settings?.secrets?.NVIDIA_API_KEY || settings.NVIDIA_API_KEY\n\t\tcase ModelProviderName.AKASH_CHAT_API:\n\t\t\treturn character.settings?.secrets?.AKASH_CHAT_API_KEY || settings.AKASH_CHAT_API_KEY\n\t\tcase ModelProviderName.GOOGLE:\n\t\t\treturn character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY || settings.GOOGLE_GENERATIVE_AI_API_KEY\n\t\tcase ModelProviderName.MISTRAL:\n\t\t\treturn character.settings?.secrets?.MISTRAL_API_KEY || settings.MISTRAL_API_KEY\n\t\tcase ModelProviderName.LETZAI:\n\t\t\treturn character.settings?.secrets?.LETZAI_API_KEY || settings.LETZAI_API_KEY\n\t\tcase ModelProviderName.INFERA:\n\t\t\treturn character.settings?.secrets?.INFERA_API_KEY || settings.INFERA_API_KEY\n\t\tcase ModelProviderName.DEEPSEEK:\n\t\t\treturn character.settings?.secrets?.DEEPSEEK_API_KEY || settings.DEEPSEEK_API_KEY\n\t\tcase ModelProviderName.LIVEPEER:\n\t\t\treturn character.settings?.secrets?.LIVEPEER_GATEWAY_URL || settings.LIVEPEER_GATEWAY_URL\n\t\tdefault:\n\t\t\tconst errorMessage = `Failed to get token - unsupported model provider: ${provider}`\n\t\t\telizaLogger.error(errorMessage)\n\t\t\tthrow new Error(errorMessage)\n\t}\n}\n\nfunction initializeDatabase(dataDir: string) {\n\tif (process.env.MONGODB_CONNECTION_STRING) {\n\t\telizaLogger.log(\"Initializing database on MongoDB Atlas\");\n\t\tconst client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n\t\t\tmaxPoolSize: 100,\n\t\t\tminPoolSize: 5,\n\t\t\tmaxIdleTimeMS: 60000,\n\t\t\tconnectTimeoutMS: 10000,\n\t\t\tserverSelectionTimeoutMS: 5000,\n\t\t\tsocketTimeoutMS: 45000,\n\t\t\tcompressors: ['zlib'],\n\t\t\tretryWrites: true,\n\t\t\tretryReads: true\n\t\t});\n\n\t\tconst dbName = process.env.MONGODB_DATABASE || 'elizaAgent';\n\t\tconst db = new MongoDBDatabaseAdapter(client, dbName);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\n\t\t\t\t\t\"Successfully connected to MongoDB Atlas\"\n\t\t\t\t);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n\t\t\t\tthrow error; // Re-throw to handle it in the calling code\n\t\t\t});\n\n\t\treturn db;\n\t} else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n\t\telizaLogger.info(\"Initializing Supabase connection...\");\n\t\tconst db = new SupabaseDatabaseAdapter(\n\t\t\tprocess.env.SUPABASE_URL,\n\t\t\tprocess.env.SUPABASE_ANON_KEY,\n\t\t);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to Supabase database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to Supabase:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.POSTGRES_URL) {\n\t\telizaLogger.info(\"Initializing PostgreSQL connection...\")\n\t\tconst db = new PostgresDatabaseAdapter({\n\t\t\tconnectionString: process.env.POSTGRES_URL,\n\t\t\tparseInputs: true,\n\t\t})\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to PostgreSQL database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to PostgreSQL:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.PGLITE_DATA_DIR) {\n\t\telizaLogger.info(\"Initializing PgLite adapter...\")\n\t\t// `dataDir: memory://` for in memory pg\n\t\tconst db = new PGLiteDatabaseAdapter({\n\t\t\tdataDir: process.env.PGLITE_DATA_DIR,\n\t\t})\n\t\treturn db\n\t} else if (\n\t\tprocess.env.QDRANT_URL && process.env.QDRANT_KEY && process.env.QDRANT_PORT && process.env.QDRANT_VECTOR_SIZE) {\n\t\telizaLogger.info(\"Initializing Qdrant adapter...\")\n\t\tconst db = new QdrantDatabaseAdapter(process.env.QDRANT_URL, process.env.QDRANT_KEY, Number(process.env.QDRANT_PORT), Number(process.env.QDRANT_VECTOR_SIZE),)\n\t\treturn db\n\t} else {\n\t\tconst filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\")\n\t\telizaLogger.info(`Initializing SQLite database at ${filePath}...`)\n\t\tconst db = new SqliteDatabaseAdapter(new Database(filePath))\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to SQLite database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to SQLite:\", error)\n\t\t\t})\n\n\t\treturn db\n\t}\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(character: Character, runtime: IAgentRuntime) {\n\t// each client can only register once\n\t// and if we want two we can explicitly support it\n\tconst clients: Record<string, any> = {}\n\tconst clientTypes: string[] = character.clients?.map((str) => str.toLowerCase()) || []\n\telizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name)\n\n\n\t// Start Auto Client if \"auto\" detected as a configured client\n\tif (clientTypes.includes(Clients.AUTO)) {\n\t\tconst autoClient = await AutoClientInterface.start(runtime)\n\t\tif (autoClient) clients.auto = autoClient\n\t}\n\n\tif (clientTypes.includes(Clients.XMTP)) {\n\t\tconst xmtpClient = await XmtpClientInterface.start(runtime);\n\t\tif (xmtpClient) clients.xmtp = xmtpClient;\n\t}\n\n\tif (clientTypes.includes(Clients.DISCORD)) {\n\t\tconst discordClient = await DiscordClientInterface.start(runtime)\n\t\tif (discordClient) clients.discord = discordClient\n\t}\n\n\tif (clientTypes.includes(Clients.TELEGRAM)) {\n\t\tconst telegramClient = await TelegramClientInterface.start(runtime)\n\t\tif (telegramClient) clients.telegram = telegramClient\n\t}\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient = await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient) clients.telegram_account = telegramAccountClient;\n }\n\n\tif (clientTypes.includes(Clients.TWITTER)) {\n\t\tconst twitterClient = await TwitterClientInterface.start(runtime)\n\t\tif (twitterClient) {\n\t\t\tclients.twitter = twitterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.ALEXA)) {\n\t\tconst alexaClient = await AlexaClientInterface.start(runtime);\n\t\tif (alexaClient) {\n\t\t\tclients.alexa = alexaClient;\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.INSTAGRAM)) {\n\t\tconst instagramClient = await InstagramClientInterface.start(runtime)\n\t\tif (instagramClient) {\n\t\t\tclients.instagram = instagramClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.FARCASTER)) {\n\t\tconst farcasterClient = await FarcasterClientInterface.start(runtime)\n\t\tif (farcasterClient) {\n\t\t\tclients.farcaster = farcasterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(\"lens\")) {\n\t\tconst lensClient = new LensAgentClient(runtime)\n\t\tlensClient.start()\n\t\tclients.lens = lensClient\n\t}\n\n\tif (clientTypes.includes(Clients.SIMSAI)) {\n\t\tconst simsaiClient = await JeeterClientInterface.start(runtime)\n\t\tif (simsaiClient) clients.simsai = simsaiClient\n\t}\n\n\telizaLogger.log(\"client keys\", Object.keys(clients))\n\n\t// TODO: Add Slack client to the list\n\t// Initialize clients as an object\n\n\tif (clientTypes.includes(\"slack\")) {\n\t\tconst slackClient = await SlackClientInterface.start(runtime)\n\t\tif (slackClient) clients.slack = slackClient // Use object property instead of push\n\t}\n\n\tfunction determineClientType(client: Client): string {\n\t\t// Check if client has a direct type identifier\n\t\tif (\"type\" in client) {\n\t\t\treturn (client as any).type\n\t\t}\n\n\t\t// Check constructor name\n\t\tconst constructorName = client.constructor?.name\n\t\tif (constructorName && !constructorName.includes(\"Object\")) {\n\t\t\treturn constructorName.toLowerCase().replace(\"client\", \"\")\n\t\t}\n\n\t\t// Fallback: Generate a unique identifier\n\t\treturn `client_${Date.now()}`\n\t}\n\n\tif (character.plugins?.length > 0) {\n\t\tfor (const plugin of character.plugins) {\n\t\t\tif (plugin.clients) {\n\t\t\t\tfor (const client of plugin.clients) {\n\t\t\t\t\tconst startedClient = await client.start(runtime)\n\t\t\t\t\tconst clientType = determineClientType(client)\n\t\t\t\t\telizaLogger.debug(`Initializing client of type: ${clientType}`)\n\t\t\t\t\tclients[clientType] = startedClient\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn clients\n}\n\nfunction getSecret(character: Character, secret: string) {\n\treturn character.settings?.secrets?.[secret] || process.env[secret]\n}\n\nlet nodePlugin: any | undefined\n\nexport async function createAgent(character: Character, db: IDatabaseAdapter, cache: ICacheManager, token: string): Promise<AgentRuntime> {\n\telizaLogger.log(`Creating runtime for character ${character.name}`)\n\n\tnodePlugin ??= createNodePlugin()\n\n\tconst teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\"\n\tconst walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\")\n\n\t// Validate TEE configuration\n\tif (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n\t\telizaLogger.error(\"A WALLET_SECRET_SALT required when TEE_MODE is enabled\")\n\t\tthrow new Error(\"Invalid TEE configuration\")\n\t}\n\n\tlet goatPlugin: any | undefined\n\n\tif (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n\t\tgoatPlugin = await createGoatPlugin((secret) => getSecret(character, secret))\n\t}\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n\t// Initialize Reclaim adapter if environment variables are present\n\t// let verifiableInferenceAdapter;\n\t// if (\n\t// process.env.RECLAIM_APP_ID &&\n\t// process.env.RECLAIM_APP_SECRET &&\n\t// process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n\t// ) {\n\t// verifiableInferenceAdapter = new ReclaimAdapter({\n\t// appId: process.env.RECLAIM_APP_ID,\n\t// appSecret: process.env.RECLAIM_APP_SECRET,\n\t// modelProvider: character.modelProvider,\n\t// token,\n\t// });\n\t// elizaLogger.log(\"Verifiable inference adapter initialized\");\n\t// }\n\t// Initialize Opacity adapter if environment variables are present\n\tlet verifiableInferenceAdapter\n\tif (process.env.OPACITY_TEAM_ID && process.env.OPACITY_CLOUDFLARE_NAME && process.env.OPACITY_PROVER_URL && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new OpacityAdapter({\n\t\t\tteamId: process.env.OPACITY_TEAM_ID,\n\t\t\tteamName: process.env.OPACITY_CLOUDFLARE_NAME,\n\t\t\topacityProverUrl: process.env.OPACITY_PROVER_URL,\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken: token,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference adapter initialized\")\n\t\telizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID)\n\t\telizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME)\n\t\telizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL)\n\t\telizaLogger.log(\"modelProvider\", character.modelProvider)\n\t\telizaLogger.log(\"token\", token)\n\t}\n\tif (process.env.PRIMUS_APP_ID && process.env.PRIMUS_APP_SECRET && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new PrimusAdapter({\n\t\t\tappId: process.env.PRIMUS_APP_ID,\n\t\t\tappSecret: process.env.PRIMUS_APP_SECRET,\n\t\t\tattMode: \"proxytls\",\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference primus adapter initialized\")\n\t}\n\n\treturn new AgentRuntime({\n\t\tdatabaseAdapter: db,\n\t\ttoken,\n\t\tmodelProvider: character.modelProvider,\n\t\tevaluators: [],\n\t\tcharacter,\n\t\t// character.plugins are handled when clients are added\n\t\tplugins: [\n\t\t\tparseBooleanFromText(getSecret(character, \"BITMIND\")) && getSecret(character, \"BITMIND_API_TOKEN\") ? bittensorPlugin : null,\n\t\t\tparseBooleanFromText(getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")) ? emailAutomationPlugin : null,\n\t\t\tgetSecret(character, \"IQ_WALLET_ADDRESS\") && getSecret(character, \"IQSOlRPC\") ? elizaCodeinPlugin : null,\n\t\t\tbootstrapPlugin,\n\t\t\tgetSecret(character, \"CDP_API_KEY_NAME\") && getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") && getSecret(character, \"CDP_AGENT_KIT_NETWORK\") ? agentKitPlugin : null,\n\t\t\tgetSecret(character, \"DEXSCREENER_API_KEY\") ? dexScreenerPlugin : null,\n\t\t\tgetSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n\t\t\tgetSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\") ? confluxPlugin : null,\n\t\t\tnodePlugin,\n\t\t\tgetSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") && getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\") ? nitroPlugin : null,\n\t\t\tgetSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n\t\t\tgetSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? [solanaPlugin, solanaPluginV2] : null,\n\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") ? solanaAgentkitPlugin : null,\n\t\t\tgetSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n\t\t\t(getSecret(character, \"NEAR_ADDRESS\") || getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) && getSecret(character, \"NEAR_WALLET_SECRET_KEY\") ? nearPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? evmPlugin : null,\n\t\t\t(getSecret(character, \"EVM_PUBLIC_KEY\") || getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) && getSecret(character, \"INJECTIVE_PRIVATE_KEY\") ? injectivePlugin : null,\n\t\t\tgetSecret(character, \"COSMOS_RECOVERY_PHRASE\") && getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") && createCosmosPlugin(),\n\t\t\t(getSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))) &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n\t\t\t\t? nftGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n\t\t\tgetSecret(character, \"COINMARKETCAP_API_KEY\") ? coinmarketcapPlugin : null,\n\t\t\tgetSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_COMMERCE_KEY\") ? coinbaseCommercePlugin : null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"OPENAI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"VENICE_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NVIDIA_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NINETEEN_AI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"HEURIST_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"LIVEPEER_GATEWAY_URL\")\n\t\t\t\t? imageGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n\t\t\t...(getSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") ? [coinbaseMassPaymentsPlugin, tradePlugin, tokenContractPlugin, advancedTradePlugin] : []),\n\t\t\t...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n\t\t\tteeMode !== TEEMode.OFF && walletSecretSalt && getSecret(character, \"VLOG\") ? verifiableLogPlugin : null,\n\t\t\tgetSecret(character, \"SGX\") ? sgxPlugin : null,\n\t\t\tgetSecret(character, \"ENABLE_TEE_LOG\") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, \"SGX\")) ? teeLogPlugin : null,\n\t\t\tgetSecret(character, \"OMNIFLIX_API_URL\") && getSecret(character, \"OMNIFLIX_MNEMONIC\") ? OmniflixPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") && getSecret(character, \"COINBASE_NOTIFICATION_URI\") ? webhookPlugin : null,\n \t\t goatPlugin,\n zilliqaPlugin,\n\t\t\tgetSecret(character, \"COINGECKO_API_KEY\") || getSecret(character, \"COINGECKO_PRO_API_KEY\") ? coingeckoPlugin : null,\n\t\t\tgetSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n\t\t\tgetSecret(character, \"ABSTRACT_PRIVATE_KEY\") ? abstractPlugin : null,\n\t\t\tgetSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n\t\t\tgetSecret(character, \"BINANCE_API_KEY\") && getSecret(character, \"BINANCE_SECRET_KEY\") ? binancePlugin : null,\n\t\t\tgetSecret(character, \"FLOW_ADDRESS\") && getSecret(character, \"FLOW_PRIVATE_KEY\") ? flowPlugin : null,\n\t\t\tgetSecret(character, \"LENS_ADDRESS\") && getSecret(character, \"LENS_PRIVATE_KEY\") ? lensPlugin : null,\n\t\t\tgetSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n\t\t\tgetSecret(character, \"MIND_COLD_WALLET_ADDRESS\") ? mindNetworkPlugin : null,\n\t\t\tgetSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n\t\t\tgetSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n\t\t\tgetSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\") ? cronosZkEVMPlugin : null,\n\t\t\tgetSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n\t\t\tgetSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n\t\t\tgetSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n\t\t\tgetSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n\t\t\tgetSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n\t\t\tgetSecret(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\")\n\t\t\t\t? squidRouterPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n\t\t\tgetSecret(character, \"AVALANCHE_PRIVATE_KEY\") ? avalanchePlugin : null,\n\t\t\tgetSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n\t\t\tgetSecret(character, \"ECHOCHAMBERS_API_URL\") && getSecret(character, \"ECHOCHAMBERS_API_KEY\") ? echoChambersPlugin : null,\n\t\t\tgetSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n\t\t\tgetSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n\t\t\tgetSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n\t\t\tgetSecret(character, \"PASSPORT_API_KEY\") ? gitcoinPassportPlugin : null,\n\t\t\tgetSecret(character, \"GENLAYER_PRIVATE_KEY\") ? genLayerPlugin : null,\n\t\t\tgetSecret(character, \"AVAIL_SEED\") && getSecret(character, \"AVAIL_APP_ID\") ? availPlugin : null,\n\t\t\tgetSecret(character, \"OPEN_WEATHER_API_KEY\") ? openWeatherPlugin : null,\n\t\t\tgetSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n\t\t\tgetSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\") ? artheraPlugin : null,\n\t\t\tgetSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_PRIVATE_KEY\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_TESTNET\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"AKASH_MNEMONIC\") && getSecret(character, \"AKASH_WALLET_ADDRESS\") ? akashPlugin : null,\n\t\t\tgetSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n\t\t\tgetSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n\t\t\tgetSecret(character, \"RESERVOIR_API_KEY\") ? createNFTCollectionsPlugin() : null,\n\t\t\tgetSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n\t\t\tgetSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n\t\t\tgetSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") || getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\") ? pythDataPlugin : null,\n\t\t\tgetSecret(character, \"LND_TLS_CERT\") && getSecret(character, \"LND_MACAROON\") && getSecret(character, \"LND_SOCKET\") ? lightningPlugin : null,\n\t\t\tgetSecret(character, \"OPENAI_API_KEY\") && parseBooleanFromText(getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")) ? openaiPlugin : null,\n\t\t\tgetSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n\t\t\tgetSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n\t\t\tgetSecret(character, \"HOLDSTATION_PRIVATE_KEY\") ? holdstationPlugin : null,\n\t\t\tgetSecret(character, \"NVIDIA_NIM_API_KEY\") || getSecret(character, \"NVIDIA_NGC_API_KEY\") ? nvidiaNimPlugin : null,\n\t\t\tgetSecret(character, \"BNB_PRIVATE_KEY\") || getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\") ? bnbPlugin : null,\n\t\t\t(getSecret(character, \"EMAIL_INCOMING_USER\") && getSecret(character, \"EMAIL_INCOMING_PASS\")) || (getSecret(character, \"EMAIL_OUTGOING_USER\") && getSecret(character, \"EMAIL_OUTGOING_PASS\")) ? emailPlugin : null,\n\t\t\tgetSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n\t\t\tgetSecret(character, \"HYPERBOLIC_API_KEY\") ? hyperbolicPlugin : null,\n\t\t\tgetSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n\t\t\tgetSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n\t\t\tgetSecret(character, \"IMGFLIP_USERNAME\") && getSecret(character, \"IMGFLIP_PASSWORD\") ? imgflipPlugin : null,\n\t\t\tgetSecret(character, \"FUNDING_PRIVATE_KEY\") && getSecret(character, \"EVM_RPC_URL\") ? litPlugin : null,\n\t\t\tgetSecret(character, \"ETHSTORAGE_PRIVATE_KEY\") ? ethstoragePlugin : null,\n\t\t\tgetSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n\t\t\tgetSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n\t\t\tgetSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n\t\t\tgetSecret(character, \"DCAP_EVM_PRIVATE_KEY\") && getSecret(character, \"DCAP_MODE\") ? dcapPlugin : null,\n\t\t\tgetSecret(character, \"QUICKINTEL_API_KEY\") ? quickIntelPlugin : null,\n\t\t\tgetSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n\t\t\tgetSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n\t\t\tgetSecret(character, \"ARBITRAGE_EVM_PRIVATE_KEY\") && \n\t\t\t(getSecret(character, \"ARBITRAGE_EVM_PROVIDER_URL\")\n\t\t\t\t|| getSecret(character, \"ARBITRAGE_ETHEREUM_WS_URL\")) \n\t\t\t\t&& getSecret(character, \"ARBITRAGE_FLASHBOTS_RELAY_SIGNING_KEY\") \n\t\t\t\t&& getSecret(character, \"ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS\") ? arbitragePlugin : null,\n\t\t].flat().filter(Boolean),\n\t\tproviders: [],\n\t\tmanagers: [],\n\t\tcacheManager: cache,\n\t\tfetch: logFetch,\n\t\tverifiableInferenceAdapter,\n\t})\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cacheDir = path.resolve(baseDir, character.id, \"cache\")\n\n\tconst cache = new CacheManager(new FsCacheAdapter(cacheDir))\n\treturn cache\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cache = new CacheManager(new DbCacheAdapter(db, character.id))\n\treturn cache\n}\n\nfunction initializeCache(cacheStore: string, character: Character, baseDir?: string, db?: IDatabaseCacheAdapter) {\n\tswitch (cacheStore) {\n\t\tcase CacheStore.REDIS:\n\t\t\tif (process.env.REDIS_URL) {\n\t\t\t\telizaLogger.info(\"Connecting to Redis...\")\n\t\t\t\tconst redisClient = new RedisClient(process.env.REDIS_URL)\n\t\t\t\tif (!character?.id) {\n\t\t\t\t\tthrow new Error(\"CacheStore.REDIS requires id to be set in character definition\")\n\t\t\t\t}\n\t\t\t\treturn new CacheManager(\n\t\t\t\t\tnew DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"REDIS_URL environment variable is not set.\")\n\t\t\t}\n\n\t\tcase CacheStore.DATABASE:\n\t\t\tif (db) {\n\t\t\t\telizaLogger.info(\"Using Database Cache...\")\n\t\t\t\treturn initializeDbCache(character, db)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Database adapter is not provided for CacheStore.Database.\")\n\t\t\t}\n\n\t\tcase CacheStore.FILESYSTEM:\n\t\t\telizaLogger.info(\"Using File System Cache...\")\n\t\t\tif (!baseDir) {\n\t\t\t\tthrow new Error(\"baseDir must be provided for CacheStore.FILESYSTEM.\")\n\t\t\t}\n\t\t\treturn initializeFsCache(baseDir, character)\n\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid cache store: ${cacheStore} or required configuration missing.`)\n\t}\n}\n\nasync function startAgent(character: Character, directClient: DirectClient): Promise<AgentRuntime> {\n\tlet db: IDatabaseAdapter & IDatabaseCacheAdapter\n\ttry {\n\t\tcharacter.id ??= stringToUuid(character.name)\n\t\tcharacter.username ??= character.name\n\n\t\tconst token = getTokenForProvider(character.modelProvider, character)\n\t\tconst dataDir = path.join(__dirname, \"../data\")\n\n\t\tif (!fs.existsSync(dataDir)) {\n\t\t\tfs.mkdirSync(dataDir, { recursive: true })\n\t\t}\n\n\t\tdb = initializeDatabase(dataDir) as IDatabaseAdapter & IDatabaseCacheAdapter\n\n\t\tawait db.init()\n\n\t\tconst cache = initializeCache(process.env.CACHE_STORE ?? CacheStore.DATABASE, character, \"\", db) // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n\t\tconst runtime: AgentRuntime = await createAgent(character, db, cache, token)\n\n\t\t// start services/plugins/process knowledge\n\t\tawait runtime.initialize()\n\n\t\t// start assigned clients\n\t\truntime.clients = await initializeClients(character, runtime)\n\n\t\t// add to container\n\t\tdirectClient.registerAgent(runtime)\n\n\t\t// report to console\n\t\telizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`)\n\n\t\treturn runtime\n\t} catch (error) {\n\t\telizaLogger.error(`Error starting agent for character ${character.name}:`, error)\n\t\telizaLogger.error(error)\n\t\tif (db) {\n\t\t\tawait db.close()\n\t\t}\n\t\tthrow error\n\t}\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\n\t\tserver.once(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\tresolve(false)\n\t\t\t}\n\t\t})\n\n\t\tserver.once(\"listening\", () => {\n\t\t\tserver.close()\n\t\t\tresolve(true)\n\t\t})\n\n\t\tserver.listen(port)\n\t})\n}\n\nconst hasValidRemoteUrls = () => process.env.REMOTE_CHARACTER_URLS && process.env.REMOTE_CHARACTER_URLS !== \"\" && process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\")\n\nconst startAgents = async () => {\n\tconst directClient = new DirectClient()\n\tlet serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\")\n\tconst args = parseArguments()\n\tconst charactersArg = args.characters || args.character\n\tlet characters = [defaultCharacter]\n\n\tif (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n\t\tcharacters = await loadCharacterFromOnchain()\n\t}\n\n\tconst notOnchainJson = !onchainJson || onchainJson == \"null\"\n\n\tif ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n\t\tcharacters = await loadCharacters(charactersArg)\n\t}\n\n\t// Normalize characters for injectable plugins\n\tcharacters = await Promise.all(characters.map(normalizeCharacter))\n\n\ttry {\n\t\tfor (const character of characters) {\n\t\t\tawait startAgent(character, directClient)\n\t\t}\n\t} catch (error) {\n\t\telizaLogger.error(\"Error starting agents:\", error)\n\t}\n\n\t// Find available port\n\twhile (!(await checkPortAvailable(serverPort))) {\n\t\telizaLogger.warn(`Port ${serverPort} is in use, trying ${serverPort + 1}`)\n\t\tserverPort++\n\t}\n\n\t// upload some agent functionality into directClient\n\tdirectClient.startAgent = async (character) => {\n\t\t// Handle plugins\n\t\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\n\t\t// wrap it so we don't have to inject directClient later\n\t\treturn startAgent(character, directClient)\n\t}\n\n\tdirectClient.loadCharacterTryPath = loadCharacterTryPath\n\tdirectClient.jsonToCharacter = jsonToCharacter\n\n\tdirectClient.start(serverPort)\n\n\tif (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n\t\telizaLogger.log(`Server started on alternate port ${serverPort}`)\n\t}\n\n\telizaLogger.log(\"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\")\n}\n\nstartAgents().catch((error) => {\n\telizaLogger.error(\"Unhandled error in startAgents:\", error)\n\tprocess.exit(1)\n})\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n\tprocess.env.PREVENT_UNHANDLED_EXIT &&\n\tparseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n\t// Handle uncaught exceptions to prevent the process from crashing\n\tprocess.on(\"uncaughtException\", function (err) {\n\t\tconsole.error(\"uncaughtException\", err);\n\t});\n\n\t// Handle unhandled rejections to prevent the process from crashing\n\tprocess.on(\"unhandledRejection\", function (err) {\n\t\tconsole.error(\"unhandledRejection\", err);\n\t});\n}\n"}, "512f711d1d0b139355abd740d7e5a0fa63efa049": {"t": 1785754693.5109854, "n": 47219, "h": "aafc22e96ace7f02", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\"\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\"\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\"\nimport { RedisClient } from \"@elizaos/adapter-redis\"\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\"\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\"\nimport { AutoClientInterface } from \"@elizaos/client-auto\"\nimport { DiscordClientInterface } from \"@elizaos/client-discord\"\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\"\nimport { LensAgentClient } from \"@elizaos/client-lens\"\nimport { SlackClientInterface } from \"@elizaos/client-slack\"\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\"\nimport { TelegramAccountClientInterface } from \"@elizaos/client-telegram-account\"\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\"\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\"\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\"\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\"\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\"\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\"\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\"\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\"\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\"\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\"\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\"\nimport {\n\tAgentRuntime,\n\tCacheManager,\n\tCacheStore,\n\ttype Character,\n\ttype Client,\n\tClients,\n\tDbCacheAdapter,\n\tdefaultCharacter,\n\telizaLogger,\n\tFsCacheAdapter,\n\ttype IAgentRuntime,\n\ttype ICacheManager,\n\ttype IDatabaseAdapter,\n\ttype IDatabaseCacheAdapter,\n\tModelProviderName,\n\tparseBooleanFromText,\n\tsettings,\n\tstringToUuid,\n\tvalidateCharacterConfig,\n} from \"@elizaos/core\"\nimport { zgPlugin } from \"@elizaos/plugin-0g\"\nimport { footballPlugin } from \"@elizaos/plugin-football\"\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\"\nimport { normalizeCharacter } from \"@elizaos/plugin-di\"\nimport createGoatPlugin from \"@elizaos/plugin-goat\"\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\"\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\"\nimport { akashPlugin } from \"@elizaos/plugin-akash\"\nimport { alloraPlugin } from \"@elizaos/plugin-allora\"\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\"\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\"\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\"\nimport { availPlugin } from \"@elizaos/plugin-avail\"\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\"\nimport { b2Plugin } from \"@elizaos/plugin-b2\"\nimport { binancePlugin } from \"@elizaos/plugin-binance\"\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\"\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\"\nimport { advancedTradePlugin, coinbaseCommercePlugin, coinbaseMassPaymentsPlugin, tokenContractPlugin, tradePlugin, webhookPlugin } from \"@elizaos/plugin-coinbase\"\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\"\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\"\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\"\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\"\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\"\nimport { evmPlugin } from \"@elizaos/plugin-evm\"\nimport { flowPlugin } from \"@elizaos/plugin-flow\"\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\"\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\"\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\"\nimport { initiaPlugin } from \"@elizaos/plugin-initia\"\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\"\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\"\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\"\nimport { nearPlugin } from \"@elizaos/plugin-near\"\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\"\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\"\nimport { createNodePlugin } from \"@elizaos/plugin-node\"\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\"\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\"\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\"\nimport { quaiPlugin } from \"@elizaos/plugin-quai\"\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\"\nimport { solanaPlugin } from \"@elizaos/plugin-solana\"\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\"\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\"\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\"\nimport { storyPlugin } from \"@elizaos/plugin-story\"\nimport { suiPlugin } from \"@elizaos/plugin-sui\"\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\"\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\"\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\"\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\"\nimport { tonPlugin } from \"@elizaos/plugin-ton\"\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\"\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\"\nimport { injectivePlugin } from \"@elizaos/plugin-injective\"\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\"\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\"\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\"\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\"\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\"\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\"\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\"\nimport { openaiPlugin } from \"@elizaos/plugin-openai\"\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\"\nimport { devinPlugin } from \"@elizaos/plugin-devin\"\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\"\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\"\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\"\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\"\nimport { zxPlugin } from \"@elizaos/plugin-0x\"\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\"\nimport { litPlugin } from \"@elizaos/plugin-lit\"\nimport Database from \"better-sqlite3\"\nimport fs from \"fs\"\nimport net from \"net\"\nimport path from \"path\"\nimport { fileURLToPath } from \"url\"\nimport yargs from \"yargs\"\nimport { emailPlugin } from \"@elizaos/plugin-email\"\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\"\nimport { sunoPlugin } from \"@elizaos/plugin-suno\"\nimport { udioPlugin } from \"@elizaos/plugin-udio\"\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\"\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\"\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\"\nimport { minaPlugin } from \"@elizaos/plugin-mina\"\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\"\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\"\nconst __filename = fileURLToPath(import.meta.url) // get the resolved path to the file\nconst __dirname = path.dirname(__filename) // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n\tconst waitTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime\n\treturn new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\nconst logFetch = async (url: string, options: any) => {\n\telizaLogger.debug(`Fetching ${url}`)\n\t// Disabled to avoid disclosure of sensitive information such as API keys\n\t// elizaLogger.debug(JSON.stringify(options, null, 2));\n\treturn fetch(url, options)\n}\n\nexport function parseArguments(): {\n\tcharacter?: string\n\tcharacters?: string\n} {\n\ttry {\n\t\treturn yargs(process.argv.slice(3))\n\t\t\t.option(\"character\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Path to the character JSON file\",\n\t\t\t})\n\t\t\t.option(\"characters\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Comma separated list of paths to character JSON files\",\n\t\t\t})\n\t\t\t.parseSync()\n\t} catch (error) {\n\t\telizaLogger.error(\"Error parsing arguments:\", error)\n\t\treturn {}\n\t}\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n\ttry {\n\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t} catch (e) {\n\t\treturn null\n\t}\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n\tconst mergeObjects = (baseObj: any, childObj: any) => {\n\t\tconst result: any = {}\n\t\tconst keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})])\n\t\tkeys.forEach((key) => {\n\t\t\tif (typeof baseObj[key] === \"object\" && typeof childObj[key] === \"object\" && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = mergeObjects(baseObj[key], childObj[key])\n\t\t\t} else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = [...(baseObj[key] || []), ...(childObj[key] || [])]\n\t\t\t} else {\n\t\t\t\tresult[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key]\n\t\t\t}\n\t\t})\n\t\treturn result\n\t}\n\treturn mergeObjects(base, child)\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n\treturn Array.isArray(arr) && arr.every((item) => typeof item === \"string\")\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n\tconst jsonText = onchainJson\n\n\tconsole.log(\"JSON:\", jsonText)\n\tif (!jsonText) return []\n\tconst loadedCharacters = []\n\ttry {\n\t\tconst character = JSON.parse(jsonText)\n\t\tvalidateCharacterConfig(character)\n\n\t\t// .id isn't really valid\n\t\tconst characterId = character.id || character.name\n\t\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\n\t\tconst characterSettings = Object.entries(process.env)\n\t\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t\t.reduce((settings, [key, value]) => {\n\t\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\t\tsettings[settingKey] = value\n\t\t\t\treturn settings\n\t\t\t}, {})\n\n\t\tif (Object.keys(characterSettings).length > 0) {\n\t\t\tcharacter.settings = character.settings || {}\n\t\t\tcharacter.settings.secrets = {\n\t\t\t\t...characterSettings,\n\t\t\t\t...character.settings.secrets,\n\t\t\t}\n\t\t}\n\n\t\t// Handle plugins\n\t\tif (isAllStrings(character.plugins)) {\n\t\t\telizaLogger.info(\"Plugins are: \", character.plugins)\n\t\t\tconst importedPlugins = await Promise.all(\n\t\t\t\tcharacter.plugins.map(async (plugin) => {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\treturn importedPlugin.default\n\t\t\t\t})\n\t\t\t)\n\t\t\tcharacter.plugins = importedPlugins\n\t\t}\n\n\t\tloadedCharacters.push(character)\n\t\telizaLogger.info(`Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`)\n\t\treturn loadedCharacters\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n\ttry {\n\t\tconst response = await fetch(url)\n\t\tconst responseJson = await response.json()\n\n\t\tlet characters: Character[] = []\n\t\tif (Array.isArray(responseJson)) {\n\t\t\tcharacters = await Promise.all(responseJson.map((character) => jsonToCharacter(url, character)))\n\t\t} else {\n\t\t\tconst character = await jsonToCharacter(url, responseJson)\n\t\t\tcharacters.push(character)\n\t\t}\n\t\treturn characters\n\t} catch (e) {\n\t\telizaLogger.error(`Error loading character(s) from ${url}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function jsonToCharacter(filePath: string, character: any): Promise<Character> {\n\tvalidateCharacterConfig(character)\n\n\t// .id isn't really valid\n\tconst characterId = character.id || character.name\n\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\tconst characterSettings = Object.entries(process.env)\n\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t.reduce((settings, [key, value]) => {\n\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\treturn { ...settings, [settingKey]: value }\n\t\t}, {})\n\tif (Object.keys(characterSettings).length > 0) {\n\t\tcharacter.settings = character.settings || {}\n\t\tcharacter.settings.secrets = {\n\t\t\t...characterSettings,\n\t\t\t...character.settings.secrets,\n\t\t}\n\t}\n\t// Handle plugins\n\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\tif (character.extends) {\n\t\telizaLogger.info(`Merging ${character.name} character with parent characters`)\n\t\tfor (const extendPath of character.extends) {\n\t\t\tconst baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath))\n\t\t\tcharacter = mergeCharacters(baseCharacter, character)\n\t\t\telizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`)\n\t\t}\n\t}\n\treturn character\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n\tconst content = tryLoadFile(filePath)\n\tif (!content) {\n\t\tthrow new Error(`Character file not found: ${filePath}`)\n\t}\n\tconst character = JSON.parse(content)\n\treturn jsonToCharacter(filePath, character)\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n\tlet content: string | null = null\n\tlet resolvedPath = \"\"\n\n\t// Try different path resolutions in order\n\tconst pathsToTry = [\n\t\tcharacterPath, // exact path as specified\n\t\tpath.resolve(process.cwd(), characterPath), // relative to cwd\n\t\tpath.resolve(process.cwd(), \"agent\", characterPath), // Add this\n\t\tpath.resolve(__dirname, characterPath), // relative to current script\n\t\tpath.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n\t\tpath.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n\t\tpath.resolve(__dirname, \"../../characters\", path.basename(characterPath)), // relative to project root characters dir\n\t]\n\n\telizaLogger.info(\n\t\t\"Trying paths:\",\n\t\tpathsToTry.map((p) => ({\n\t\t\tpath: p,\n\t\t\texists: fs.existsSync(p),\n\t\t}))\n\t)\n\n\tfor (const tryPath of pathsToTry) {\n\t\tcontent = tryLoadFile(tryPath)\n\t\tif (content !== null) {\n\t\t\tresolvedPath = tryPath\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (content === null) {\n\t\telizaLogger.error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t\telizaLogger.error(\"Tried the following paths:\")\n\t\tpathsToTry.forEach((p) => elizaLogger.error(` - ${p}`))\n\t\tthrow new Error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t}\n\ttry {\n\t\tconst character: Character = await loadCharacter(resolvedPath)\n\t\telizaLogger.info(`Successfully loaded character from: ${resolvedPath}`)\n\t\treturn character\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t\tthrow new Error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t}\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n\treturn commaSeparated?.split(\",\").map((value) => value.trim())\n}\n\nasync function readCharactersFromStorage(characterPaths: string[]): Promise<string[]> {\n\ttry {\n\t\tconst uploadDir = path.join(process.cwd(), \"data\", \"characters\")\n\t\tawait fs.promises.mkdir(uploadDir, { recursive: true })\n\t\tconst fileNames = await fs.promises.readdir(uploadDir)\n\t\tfileNames.forEach((fileName) => {\n\t\t\tcharacterPaths.push(path.join(uploadDir, fileName))\n\t\t})\n\t} catch (err) {\n\t\telizaLogger.error(`Error reading directory: ${err.message}`)\n\t}\n\n\treturn characterPaths\n}\n\nexport async function loadCharacters(charactersArg: string): Promise<Character[]> {\n\tlet characterPaths = commaSeparatedStringToArray(charactersArg)\n\n\tif (process.env.USE_CHARACTER_STORAGE === \"true\") {\n\t\tcharacterPaths = await readCharactersFromStorage(characterPaths)\n\t}\n\n\tconst loadedCharacters: Character[] = []\n\n\tif (characterPaths?.length > 0) {\n\t\tfor (const characterPath of characterPaths) {\n\t\t\ttry {\n\t\t\t\tconst character: Character = await loadCharacterTryPath(characterPath)\n\t\t\t\tloadedCharacters.push(character)\n\t\t\t} catch (e) {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasValidRemoteUrls()) {\n\t\telizaLogger.info(\"Loading characters from remote URLs\")\n\t\tconst characterUrls = commaSeparatedStringToArray(process.env.REMOTE_CHARACTER_URLS)\n\t\tfor (const characterUrl of characterUrls) {\n\t\t\tconst characters = await loadCharactersFromUrl(characterUrl)\n\t\t\tloadedCharacters.push(...characters)\n\t\t}\n\t}\n\n\tif (loadedCharacters.length === 0) {\n\t\telizaLogger.info(\"No characters found, using default character\")\n\t\tloadedCharacters.push(defaultCharacter)\n\t}\n\n\treturn loadedCharacters\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n\tif (plugins.length > 0) {\n\t\telizaLogger.info(\"Plugins are: \", plugins)\n\t\tconst importedPlugins = await Promise.all(\n\t\t\tplugins.map(async (plugin) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\tconst functionName = plugin.replace(\"@elizaos/plugin-\", \"\").replace(/-./g, (x) => x[1].toUpperCase()) + \"Plugin\" // Assumes plugin function is camelCased with Plugin suffix\n\t\t\t\t\treturn importedPlugin.default || importedPlugin[functionName]\n\t\t\t\t} catch (importError) {\n\t\t\t\t\telizaLogger.error(`Failed to import plugin: ${plugin}`, importError)\n\t\t\t\t\treturn [] // Return null for failed imports\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\treturn importedPlugins\n\t} else {\n\t\treturn []\n\t}\n}\n\nexport function getTokenForProvider(provider: ModelProviderName, character: Character): string | undefined {\n\tswitch (provider) {\n\t\t// no key needed for llama_local or gaianet\n\t\tcase ModelProviderName.LLAMALOCAL:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OLLAMA:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.GAIANET:\n\t\t\treturn \"\";\n\t\tcase ModelProviderName.BEDROCK:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OPENAI:\n\t\t\treturn character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.ETERNALAI:\n\t\t\treturn character.settings?.secrets?.ETERNALAI_API_KEY || settings.ETERNALAI_API_KEY\n\t\tcase ModelProviderName.NINETEEN_AI:\n\t\t\treturn character.settings?.secrets?.NINETEEN_AI_API_KEY || settings.NINETEEN_AI_API_KEY\n\t\tcase ModelProviderName.LLAMACLOUD:\n\t\tcase ModelProviderName.TOGETHER:\n\t\t\treturn character.settings?.secrets?.LLAMACLOUD_API_KEY || settings.LLAMACLOUD_API_KEY || character.settings?.secrets?.TOGETHER_API_KEY || settings.TOGETHER_API_KEY || character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.CLAUDE_VERTEX:\n\t\tcase ModelProviderName.ANTHROPIC:\n\t\t\treturn character.settings?.secrets?.ANTHROPIC_API_KEY || character.settings?.secrets?.CLAUDE_API_KEY || settings.ANTHROPIC_API_KEY || settings.CLAUDE_API_KEY\n\t\tcase ModelProviderName.REDPILL:\n\t\t\treturn character.settings?.secrets?.REDPILL_API_KEY || settings.REDPILL_API_KEY\n\t\tcase ModelProviderName.OPENROUTER:\n\t\t\treturn character.settings?.secrets?.OPENROUTER_API_KEY || settings.OPENROUTER_API_KEY\n\t\tcase ModelProviderName.GROK:\n\t\t\treturn character.settings?.secrets?.GROK_API_KEY || settings.GROK_API_KEY\n\t\tcase ModelProviderName.HEURIST:\n\t\t\treturn character.settings?.secrets?.HEURIST_API_KEY || settings.HEURIST_API_KEY\n\t\tcase ModelProviderName.GROQ:\n\t\t\treturn character.settings?.secrets?.GROQ_API_KEY || settings.GROQ_API_KEY\n\t\tcase ModelProviderName.GALADRIEL:\n\t\t\treturn character.settings?.secrets?.GALADRIEL_API_KEY || settings.GALADRIEL_API_KEY\n\t\tcase ModelProviderName.FAL:\n\t\t\treturn character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n\t\tcase ModelProviderName.ALI_BAILIAN:\n\t\t\treturn character.settings?.secrets?.ALI_BAILIAN_API_KEY || settings.ALI_BAILIAN_API_KEY\n\t\tcase ModelProviderName.VOLENGINE:\n\t\t\treturn character.settings?.secrets?.VOLENGINE_API_KEY || settings.VOLENGINE_API_KEY\n\t\tcase ModelProviderName.NANOGPT:\n\t\t\treturn character.settings?.secrets?.NANOGPT_API_KEY || settings.NANOGPT_API_KEY\n\t\tcase ModelProviderName.HYPERBOLIC:\n\t\t\treturn character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY\n\n\t\tcase ModelProviderName.VENICE:\n\t\t\treturn character.settings?.secrets?.VENICE_API_KEY || settings.VENICE_API_KEY\n\t\tcase ModelProviderName.ATOMA:\n\t\t\treturn character.settings?.secrets?.ATOMASDK_BEARER_AUTH || settings.ATOMASDK_BEARER_AUTH\n\t\tcase ModelProviderName.NVIDIA:\n\t\t\treturn character.settings?.secrets?.NVIDIA_API_KEY || settings.NVIDIA_API_KEY\n\t\tcase ModelProviderName.AKASH_CHAT_API:\n\t\t\treturn character.settings?.secrets?.AKASH_CHAT_API_KEY || settings.AKASH_CHAT_API_KEY\n\t\tcase ModelProviderName.GOOGLE:\n\t\t\treturn character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY || settings.GOOGLE_GENERATIVE_AI_API_KEY\n\t\tcase ModelProviderName.MISTRAL:\n\t\t\treturn character.settings?.secrets?.MISTRAL_API_KEY || settings.MISTRAL_API_KEY\n\t\tcase ModelProviderName.LETZAI:\n\t\t\treturn character.settings?.secrets?.LETZAI_API_KEY || settings.LETZAI_API_KEY\n\t\tcase ModelProviderName.INFERA:\n\t\t\treturn character.settings?.secrets?.INFERA_API_KEY || settings.INFERA_API_KEY\n\t\tcase ModelProviderName.DEEPSEEK:\n\t\t\treturn character.settings?.secrets?.DEEPSEEK_API_KEY || settings.DEEPSEEK_API_KEY\n\t\tcase ModelProviderName.LIVEPEER:\n\t\t\treturn character.settings?.secrets?.LIVEPEER_GATEWAY_URL || settings.LIVEPEER_GATEWAY_URL\n\t\tdefault:\n\t\t\tconst errorMessage = `Failed to get token - unsupported model provider: ${provider}`\n\t\t\telizaLogger.error(errorMessage)\n\t\t\tthrow new Error(errorMessage)\n\t}\n}\n\nfunction initializeDatabase(dataDir: string) {\n\tif (process.env.MONGODB_CONNECTION_STRING) {\n\t\telizaLogger.log(\"Initializing database on MongoDB Atlas\");\n\t\tconst client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n\t\t\tmaxPoolSize: 100,\n\t\t\tminPoolSize: 5,\n\t\t\tmaxIdleTimeMS: 60000,\n\t\t\tconnectTimeoutMS: 10000,\n\t\t\tserverSelectionTimeoutMS: 5000,\n\t\t\tsocketTimeoutMS: 45000,\n\t\t\tcompressors: ['zlib'],\n\t\t\tretryWrites: true,\n\t\t\tretryReads: true\n\t\t});\n\n\t\tconst dbName = process.env.MONGODB_DATABASE || 'elizaAgent';\n\t\tconst db = new MongoDBDatabaseAdapter(client, dbName);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\n\t\t\t\t\t\"Successfully connected to MongoDB Atlas\"\n\t\t\t\t);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n\t\t\t\tthrow error; // Re-throw to handle it in the calling code\n\t\t\t});\n\n\t\treturn db;\n\t} else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n\t\telizaLogger.info(\"Initializing Supabase connection...\");\n\t\tconst db = new SupabaseDatabaseAdapter(\n\t\t\tprocess.env.SUPABASE_URL,\n\t\t\tprocess.env.SUPABASE_ANON_KEY,\n\t\t);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to Supabase database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to Supabase:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.POSTGRES_URL) {\n\t\telizaLogger.info(\"Initializing PostgreSQL connection...\")\n\t\tconst db = new PostgresDatabaseAdapter({\n\t\t\tconnectionString: process.env.POSTGRES_URL,\n\t\t\tparseInputs: true,\n\t\t})\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to PostgreSQL database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to PostgreSQL:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.PGLITE_DATA_DIR) {\n\t\telizaLogger.info(\"Initializing PgLite adapter...\")\n\t\t// `dataDir: memory://` for in memory pg\n\t\tconst db = new PGLiteDatabaseAdapter({\n\t\t\tdataDir: process.env.PGLITE_DATA_DIR,\n\t\t})\n\t\treturn db\n\t} else if (\n\t\tprocess.env.QDRANT_URL && process.env.QDRANT_KEY && process.env.QDRANT_PORT && process.env.QDRANT_VECTOR_SIZE) {\n\t\telizaLogger.info(\"Initializing Qdrant adapter...\")\n\t\tconst db = new QdrantDatabaseAdapter(process.env.QDRANT_URL, process.env.QDRANT_KEY, Number(process.env.QDRANT_PORT), Number(process.env.QDRANT_VECTOR_SIZE),)\n\t\treturn db\n\t} else {\n\t\tconst filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\")\n\t\telizaLogger.info(`Initializing SQLite database at ${filePath}...`)\n\t\tconst db = new SqliteDatabaseAdapter(new Database(filePath))\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to SQLite database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to SQLite:\", error)\n\t\t\t})\n\n\t\treturn db\n\t}\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(character: Character, runtime: IAgentRuntime) {\n\t// each client can only register once\n\t// and if we want two we can explicitly support it\n\tconst clients: Record<string, any> = {}\n\tconst clientTypes: string[] = character.clients?.map((str) => str.toLowerCase()) || []\n\telizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name)\n\n\n\t// Start Auto Client if \"auto\" detected as a configured client\n\tif (clientTypes.includes(Clients.AUTO)) {\n\t\tconst autoClient = await AutoClientInterface.start(runtime)\n\t\tif (autoClient) clients.auto = autoClient\n\t}\n\n\tif (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n\tif (clientTypes.includes(Clients.DISCORD)) {\n\t\tconst discordClient = await DiscordClientInterface.start(runtime)\n\t\tif (discordClient) clients.discord = discordClient\n\t}\n\n\tif (clientTypes.includes(Clients.TELEGRAM)) {\n\t\tconst telegramClient = await TelegramClientInterface.start(runtime)\n\t\tif (telegramClient) clients.telegram = telegramClient\n\t}\n\n if (clientTypes.includes(Clients.TELEGRAM_ACCOUNT)) {\n const telegramAccountClient = await TelegramAccountClientInterface.start(runtime);\n if (telegramAccountClient) clients.telegram_account = telegramAccountClient;\n }\n\n\tif (clientTypes.includes(Clients.TWITTER)) {\n\t\tconst twitterClient = await TwitterClientInterface.start(runtime)\n\t\tif (twitterClient) {\n\t\t\tclients.twitter = twitterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.ALEXA)) {\n\t\tconst alexaClient = await AlexaClientInterface.start(runtime);\n\t\tif (alexaClient) {\n\t\t\tclients.alexa = alexaClient;\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.INSTAGRAM)) {\n\t\tconst instagramClient = await InstagramClientInterface.start(runtime)\n\t\tif (instagramClient) {\n\t\t\tclients.instagram = instagramClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.FARCASTER)) {\n\t\tconst farcasterClient = await FarcasterClientInterface.start(runtime)\n\t\tif (farcasterClient) {\n\t\t\tclients.farcaster = farcasterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(\"lens\")) {\n\t\tconst lensClient = new LensAgentClient(runtime)\n\t\tlensClient.start()\n\t\tclients.lens = lensClient\n\t}\n\n\tif (clientTypes.includes(Clients.SIMSAI)) {\n\t\tconst simsaiClient = await JeeterClientInterface.start(runtime)\n\t\tif (simsaiClient) clients.simsai = simsaiClient\n\t}\n\n\telizaLogger.log(\"client keys\", Object.keys(clients))\n\n\t// TODO: Add Slack client to the list\n\t// Initialize clients as an object\n\n\tif (clientTypes.includes(\"slack\")) {\n\t\tconst slackClient = await SlackClientInterface.start(runtime)\n\t\tif (slackClient) clients.slack = slackClient // Use object property instead of push\n\t}\n\n\tfunction determineClientType(client: Client): string {\n\t\t// Check if client has a direct type identifier\n\t\tif (\"type\" in client) {\n\t\t\treturn (client as any).type\n\t\t}\n\n\t\t// Check constructor name\n\t\tconst constructorName = client.constructor?.name\n\t\tif (constructorName && !constructorName.includes(\"Object\")) {\n\t\t\treturn constructorName.toLowerCase().replace(\"client\", \"\")\n\t\t}\n\n\t\t// Fallback: Generate a unique identifier\n\t\treturn `client_${Date.now()}`\n\t}\n\n\tif (character.plugins?.length > 0) {\n\t\tfor (const plugin of character.plugins) {\n\t\t\tif (plugin.clients) {\n\t\t\t\tfor (const client of plugin.clients) {\n\t\t\t\t\tconst startedClient = await client.start(runtime)\n\t\t\t\t\tconst clientType = determineClientType(client)\n\t\t\t\t\telizaLogger.debug(`Initializing client of type: ${clientType}`)\n\t\t\t\t\tclients[clientType] = startedClient\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn clients\n}\n\nfunction getSecret(character: Character, secret: string) {\n\treturn character.settings?.secrets?.[secret] || process.env[secret]\n}\n\nlet nodePlugin: any | undefined\n\nexport async function createAgent(character: Character, db: IDatabaseAdapter, cache: ICacheManager, token: string): Promise<AgentRuntime> {\n\telizaLogger.log(`Creating runtime for character ${character.name}`)\n\n\tnodePlugin ??= createNodePlugin()\n\n\tconst teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\"\n\tconst walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\")\n\n\t// Validate TEE configuration\n\tif (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n\t\telizaLogger.error(\"A WALLET_SECRET_SALT required when TEE_MODE is enabled\")\n\t\tthrow new Error(\"Invalid TEE configuration\")\n\t}\n\n\tlet goatPlugin: any | undefined\n\n\tif (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n\t\tgoatPlugin = await createGoatPlugin((secret) => getSecret(character, secret))\n\t}\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n\t// Initialize Reclaim adapter if environment variables are present\n\t// let verifiableInferenceAdapter;\n\t// if (\n\t// process.env.RECLAIM_APP_ID &&\n\t// process.env.RECLAIM_APP_SECRET &&\n\t// process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n\t// ) {\n\t// verifiableInferenceAdapter = new ReclaimAdapter({\n\t// appId: process.env.RECLAIM_APP_ID,\n\t// appSecret: process.env.RECLAIM_APP_SECRET,\n\t// modelProvider: character.modelProvider,\n\t// token,\n\t// });\n\t// elizaLogger.log(\"Verifiable inference adapter initialized\");\n\t// }\n\t// Initialize Opacity adapter if environment variables are present\n\tlet verifiableInferenceAdapter\n\tif (process.env.OPACITY_TEAM_ID && process.env.OPACITY_CLOUDFLARE_NAME && process.env.OPACITY_PROVER_URL && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new OpacityAdapter({\n\t\t\tteamId: process.env.OPACITY_TEAM_ID,\n\t\t\tteamName: process.env.OPACITY_CLOUDFLARE_NAME,\n\t\t\topacityProverUrl: process.env.OPACITY_PROVER_URL,\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken: token,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference adapter initialized\")\n\t\telizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID)\n\t\telizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME)\n\t\telizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL)\n\t\telizaLogger.log(\"modelProvider\", character.modelProvider)\n\t\telizaLogger.log(\"token\", token)\n\t}\n\tif (process.env.PRIMUS_APP_ID && process.env.PRIMUS_APP_SECRET && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new PrimusAdapter({\n\t\t\tappId: process.env.PRIMUS_APP_ID,\n\t\t\tappSecret: process.env.PRIMUS_APP_SECRET,\n\t\t\tattMode: \"proxytls\",\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference primus adapter initialized\")\n\t}\n\n\treturn new AgentRuntime({\n\t\tdatabaseAdapter: db,\n\t\ttoken,\n\t\tmodelProvider: character.modelProvider,\n\t\tevaluators: [],\n\t\tcharacter,\n\t\t// character.plugins are handled when clients are added\n\t\tplugins: [\n\t\t\tparseBooleanFromText(getSecret(character, \"BITMIND\")) && getSecret(character, \"BITMIND_API_TOKEN\") ? bittensorPlugin : null,\n\t\t\tparseBooleanFromText(getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")) ? emailAutomationPlugin : null,\n\t\t\tgetSecret(character, \"IQ_WALLET_ADDRESS\") && getSecret(character, \"IQSOlRPC\") ? elizaCodeinPlugin : null,\n\t\t\tbootstrapPlugin,\n\t\t\tgetSecret(character, \"CDP_API_KEY_NAME\") && getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") && getSecret(character, \"CDP_AGENT_KIT_NETWORK\") ? agentKitPlugin : null,\n\t\t\tgetSecret(character, \"DEXSCREENER_API_KEY\") ? dexScreenerPlugin : null,\n\t\t\tgetSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n\t\t\tgetSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\") ? confluxPlugin : null,\n\t\t\tnodePlugin,\n\t\t\tgetSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") && getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\") ? nitroPlugin : null,\n\t\t\tgetSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n\t\t\tgetSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? [solanaPlugin, solanaPluginV2] : null,\n\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") ? solanaAgentkitPlugin : null,\n\t\t\tgetSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n\t\t\t(getSecret(character, \"NEAR_ADDRESS\") || getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) && getSecret(character, \"NEAR_WALLET_SECRET_KEY\") ? nearPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? evmPlugin : null,\n\t\t\t(getSecret(character, \"EVM_PUBLIC_KEY\") || getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) && getSecret(character, \"INJECTIVE_PRIVATE_KEY\") ? injectivePlugin : null,\n\t\t\tgetSecret(character, \"COSMOS_RECOVERY_PHRASE\") && getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") && createCosmosPlugin(),\n\t\t\t(getSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))) &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n\t\t\t\t? nftGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n\t\t\tgetSecret(character, \"COINMARKETCAP_API_KEY\") ? coinmarketcapPlugin : null,\n\t\t\tgetSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_COMMERCE_KEY\") ? coinbaseCommercePlugin : null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"OPENAI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"VENICE_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NVIDIA_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NINETEEN_AI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"HEURIST_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"LIVEPEER_GATEWAY_URL\")\n\t\t\t\t? imageGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n\t\t\t...(getSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") ? [coinbaseMassPaymentsPlugin, tradePlugin, tokenContractPlugin, advancedTradePlugin] : []),\n\t\t\t...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n\t\t\tteeMode !== TEEMode.OFF && walletSecretSalt && getSecret(character, \"VLOG\") ? verifiableLogPlugin : null,\n\t\t\tgetSecret(character, \"SGX\") ? sgxPlugin : null,\n\t\t\tgetSecret(character, \"ENABLE_TEE_LOG\") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, \"SGX\")) ? teeLogPlugin : null,\n\t\t\tgetSecret(character, \"OMNIFLIX_API_URL\") && getSecret(character, \"OMNIFLIX_MNEMONIC\") ? OmniflixPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") && getSecret(character, \"COINBASE_NOTIFICATION_URI\") ? webhookPlugin : null,\n \t\t goatPlugin,\n zilliqaPlugin,\n\t\t\tgetSecret(character, \"COINGECKO_API_KEY\") || getSecret(character, \"COINGECKO_PRO_API_KEY\") ? coingeckoPlugin : null,\n\t\t\tgetSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n\t\t\tgetSecret(character, \"ABSTRACT_PRIVATE_KEY\") ? abstractPlugin : null,\n\t\t\tgetSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n\t\t\tgetSecret(character, \"BINANCE_API_KEY\") && getSecret(character, \"BINANCE_SECRET_KEY\") ? binancePlugin : null,\n\t\t\tgetSecret(character, \"FLOW_ADDRESS\") && getSecret(character, \"FLOW_PRIVATE_KEY\") ? flowPlugin : null,\n\t\t\tgetSecret(character, \"LENS_ADDRESS\") && getSecret(character, \"LENS_PRIVATE_KEY\") ? lensPlugin : null,\n\t\t\tgetSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n\t\t\tgetSecret(character, \"MIND_COLD_WALLET_ADDRESS\") ? mindNetworkPlugin : null,\n\t\t\tgetSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n\t\t\tgetSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n\t\t\tgetSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\") ? cronosZkEVMPlugin : null,\n\t\t\tgetSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n\t\t\tgetSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n\t\t\tgetSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n\t\t\tgetSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n\t\t\tgetSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n\t\t\tgetSecret(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\")\n\t\t\t\t? squidRouterPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n\t\t\tgetSecret(character, \"AVALANCHE_PRIVATE_KEY\") ? avalanchePlugin : null,\n\t\t\tgetSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n\t\t\tgetSecret(character, \"ECHOCHAMBERS_API_URL\") && getSecret(character, \"ECHOCHAMBERS_API_KEY\") ? echoChambersPlugin : null,\n\t\t\tgetSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n\t\t\tgetSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n\t\t\tgetSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n\t\t\tgetSecret(character, \"PASSPORT_API_KEY\") ? gitcoinPassportPlugin : null,\n\t\t\tgetSecret(character, \"GENLAYER_PRIVATE_KEY\") ? genLayerPlugin : null,\n\t\t\tgetSecret(character, \"AVAIL_SEED\") && getSecret(character, \"AVAIL_APP_ID\") ? availPlugin : null,\n\t\t\tgetSecret(character, \"OPEN_WEATHER_API_KEY\") ? openWeatherPlugin : null,\n\t\t\tgetSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n\t\t\tgetSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\") ? artheraPlugin : null,\n\t\t\tgetSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_PRIVATE_KEY\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_TESTNET\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"AKASH_MNEMONIC\") && getSecret(character, \"AKASH_WALLET_ADDRESS\") ? akashPlugin : null,\n\t\t\tgetSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n\t\t\tgetSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n\t\t\tgetSecret(character, \"RESERVOIR_API_KEY\") ? createNFTCollectionsPlugin() : null,\n\t\t\tgetSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n\t\t\tgetSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n\t\t\tgetSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") || getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\") ? pythDataPlugin : null,\n\t\t\tgetSecret(character, \"LND_TLS_CERT\") && getSecret(character, \"LND_MACAROON\") && getSecret(character, \"LND_SOCKET\") ? lightningPlugin : null,\n\t\t\tgetSecret(character, \"OPENAI_API_KEY\") && parseBooleanFromText(getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")) ? openaiPlugin : null,\n\t\t\tgetSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n\t\t\tgetSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n\t\t\tgetSecret(character, \"HOLDSTATION_PRIVATE_KEY\") ? holdstationPlugin : null,\n\t\t\tgetSecret(character, \"NVIDIA_NIM_API_KEY\") || getSecret(character, \"NVIDIA_NGC_API_KEY\") ? nvidiaNimPlugin : null,\n\t\t\tgetSecret(character, \"BNB_PRIVATE_KEY\") || getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\") ? bnbPlugin : null,\n\t\t\t(getSecret(character, \"EMAIL_INCOMING_USER\") && getSecret(character, \"EMAIL_INCOMING_PASS\")) || (getSecret(character, \"EMAIL_OUTGOING_USER\") && getSecret(character, \"EMAIL_OUTGOING_PASS\")) ? emailPlugin : null,\n\t\t\tgetSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n\t\t\tgetSecret(character, \"HYPERBOLIC_API_KEY\") ? hyperbolicPlugin : null,\n\t\t\tgetSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n\t\t\tgetSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n\t\t\tgetSecret(character, \"IMGFLIP_USERNAME\") && getSecret(character, \"IMGFLIP_PASSWORD\") ? imgflipPlugin : null,\n\t\t\tgetSecret(character, \"FUNDING_PRIVATE_KEY\") && getSecret(character, \"EVM_RPC_URL\") ? litPlugin : null,\n\t\t\tgetSecret(character, \"ETHSTORAGE_PRIVATE_KEY\") ? ethstoragePlugin : null,\n\t\t\tgetSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n\t\t\tgetSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n\t\t\tgetSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n\t\t\tgetSecret(character, \"DCAP_EVM_PRIVATE_KEY\") && getSecret(character, \"DCAP_MODE\") ? dcapPlugin : null,\n\t\t\tgetSecret(character, \"QUICKINTEL_API_KEY\") ? quickIntelPlugin : null,\n\t\t\tgetSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n\t\t\tgetSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n\t\t].flat().filter(Boolean),\n\t\tproviders: [],\n\t\tmanagers: [],\n\t\tcacheManager: cache,\n\t\tfetch: logFetch,\n\t\tverifiableInferenceAdapter,\n\t})\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cacheDir = path.resolve(baseDir, character.id, \"cache\")\n\n\tconst cache = new CacheManager(new FsCacheAdapter(cacheDir))\n\treturn cache\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cache = new CacheManager(new DbCacheAdapter(db, character.id))\n\treturn cache\n}\n\nfunction initializeCache(cacheStore: string, character: Character, baseDir?: string, db?: IDatabaseCacheAdapter) {\n\tswitch (cacheStore) {\n\t\tcase CacheStore.REDIS:\n\t\t\tif (process.env.REDIS_URL) {\n\t\t\t\telizaLogger.info(\"Connecting to Redis...\")\n\t\t\t\tconst redisClient = new RedisClient(process.env.REDIS_URL)\n\t\t\t\tif (!character?.id) {\n\t\t\t\t\tthrow new Error(\"CacheStore.REDIS requires id to be set in character definition\")\n\t\t\t\t}\n\t\t\t\treturn new CacheManager(\n\t\t\t\t\tnew DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"REDIS_URL environment variable is not set.\")\n\t\t\t}\n\n\t\tcase CacheStore.DATABASE:\n\t\t\tif (db) {\n\t\t\t\telizaLogger.info(\"Using Database Cache...\")\n\t\t\t\treturn initializeDbCache(character, db)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Database adapter is not provided for CacheStore.Database.\")\n\t\t\t}\n\n\t\tcase CacheStore.FILESYSTEM:\n\t\t\telizaLogger.info(\"Using File System Cache...\")\n\t\t\tif (!baseDir) {\n\t\t\t\tthrow new Error(\"baseDir must be provided for CacheStore.FILESYSTEM.\")\n\t\t\t}\n\t\t\treturn initializeFsCache(baseDir, character)\n\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid cache store: ${cacheStore} or required configuration missing.`)\n\t}\n}\n\nasync function startAgent(character: Character, directClient: DirectClient): Promise<AgentRuntime> {\n\tlet db: IDatabaseAdapter & IDatabaseCacheAdapter\n\ttry {\n\t\tcharacter.id ??= stringToUuid(character.name)\n\t\tcharacter.username ??= character.name\n\n\t\tconst token = getTokenForProvider(character.modelProvider, character)\n\t\tconst dataDir = path.join(__dirname, \"../data\")\n\n\t\tif (!fs.existsSync(dataDir)) {\n\t\t\tfs.mkdirSync(dataDir, { recursive: true })\n\t\t}\n\n\t\tdb = initializeDatabase(dataDir) as IDatabaseAdapter & IDatabaseCacheAdapter\n\n\t\tawait db.init()\n\n\t\tconst cache = initializeCache(process.env.CACHE_STORE ?? CacheStore.DATABASE, character, \"\", db) // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n\t\tconst runtime: AgentRuntime = await createAgent(character, db, cache, token)\n\n\t\t// start services/plugins/process knowledge\n\t\tawait runtime.initialize()\n\n\t\t// start assigned clients\n\t\truntime.clients = await initializeClients(character, runtime)\n\n\t\t// add to container\n\t\tdirectClient.registerAgent(runtime)\n\n\t\t// report to console\n\t\telizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`)\n\n\t\treturn runtime\n\t} catch (error) {\n\t\telizaLogger.error(`Error starting agent for character ${character.name}:`, error)\n\t\telizaLogger.error(error)\n\t\tif (db) {\n\t\t\tawait db.close()\n\t\t}\n\t\tthrow error\n\t}\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\n\t\tserver.once(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\tresolve(false)\n\t\t\t}\n\t\t})\n\n\t\tserver.once(\"listening\", () => {\n\t\t\tserver.close()\n\t\t\tresolve(true)\n\t\t})\n\n\t\tserver.listen(port)\n\t})\n}\n\nconst hasValidRemoteUrls = () => process.env.REMOTE_CHARACTER_URLS && process.env.REMOTE_CHARACTER_URLS !== \"\" && process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\")\n\nconst startAgents = async () => {\n\tconst directClient = new DirectClient()\n\tlet serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\")\n\tconst args = parseArguments()\n\tconst charactersArg = args.characters || args.character\n\tlet characters = [defaultCharacter]\n\n\tif (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n\t\tcharacters = await loadCharacterFromOnchain()\n\t}\n\n\tconst notOnchainJson = !onchainJson || onchainJson == \"null\"\n\n\tif ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n\t\tcharacters = await loadCharacters(charactersArg)\n\t}\n\n\t// Normalize characters for injectable plugins\n\tcharacters = await Promise.all(characters.map(normalizeCharacter))\n\n\ttry {\n\t\tfor (const character of characters) {\n\t\t\tawait startAgent(character, directClient)\n\t\t}\n\t} catch (error) {\n\t\telizaLogger.error(\"Error starting agents:\", error)\n\t}\n\n\t// Find available port\n\twhile (!(await checkPortAvailable(serverPort))) {\n\t\telizaLogger.warn(`Port ${serverPort} is in use, trying ${serverPort + 1}`)\n\t\tserverPort++\n\t}\n\n\t// upload some agent functionality into directClient\n\tdirectClient.startAgent = async (character) => {\n\t\t// Handle plugins\n\t\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\n\t\t// wrap it so we don't have to inject directClient later\n\t\treturn startAgent(character, directClient)\n\t}\n\n\tdirectClient.loadCharacterTryPath = loadCharacterTryPath\n\tdirectClient.jsonToCharacter = jsonToCharacter\n\n\tdirectClient.start(serverPort)\n\n\tif (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n\t\telizaLogger.log(`Server started on alternate port ${serverPort}`)\n\t}\n\n\telizaLogger.log(\"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\")\n}\n\nstartAgents().catch((error) => {\n\telizaLogger.error(\"Unhandled error in startAgents:\", error)\n\tprocess.exit(1)\n})\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n\tprocess.env.PREVENT_UNHANDLED_EXIT &&\n\tparseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n\t// Handle uncaught exceptions to prevent the process from crashing\n\tprocess.on(\"uncaughtException\", function (err) {\n\t\tconsole.error(\"uncaughtException\", err);\n\t});\n\n\t// Handle unhandled rejections to prevent the process from crashing\n\tprocess.on(\"unhandledRejection\", function (err) {\n\t\tconsole.error(\"unhandledRejection\", err);\n\t});\n}\n"}, "e8d0499d990358f42bf587ad22ee9a0ec7d84072": {"t": 1785754695.1514862, "n": 46896, "h": "56ff84da40ee8fc8", "c": "import { PGLiteDatabaseAdapter } from \"@elizaos/adapter-pglite\"\nimport { PostgresDatabaseAdapter } from \"@elizaos/adapter-postgres\"\nimport { QdrantDatabaseAdapter } from \"@elizaos/adapter-qdrant\"\nimport { RedisClient } from \"@elizaos/adapter-redis\"\nimport { SqliteDatabaseAdapter } from \"@elizaos/adapter-sqlite\"\nimport { SupabaseDatabaseAdapter } from \"@elizaos/adapter-supabase\"\nimport { AutoClientInterface } from \"@elizaos/client-auto\"\nimport { DiscordClientInterface } from \"@elizaos/client-discord\"\nimport { InstagramClientInterface } from \"@elizaos/client-instagram\"\nimport { LensAgentClient } from \"@elizaos/client-lens\"\nimport { SlackClientInterface } from \"@elizaos/client-slack\"\nimport { TelegramClientInterface } from \"@elizaos/client-telegram\"\nimport { TwitterClientInterface } from \"@elizaos/client-twitter\"\nimport { AlexaClientInterface } from \"@elizaos/client-alexa\";\nimport { MongoDBDatabaseAdapter } from \"@elizaos/adapter-mongodb\"\n\nimport { FarcasterClientInterface } from \"@elizaos/client-farcaster\"\nimport { OmniflixPlugin } from \"@elizaos/plugin-omniflix\"\nimport { JeeterClientInterface } from \"@elizaos/client-simsai\"\nimport { XmtpClientInterface } from \"@elizaos/client-xmtp\";\nimport { DirectClient } from \"@elizaos/client-direct\"\nimport { agentKitPlugin } from \"@elizaos/plugin-agentkit\"\nimport { gelatoPlugin } from \"@elizaos/plugin-gelato\";\nimport { PrimusAdapter } from \"@elizaos/plugin-primus\"\nimport { lightningPlugin } from \"@elizaos/plugin-lightning\"\nimport { elizaCodeinPlugin, onchainJson } from \"@elizaos/plugin-iq6900\"\nimport { dcapPlugin } from \"@elizaos/plugin-dcap\"\nimport {\n\tAgentRuntime,\n\tCacheManager,\n\tCacheStore,\n\ttype Character,\n\ttype Client,\n\tClients,\n\tDbCacheAdapter,\n\tdefaultCharacter,\n\telizaLogger,\n\tFsCacheAdapter,\n\ttype IAgentRuntime,\n\ttype ICacheManager,\n\ttype IDatabaseAdapter,\n\ttype IDatabaseCacheAdapter,\n\tModelProviderName,\n\tparseBooleanFromText,\n\tsettings,\n\tstringToUuid,\n\tvalidateCharacterConfig,\n} from \"@elizaos/core\"\nimport { zgPlugin } from \"@elizaos/plugin-0g\"\nimport { footballPlugin } from \"@elizaos/plugin-football\"\n\nimport { bootstrapPlugin } from \"@elizaos/plugin-bootstrap\"\nimport { normalizeCharacter } from \"@elizaos/plugin-di\"\nimport createGoatPlugin from \"@elizaos/plugin-goat\"\nimport createZilliqaPlugin from \"@elizaos/plugin-zilliqa\";\n\n// import { intifacePlugin } from \"@elizaos/plugin-intiface\";\nimport { ThreeDGenerationPlugin } from \"@elizaos/plugin-3d-generation\"\nimport { abstractPlugin } from \"@elizaos/plugin-abstract\"\nimport { akashPlugin } from \"@elizaos/plugin-akash\"\nimport { alloraPlugin } from \"@elizaos/plugin-allora\"\nimport { aptosPlugin } from \"@elizaos/plugin-aptos\"\nimport { artheraPlugin } from \"@elizaos/plugin-arthera\"\nimport { autonomePlugin } from \"@elizaos/plugin-autonome\"\nimport { availPlugin } from \"@elizaos/plugin-avail\"\nimport { avalanchePlugin } from \"@elizaos/plugin-avalanche\"\nimport { b2Plugin } from \"@elizaos/plugin-b2\"\nimport { binancePlugin } from \"@elizaos/plugin-binance\"\nimport { birdeyePlugin } from \"@elizaos/plugin-birdeye\"\nimport { bittensorPlugin } from \"@elizaos/plugin-bittensor\";\nimport { bnbPlugin } from \"@elizaos/plugin-bnb\"\nimport { advancedTradePlugin, coinbaseCommercePlugin, coinbaseMassPaymentsPlugin, tokenContractPlugin, tradePlugin, webhookPlugin } from \"@elizaos/plugin-coinbase\"\nimport { coingeckoPlugin } from \"@elizaos/plugin-coingecko\"\nimport { coinmarketcapPlugin } from \"@elizaos/plugin-coinmarketcap\"\nimport { confluxPlugin } from \"@elizaos/plugin-conflux\"\nimport { createCosmosPlugin } from \"@elizaos/plugin-cosmos\"\nimport { cronosZkEVMPlugin } from \"@elizaos/plugin-cronoszkevm\"\nimport { evmPlugin } from \"@elizaos/plugin-evm\"\nimport { flowPlugin } from \"@elizaos/plugin-flow\"\nimport { fuelPlugin } from \"@elizaos/plugin-fuel\"\nimport { genLayerPlugin } from \"@elizaos/plugin-genlayer\"\nimport { gitcoinPassportPlugin } from \"@elizaos/plugin-gitcoin-passport\"\nimport { initiaPlugin } from \"@elizaos/plugin-initia\"\nimport { imageGenerationPlugin } from \"@elizaos/plugin-image-generation\"\nimport { lensPlugin } from \"@elizaos/plugin-lensNetwork\"\nimport { mindNetworkPlugin } from \"@elizaos/plugin-mind-network\";\nimport { multiversxPlugin } from \"@elizaos/plugin-multiversx\"\nimport { nearPlugin } from \"@elizaos/plugin-near\"\nimport { newsPlugin } from \"@elizaos/plugin-news\";\nimport createNFTCollectionsPlugin from \"@elizaos/plugin-nft-collections\"\nimport { nftGenerationPlugin } from \"@elizaos/plugin-nft-generation\"\nimport { createNodePlugin } from \"@elizaos/plugin-node\"\nimport { obsidianPlugin } from \"@elizaos/plugin-obsidian\"\nimport { OpacityAdapter } from \"@elizaos/plugin-opacity\"\nimport { openWeatherPlugin } from \"@elizaos/plugin-open-weather\"\nimport { quaiPlugin } from \"@elizaos/plugin-quai\"\nimport { sgxPlugin } from \"@elizaos/plugin-sgx\"\nimport { solanaPlugin } from \"@elizaos/plugin-solana\"\nimport { solanaPluginV2 } from \"@elizaos/plugin-solana-v2\";\nimport { solanaAgentkitPlugin } from \"@elizaos/plugin-solana-agent-kit\"\nimport { squidRouterPlugin } from \"@elizaos/plugin-squid-router\"\nimport { stargazePlugin } from \"@elizaos/plugin-stargaze\"\nimport { storyPlugin } from \"@elizaos/plugin-story\"\nimport { suiPlugin } from \"@elizaos/plugin-sui\"\nimport { TEEMode, teePlugin } from \"@elizaos/plugin-tee\"\nimport { teeLogPlugin } from \"@elizaos/plugin-tee-log\"\nimport { teeMarlinPlugin } from \"@elizaos/plugin-tee-marlin\"\nimport { verifiableLogPlugin } from \"@elizaos/plugin-tee-verifiable-log\"\nimport { tonPlugin } from \"@elizaos/plugin-ton\"\nimport { webSearchPlugin } from \"@elizaos/plugin-web-search\"\nimport { dkgPlugin } from \"@elizaos/plugin-dkg\"\nimport { injectivePlugin } from \"@elizaos/plugin-injective\"\nimport { giphyPlugin } from \"@elizaos/plugin-giphy\"\nimport { letzAIPlugin } from \"@elizaos/plugin-letzai\"\nimport { thirdwebPlugin } from \"@elizaos/plugin-thirdweb\"\nimport { hyperliquidPlugin } from \"@elizaos/plugin-hyperliquid\"\nimport { moralisPlugin } from \"@elizaos/plugin-moralis\";\nimport { echoChambersPlugin } from \"@elizaos/plugin-echochambers\"\nimport { dexScreenerPlugin } from \"@elizaos/plugin-dexscreener\"\nimport { pythDataPlugin } from \"@elizaos/plugin-pyth-data\"\nimport { openaiPlugin } from \"@elizaos/plugin-openai\"\nimport nitroPlugin from \"@elizaos/plugin-router-nitro\"\nimport { devinPlugin } from \"@elizaos/plugin-devin\"\nimport { zksyncEraPlugin } from \"@elizaos/plugin-zksync-era\"\nimport { chainbasePlugin } from \"@elizaos/plugin-chainbase\"\nimport { holdstationPlugin } from \"@elizaos/plugin-holdstation\"\nimport { nvidiaNimPlugin } from \"@elizaos/plugin-nvidia-nim\"\nimport { zxPlugin } from \"@elizaos/plugin-0x\"\nimport { hyperbolicPlugin } from \"@elizaos/plugin-hyperbolic\"\nimport { litPlugin } from \"@elizaos/plugin-lit\"\nimport Database from \"better-sqlite3\"\nimport fs from \"fs\"\nimport net from \"net\"\nimport path from \"path\"\nimport { fileURLToPath } from \"url\"\nimport yargs from \"yargs\"\nimport { emailPlugin } from \"@elizaos/plugin-email\"\nimport { emailAutomationPlugin } from \"@elizaos/plugin-email-automation\";\nimport { seiPlugin } from \"@elizaos/plugin-sei\"\nimport { sunoPlugin } from \"@elizaos/plugin-suno\"\nimport { udioPlugin } from \"@elizaos/plugin-udio\"\nimport { imgflipPlugin } from \"@elizaos/plugin-imgflip\"\nimport { ethstoragePlugin } from \"@elizaos/plugin-ethstorage\"\nimport { zerionPlugin } from \"@elizaos/plugin-zerion\"\nimport { minaPlugin } from \"@elizaos/plugin-mina\"\nimport { ankrPlugin } from \"@elizaos/plugin-ankr\";\nimport { formPlugin } from \"@elizaos/plugin-form\";\nimport { MongoClient } from \"mongodb\";\nimport { quickIntelPlugin } from \"@elizaos/plugin-quick-intel\"\n\nimport { trikonPlugin } from \"@elizaos/plugin-trikon\"\nconst __filename = fileURLToPath(import.meta.url) // get the resolved path to the file\nconst __dirname = path.dirname(__filename) // get the name of the directory\n\nexport const wait = (minTime = 1000, maxTime = 3000) => {\n\tconst waitTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime\n\treturn new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\nconst logFetch = async (url: string, options: any) => {\n\telizaLogger.debug(`Fetching ${url}`)\n\t// Disabled to avoid disclosure of sensitive information such as API keys\n\t// elizaLogger.debug(JSON.stringify(options, null, 2));\n\treturn fetch(url, options)\n}\n\nexport function parseArguments(): {\n\tcharacter?: string\n\tcharacters?: string\n} {\n\ttry {\n\t\treturn yargs(process.argv.slice(3))\n\t\t\t.option(\"character\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Path to the character JSON file\",\n\t\t\t})\n\t\t\t.option(\"characters\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Comma separated list of paths to character JSON files\",\n\t\t\t})\n\t\t\t.parseSync()\n\t} catch (error) {\n\t\telizaLogger.error(\"Error parsing arguments:\", error)\n\t\treturn {}\n\t}\n}\n\nfunction tryLoadFile(filePath: string): string | null {\n\ttry {\n\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t} catch (e) {\n\t\treturn null\n\t}\n}\nfunction mergeCharacters(base: Character, child: Character): Character {\n\tconst mergeObjects = (baseObj: any, childObj: any) => {\n\t\tconst result: any = {}\n\t\tconst keys = new Set([...Object.keys(baseObj || {}), ...Object.keys(childObj || {})])\n\t\tkeys.forEach((key) => {\n\t\t\tif (typeof baseObj[key] === \"object\" && typeof childObj[key] === \"object\" && !Array.isArray(baseObj[key]) && !Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = mergeObjects(baseObj[key], childObj[key])\n\t\t\t} else if (Array.isArray(baseObj[key]) || Array.isArray(childObj[key])) {\n\t\t\t\tresult[key] = [...(baseObj[key] || []), ...(childObj[key] || [])]\n\t\t\t} else {\n\t\t\t\tresult[key] = childObj[key] !== undefined ? childObj[key] : baseObj[key]\n\t\t\t}\n\t\t})\n\t\treturn result\n\t}\n\treturn mergeObjects(base, child)\n}\nfunction isAllStrings(arr: unknown[]): boolean {\n\treturn Array.isArray(arr) && arr.every((item) => typeof item === \"string\")\n}\nexport async function loadCharacterFromOnchain(): Promise<Character[]> {\n\tconst jsonText = onchainJson\n\n\tconsole.log(\"JSON:\", jsonText)\n\tif (!jsonText) return []\n\tconst loadedCharacters = []\n\ttry {\n\t\tconst character = JSON.parse(jsonText)\n\t\tvalidateCharacterConfig(character)\n\n\t\t// .id isn't really valid\n\t\tconst characterId = character.id || character.name\n\t\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\n\t\tconst characterSettings = Object.entries(process.env)\n\t\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t\t.reduce((settings, [key, value]) => {\n\t\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\t\tsettings[settingKey] = value\n\t\t\t\treturn settings\n\t\t\t}, {})\n\n\t\tif (Object.keys(characterSettings).length > 0) {\n\t\t\tcharacter.settings = character.settings || {}\n\t\t\tcharacter.settings.secrets = {\n\t\t\t\t...characterSettings,\n\t\t\t\t...character.settings.secrets,\n\t\t\t}\n\t\t}\n\n\t\t// Handle plugins\n\t\tif (isAllStrings(character.plugins)) {\n\t\t\telizaLogger.info(\"Plugins are: \", character.plugins)\n\t\t\tconst importedPlugins = await Promise.all(\n\t\t\t\tcharacter.plugins.map(async (plugin) => {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\treturn importedPlugin.default\n\t\t\t\t})\n\t\t\t)\n\t\t\tcharacter.plugins = importedPlugins\n\t\t}\n\n\t\tloadedCharacters.push(character)\n\t\telizaLogger.info(`Successfully loaded character from: ${process.env.IQ_WALLET_ADDRESS}`)\n\t\treturn loadedCharacters\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${process.env.IQ_WALLET_ADDRESS}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function loadCharactersFromUrl(url: string): Promise<Character[]> {\n\ttry {\n\t\tconst response = await fetch(url)\n\t\tconst responseJson = await response.json()\n\n\t\tlet characters: Character[] = []\n\t\tif (Array.isArray(responseJson)) {\n\t\t\tcharacters = await Promise.all(responseJson.map((character) => jsonToCharacter(url, character)))\n\t\t} else {\n\t\t\tconst character = await jsonToCharacter(url, responseJson)\n\t\t\tcharacters.push(character)\n\t\t}\n\t\treturn characters\n\t} catch (e) {\n\t\telizaLogger.error(`Error loading character(s) from ${url}: ${e}`)\n\t\tprocess.exit(1)\n\t}\n}\n\nasync function jsonToCharacter(filePath: string, character: any): Promise<Character> {\n\tvalidateCharacterConfig(character)\n\n\t// .id isn't really valid\n\tconst characterId = character.id || character.name\n\tconst characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, \"_\")}.`\n\tconst characterSettings = Object.entries(process.env)\n\t\t.filter(([key]) => key.startsWith(characterPrefix))\n\t\t.reduce((settings, [key, value]) => {\n\t\t\tconst settingKey = key.slice(characterPrefix.length)\n\t\t\treturn { ...settings, [settingKey]: value }\n\t\t}, {})\n\tif (Object.keys(characterSettings).length > 0) {\n\t\tcharacter.settings = character.settings || {}\n\t\tcharacter.settings.secrets = {\n\t\t\t...characterSettings,\n\t\t\t...character.settings.secrets,\n\t\t}\n\t}\n\t// Handle plugins\n\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\tif (character.extends) {\n\t\telizaLogger.info(`Merging ${character.name} character with parent characters`)\n\t\tfor (const extendPath of character.extends) {\n\t\t\tconst baseCharacter = await loadCharacter(path.resolve(path.dirname(filePath), extendPath))\n\t\t\tcharacter = mergeCharacters(baseCharacter, character)\n\t\t\telizaLogger.info(`Merged ${character.name} with ${baseCharacter.name}`)\n\t\t}\n\t}\n\treturn character\n}\n\nasync function loadCharacter(filePath: string): Promise<Character> {\n\tconst content = tryLoadFile(filePath)\n\tif (!content) {\n\t\tthrow new Error(`Character file not found: ${filePath}`)\n\t}\n\tconst character = JSON.parse(content)\n\treturn jsonToCharacter(filePath, character)\n}\n\nasync function loadCharacterTryPath(characterPath: string): Promise<Character> {\n\tlet content: string | null = null\n\tlet resolvedPath = \"\"\n\n\t// Try different path resolutions in order\n\tconst pathsToTry = [\n\t\tcharacterPath, // exact path as specified\n\t\tpath.resolve(process.cwd(), characterPath), // relative to cwd\n\t\tpath.resolve(process.cwd(), \"agent\", characterPath), // Add this\n\t\tpath.resolve(__dirname, characterPath), // relative to current script\n\t\tpath.resolve(__dirname, \"characters\", path.basename(characterPath)), // relative to agent/characters\n\t\tpath.resolve(__dirname, \"../characters\", path.basename(characterPath)), // relative to characters dir from agent\n\t\tpath.resolve(__dirname, \"../../characters\", path.basename(characterPath)), // relative to project root characters dir\n\t]\n\n\telizaLogger.info(\n\t\t\"Trying paths:\",\n\t\tpathsToTry.map((p) => ({\n\t\t\tpath: p,\n\t\t\texists: fs.existsSync(p),\n\t\t}))\n\t)\n\n\tfor (const tryPath of pathsToTry) {\n\t\tcontent = tryLoadFile(tryPath)\n\t\tif (content !== null) {\n\t\t\tresolvedPath = tryPath\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif (content === null) {\n\t\telizaLogger.error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t\telizaLogger.error(\"Tried the following paths:\")\n\t\tpathsToTry.forEach((p) => elizaLogger.error(` - ${p}`))\n\t\tthrow new Error(`Error loading character from ${characterPath}: File not found in any of the expected locations`)\n\t}\n\ttry {\n\t\tconst character: Character = await loadCharacter(resolvedPath)\n\t\telizaLogger.info(`Successfully loaded character from: ${resolvedPath}`)\n\t\treturn character\n\t} catch (e) {\n\t\telizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t\tthrow new Error(`Error parsing character from ${resolvedPath}: ${e}`)\n\t}\n}\n\nfunction commaSeparatedStringToArray(commaSeparated: string): string[] {\n\treturn commaSeparated?.split(\",\").map((value) => value.trim())\n}\n\nasync function readCharactersFromStorage(characterPaths: string[]): Promise<string[]> {\n\ttry {\n\t\tconst uploadDir = path.join(process.cwd(), \"data\", \"characters\")\n\t\tawait fs.promises.mkdir(uploadDir, { recursive: true })\n\t\tconst fileNames = await fs.promises.readdir(uploadDir)\n\t\tfileNames.forEach((fileName) => {\n\t\t\tcharacterPaths.push(path.join(uploadDir, fileName))\n\t\t})\n\t} catch (err) {\n\t\telizaLogger.error(`Error reading directory: ${err.message}`)\n\t}\n\n\treturn characterPaths\n}\n\nexport async function loadCharacters(charactersArg: string): Promise<Character[]> {\n\tlet characterPaths = commaSeparatedStringToArray(charactersArg)\n\n\tif (process.env.USE_CHARACTER_STORAGE === \"true\") {\n\t\tcharacterPaths = await readCharactersFromStorage(characterPaths)\n\t}\n\n\tconst loadedCharacters: Character[] = []\n\n\tif (characterPaths?.length > 0) {\n\t\tfor (const characterPath of characterPaths) {\n\t\t\ttry {\n\t\t\t\tconst character: Character = await loadCharacterTryPath(characterPath)\n\t\t\t\tloadedCharacters.push(character)\n\t\t\t} catch (e) {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasValidRemoteUrls()) {\n\t\telizaLogger.info(\"Loading characters from remote URLs\")\n\t\tconst characterUrls = commaSeparatedStringToArray(process.env.REMOTE_CHARACTER_URLS)\n\t\tfor (const characterUrl of characterUrls) {\n\t\t\tconst characters = await loadCharactersFromUrl(characterUrl)\n\t\t\tloadedCharacters.push(...characters)\n\t\t}\n\t}\n\n\tif (loadedCharacters.length === 0) {\n\t\telizaLogger.info(\"No characters found, using default character\")\n\t\tloadedCharacters.push(defaultCharacter)\n\t}\n\n\treturn loadedCharacters\n}\n\nasync function handlePluginImporting(plugins: string[]) {\n\tif (plugins.length > 0) {\n\t\telizaLogger.info(\"Plugins are: \", plugins)\n\t\tconst importedPlugins = await Promise.all(\n\t\t\tplugins.map(async (plugin) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst importedPlugin = await import(plugin)\n\t\t\t\t\tconst functionName = plugin.replace(\"@elizaos/plugin-\", \"\").replace(/-./g, (x) => x[1].toUpperCase()) + \"Plugin\" // Assumes plugin function is camelCased with Plugin suffix\n\t\t\t\t\treturn importedPlugin.default || importedPlugin[functionName]\n\t\t\t\t} catch (importError) {\n\t\t\t\t\telizaLogger.error(`Failed to import plugin: ${plugin}`, importError)\n\t\t\t\t\treturn [] // Return null for failed imports\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\treturn importedPlugins\n\t} else {\n\t\treturn []\n\t}\n}\n\nexport function getTokenForProvider(provider: ModelProviderName, character: Character): string | undefined {\n\tswitch (provider) {\n\t\t// no key needed for llama_local or gaianet\n\t\tcase ModelProviderName.LLAMALOCAL:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OLLAMA:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.GAIANET:\n\t\t\treturn \"\";\n\t\tcase ModelProviderName.BEDROCK:\n\t\t\treturn \"\"\n\t\tcase ModelProviderName.OPENAI:\n\t\t\treturn character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.ETERNALAI:\n\t\t\treturn character.settings?.secrets?.ETERNALAI_API_KEY || settings.ETERNALAI_API_KEY\n\t\tcase ModelProviderName.NINETEEN_AI:\n\t\t\treturn character.settings?.secrets?.NINETEEN_AI_API_KEY || settings.NINETEEN_AI_API_KEY\n\t\tcase ModelProviderName.LLAMACLOUD:\n\t\tcase ModelProviderName.TOGETHER:\n\t\t\treturn character.settings?.secrets?.LLAMACLOUD_API_KEY || settings.LLAMACLOUD_API_KEY || character.settings?.secrets?.TOGETHER_API_KEY || settings.TOGETHER_API_KEY || character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY\n\t\tcase ModelProviderName.CLAUDE_VERTEX:\n\t\tcase ModelProviderName.ANTHROPIC:\n\t\t\treturn character.settings?.secrets?.ANTHROPIC_API_KEY || character.settings?.secrets?.CLAUDE_API_KEY || settings.ANTHROPIC_API_KEY || settings.CLAUDE_API_KEY\n\t\tcase ModelProviderName.REDPILL:\n\t\t\treturn character.settings?.secrets?.REDPILL_API_KEY || settings.REDPILL_API_KEY\n\t\tcase ModelProviderName.OPENROUTER:\n\t\t\treturn character.settings?.secrets?.OPENROUTER_API_KEY || settings.OPENROUTER_API_KEY\n\t\tcase ModelProviderName.GROK:\n\t\t\treturn character.settings?.secrets?.GROK_API_KEY || settings.GROK_API_KEY\n\t\tcase ModelProviderName.HEURIST:\n\t\t\treturn character.settings?.secrets?.HEURIST_API_KEY || settings.HEURIST_API_KEY\n\t\tcase ModelProviderName.GROQ:\n\t\t\treturn character.settings?.secrets?.GROQ_API_KEY || settings.GROQ_API_KEY\n\t\tcase ModelProviderName.GALADRIEL:\n\t\t\treturn character.settings?.secrets?.GALADRIEL_API_KEY || settings.GALADRIEL_API_KEY\n\t\tcase ModelProviderName.FAL:\n\t\t\treturn character.settings?.secrets?.FAL_API_KEY || settings.FAL_API_KEY\n\t\tcase ModelProviderName.ALI_BAILIAN:\n\t\t\treturn character.settings?.secrets?.ALI_BAILIAN_API_KEY || settings.ALI_BAILIAN_API_KEY\n\t\tcase ModelProviderName.VOLENGINE:\n\t\t\treturn character.settings?.secrets?.VOLENGINE_API_KEY || settings.VOLENGINE_API_KEY\n\t\tcase ModelProviderName.NANOGPT:\n\t\t\treturn character.settings?.secrets?.NANOGPT_API_KEY || settings.NANOGPT_API_KEY\n\t\tcase ModelProviderName.HYPERBOLIC:\n\t\t\treturn character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY\n\n\t\tcase ModelProviderName.VENICE:\n\t\t\treturn character.settings?.secrets?.VENICE_API_KEY || settings.VENICE_API_KEY\n\t\tcase ModelProviderName.ATOMA:\n\t\t\treturn character.settings?.secrets?.ATOMASDK_BEARER_AUTH || settings.ATOMASDK_BEARER_AUTH\n\t\tcase ModelProviderName.NVIDIA:\n\t\t\treturn character.settings?.secrets?.NVIDIA_API_KEY || settings.NVIDIA_API_KEY\n\t\tcase ModelProviderName.AKASH_CHAT_API:\n\t\t\treturn character.settings?.secrets?.AKASH_CHAT_API_KEY || settings.AKASH_CHAT_API_KEY\n\t\tcase ModelProviderName.GOOGLE:\n\t\t\treturn character.settings?.secrets?.GOOGLE_GENERATIVE_AI_API_KEY || settings.GOOGLE_GENERATIVE_AI_API_KEY\n\t\tcase ModelProviderName.MISTRAL:\n\t\t\treturn character.settings?.secrets?.MISTRAL_API_KEY || settings.MISTRAL_API_KEY\n\t\tcase ModelProviderName.LETZAI:\n\t\t\treturn character.settings?.secrets?.LETZAI_API_KEY || settings.LETZAI_API_KEY\n\t\tcase ModelProviderName.INFERA:\n\t\t\treturn character.settings?.secrets?.INFERA_API_KEY || settings.INFERA_API_KEY\n\t\tcase ModelProviderName.DEEPSEEK:\n\t\t\treturn character.settings?.secrets?.DEEPSEEK_API_KEY || settings.DEEPSEEK_API_KEY\n\t\tcase ModelProviderName.LIVEPEER:\n\t\t\treturn character.settings?.secrets?.LIVEPEER_GATEWAY_URL || settings.LIVEPEER_GATEWAY_URL\n\t\tdefault:\n\t\t\tconst errorMessage = `Failed to get token - unsupported model provider: ${provider}`\n\t\t\telizaLogger.error(errorMessage)\n\t\t\tthrow new Error(errorMessage)\n\t}\n}\n\nfunction initializeDatabase(dataDir: string) {\n\tif (process.env.MONGODB_CONNECTION_STRING) {\n\t\telizaLogger.log(\"Initializing database on MongoDB Atlas\");\n\t\tconst client = new MongoClient(process.env.MONGODB_CONNECTION_STRING, {\n\t\t\tmaxPoolSize: 100,\n\t\t\tminPoolSize: 5,\n\t\t\tmaxIdleTimeMS: 60000,\n\t\t\tconnectTimeoutMS: 10000,\n\t\t\tserverSelectionTimeoutMS: 5000,\n\t\t\tsocketTimeoutMS: 45000,\n\t\t\tcompressors: ['zlib'],\n\t\t\tretryWrites: true,\n\t\t\tretryReads: true\n\t\t});\n\n\t\tconst dbName = process.env.MONGODB_DATABASE || 'elizaAgent';\n\t\tconst db = new MongoDBDatabaseAdapter(client, dbName);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\n\t\t\t\t\t\"Successfully connected to MongoDB Atlas\"\n\t\t\t\t);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to MongoDB Atlas:\", error);\n\t\t\t\tthrow error; // Re-throw to handle it in the calling code\n\t\t\t});\n\n\t\treturn db;\n\t} else if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) {\n\t\telizaLogger.info(\"Initializing Supabase connection...\");\n\t\tconst db = new SupabaseDatabaseAdapter(\n\t\t\tprocess.env.SUPABASE_URL,\n\t\t\tprocess.env.SUPABASE_ANON_KEY,\n\t\t);\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to Supabase database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to Supabase:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.POSTGRES_URL) {\n\t\telizaLogger.info(\"Initializing PostgreSQL connection...\")\n\t\tconst db = new PostgresDatabaseAdapter({\n\t\t\tconnectionString: process.env.POSTGRES_URL,\n\t\t\tparseInputs: true,\n\t\t})\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to PostgreSQL database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to PostgreSQL:\", error)\n\t\t\t})\n\n\t\treturn db\n\t} else if (process.env.PGLITE_DATA_DIR) {\n\t\telizaLogger.info(\"Initializing PgLite adapter...\")\n\t\t// `dataDir: memory://` for in memory pg\n\t\tconst db = new PGLiteDatabaseAdapter({\n\t\t\tdataDir: process.env.PGLITE_DATA_DIR,\n\t\t})\n\t\treturn db\n\t} else if (\n\t\tprocess.env.QDRANT_URL && process.env.QDRANT_KEY && process.env.QDRANT_PORT && process.env.QDRANT_VECTOR_SIZE) {\n\t\telizaLogger.info(\"Initializing Qdrant adapter...\")\n\t\tconst db = new QdrantDatabaseAdapter(process.env.QDRANT_URL, process.env.QDRANT_KEY, Number(process.env.QDRANT_PORT), Number(process.env.QDRANT_VECTOR_SIZE),)\n\t\treturn db\n\t} else {\n\t\tconst filePath = process.env.SQLITE_FILE ?? path.resolve(dataDir, \"db.sqlite\")\n\t\telizaLogger.info(`Initializing SQLite database at ${filePath}...`)\n\t\tconst db = new SqliteDatabaseAdapter(new Database(filePath))\n\n\t\t// Test the connection\n\t\tdb.init()\n\t\t\t.then(() => {\n\t\t\t\telizaLogger.success(\"Successfully connected to SQLite database\")\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\telizaLogger.error(\"Failed to connect to SQLite:\", error)\n\t\t\t})\n\n\t\treturn db\n\t}\n}\n\n// also adds plugins from character file into the runtime\nexport async function initializeClients(character: Character, runtime: IAgentRuntime) {\n\t// each client can only register once\n\t// and if we want two we can explicitly support it\n\tconst clients: Record<string, any> = {}\n\tconst clientTypes: string[] = character.clients?.map((str) => str.toLowerCase()) || []\n\telizaLogger.log(\"initializeClients\", clientTypes, \"for\", character.name)\n\n\n\t// Start Auto Client if \"auto\" detected as a configured client\n\tif (clientTypes.includes(Clients.AUTO)) {\n\t\tconst autoClient = await AutoClientInterface.start(runtime)\n\t\tif (autoClient) clients.auto = autoClient\n\t}\n\n\tif (clientTypes.includes(Clients.XMTP)) {\n const xmtpClient = await XmtpClientInterface.start(runtime);\n if (xmtpClient) clients.xmtp = xmtpClient;\n }\n\n\tif (clientTypes.includes(Clients.DISCORD)) {\n\t\tconst discordClient = await DiscordClientInterface.start(runtime)\n\t\tif (discordClient) clients.discord = discordClient\n\t}\n\n\tif (clientTypes.includes(Clients.TELEGRAM)) {\n\t\tconst telegramClient = await TelegramClientInterface.start(runtime)\n\t\tif (telegramClient) clients.telegram = telegramClient\n\t}\n\n\tif (clientTypes.includes(Clients.TWITTER)) {\n\t\tconst twitterClient = await TwitterClientInterface.start(runtime)\n\t\tif (twitterClient) {\n\t\t\tclients.twitter = twitterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.ALEXA)) {\n\t\tconst alexaClient = await AlexaClientInterface.start(runtime);\n\t\tif (alexaClient) {\n\t\t\tclients.alexa = alexaClient;\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.INSTAGRAM)) {\n\t\tconst instagramClient = await InstagramClientInterface.start(runtime)\n\t\tif (instagramClient) {\n\t\t\tclients.instagram = instagramClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(Clients.FARCASTER)) {\n\t\tconst farcasterClient = await FarcasterClientInterface.start(runtime)\n\t\tif (farcasterClient) {\n\t\t\tclients.farcaster = farcasterClient\n\t\t}\n\t}\n\n\tif (clientTypes.includes(\"lens\")) {\n\t\tconst lensClient = new LensAgentClient(runtime)\n\t\tlensClient.start()\n\t\tclients.lens = lensClient\n\t}\n\n\tif (clientTypes.includes(Clients.SIMSAI)) {\n\t\tconst simsaiClient = await JeeterClientInterface.start(runtime)\n\t\tif (simsaiClient) clients.simsai = simsaiClient\n\t}\n\n\telizaLogger.log(\"client keys\", Object.keys(clients))\n\n\t// TODO: Add Slack client to the list\n\t// Initialize clients as an object\n\n\tif (clientTypes.includes(\"slack\")) {\n\t\tconst slackClient = await SlackClientInterface.start(runtime)\n\t\tif (slackClient) clients.slack = slackClient // Use object property instead of push\n\t}\n\n\tfunction determineClientType(client: Client): string {\n\t\t// Check if client has a direct type identifier\n\t\tif (\"type\" in client) {\n\t\t\treturn (client as any).type\n\t\t}\n\n\t\t// Check constructor name\n\t\tconst constructorName = client.constructor?.name\n\t\tif (constructorName && !constructorName.includes(\"Object\")) {\n\t\t\treturn constructorName.toLowerCase().replace(\"client\", \"\")\n\t\t}\n\n\t\t// Fallback: Generate a unique identifier\n\t\treturn `client_${Date.now()}`\n\t}\n\n\tif (character.plugins?.length > 0) {\n\t\tfor (const plugin of character.plugins) {\n\t\t\tif (plugin.clients) {\n\t\t\t\tfor (const client of plugin.clients) {\n\t\t\t\t\tconst startedClient = await client.start(runtime)\n\t\t\t\t\tconst clientType = determineClientType(client)\n\t\t\t\t\telizaLogger.debug(`Initializing client of type: ${clientType}`)\n\t\t\t\t\tclients[clientType] = startedClient\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn clients\n}\n\nfunction getSecret(character: Character, secret: string) {\n\treturn character.settings?.secrets?.[secret] || process.env[secret]\n}\n\nlet nodePlugin: any | undefined\n\nexport async function createAgent(character: Character, db: IDatabaseAdapter, cache: ICacheManager, token: string): Promise<AgentRuntime> {\n\telizaLogger.log(`Creating runtime for character ${character.name}`)\n\n\tnodePlugin ??= createNodePlugin()\n\n\tconst teeMode = getSecret(character, \"TEE_MODE\") || \"OFF\"\n\tconst walletSecretSalt = getSecret(character, \"WALLET_SECRET_SALT\")\n\n\t// Validate TEE configuration\n\tif (teeMode !== TEEMode.OFF && !walletSecretSalt) {\n\t\telizaLogger.error(\"A WALLET_SECRET_SALT required when TEE_MODE is enabled\")\n\t\tthrow new Error(\"Invalid TEE configuration\")\n\t}\n\n\tlet goatPlugin: any | undefined\n\n\tif (getSecret(character, \"EVM_PRIVATE_KEY\")) {\n\t\tgoatPlugin = await createGoatPlugin((secret) => getSecret(character, secret))\n\t}\n\n let zilliqaPlugin: any | undefined;\n if (getSecret(character, \"ZILLIQA_PRIVATE_KEY\")) {\n zilliqaPlugin = await createZilliqaPlugin((secret) =>\n getSecret(character, secret)\n );\n }\n\n\t// Initialize Reclaim adapter if environment variables are present\n\t// let verifiableInferenceAdapter;\n\t// if (\n\t// process.env.RECLAIM_APP_ID &&\n\t// process.env.RECLAIM_APP_SECRET &&\n\t// process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\"\n\t// ) {\n\t// verifiableInferenceAdapter = new ReclaimAdapter({\n\t// appId: process.env.RECLAIM_APP_ID,\n\t// appSecret: process.env.RECLAIM_APP_SECRET,\n\t// modelProvider: character.modelProvider,\n\t// token,\n\t// });\n\t// elizaLogger.log(\"Verifiable inference adapter initialized\");\n\t// }\n\t// Initialize Opacity adapter if environment variables are present\n\tlet verifiableInferenceAdapter\n\tif (process.env.OPACITY_TEAM_ID && process.env.OPACITY_CLOUDFLARE_NAME && process.env.OPACITY_PROVER_URL && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new OpacityAdapter({\n\t\t\tteamId: process.env.OPACITY_TEAM_ID,\n\t\t\tteamName: process.env.OPACITY_CLOUDFLARE_NAME,\n\t\t\topacityProverUrl: process.env.OPACITY_PROVER_URL,\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken: token,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference adapter initialized\")\n\t\telizaLogger.log(\"teamId\", process.env.OPACITY_TEAM_ID)\n\t\telizaLogger.log(\"teamName\", process.env.OPACITY_CLOUDFLARE_NAME)\n\t\telizaLogger.log(\"opacityProverUrl\", process.env.OPACITY_PROVER_URL)\n\t\telizaLogger.log(\"modelProvider\", character.modelProvider)\n\t\telizaLogger.log(\"token\", token)\n\t}\n\tif (process.env.PRIMUS_APP_ID && process.env.PRIMUS_APP_SECRET && process.env.VERIFIABLE_INFERENCE_ENABLED === \"true\") {\n\t\tverifiableInferenceAdapter = new PrimusAdapter({\n\t\t\tappId: process.env.PRIMUS_APP_ID,\n\t\t\tappSecret: process.env.PRIMUS_APP_SECRET,\n\t\t\tattMode: \"proxytls\",\n\t\t\tmodelProvider: character.modelProvider,\n\t\t\ttoken,\n\t\t})\n\t\telizaLogger.log(\"Verifiable inference primus adapter initialized\")\n\t}\n\n\treturn new AgentRuntime({\n\t\tdatabaseAdapter: db,\n\t\ttoken,\n\t\tmodelProvider: character.modelProvider,\n\t\tevaluators: [],\n\t\tcharacter,\n\t\t// character.plugins are handled when clients are added\n\t\tplugins: [\n\t\t\tparseBooleanFromText(getSecret(character, \"BITMIND\")) && getSecret(character, \"BITMIND_API_TOKEN\") ? bittensorPlugin : null,\n\t\t\tparseBooleanFromText(getSecret(character, \"EMAIL_AUTOMATION_ENABLED\")) ? emailAutomationPlugin : null,\n\t\t\tgetSecret(character, \"IQ_WALLET_ADDRESS\") && getSecret(character, \"IQSOlRPC\") ? elizaCodeinPlugin : null,\n\t\t\tbootstrapPlugin,\n\t\t\tgetSecret(character, \"CDP_API_KEY_NAME\") && getSecret(character, \"CDP_API_KEY_PRIVATE_KEY\") && getSecret(character, \"CDP_AGENT_KIT_NETWORK\") ? agentKitPlugin : null,\n\t\t\tgetSecret(character, \"DEXSCREENER_API_KEY\") ? dexScreenerPlugin : null,\n\t\t\tgetSecret(character, \"FOOTBALL_API_KEY\") ? footballPlugin : null,\n\t\t\tgetSecret(character, \"CONFLUX_CORE_PRIVATE_KEY\") ? confluxPlugin : null,\n\t\t\tnodePlugin,\n\t\t\tgetSecret(character, \"ROUTER_NITRO_EVM_PRIVATE_KEY\") && getSecret(character, \"ROUTER_NITRO_EVM_ADDRESS\") ? nitroPlugin : null,\n\t\t\tgetSecret(character, \"TAVILY_API_KEY\") ? webSearchPlugin : null,\n\t\t\tgetSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? [solanaPlugin, solanaPluginV2] : null,\n\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") ? solanaAgentkitPlugin : null,\n\t\t\tgetSecret(character, \"AUTONOME_JWT_TOKEN\") ? autonomePlugin : null,\n\t\t\t(getSecret(character, \"NEAR_ADDRESS\") || getSecret(character, \"NEAR_WALLET_PUBLIC_KEY\")) && getSecret(character, \"NEAR_WALLET_SECRET_KEY\") ? nearPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\")) ? evmPlugin : null,\n\t\t\t(getSecret(character, \"EVM_PUBLIC_KEY\") || getSecret(character, \"INJECTIVE_PUBLIC_KEY\")) && getSecret(character, \"INJECTIVE_PRIVATE_KEY\") ? injectivePlugin : null,\n\t\t\tgetSecret(character, \"COSMOS_RECOVERY_PHRASE\") && getSecret(character, \"COSMOS_AVAILABLE_CHAINS\") && createCosmosPlugin(),\n\t\t\t(getSecret(character, \"SOLANA_PUBLIC_KEY\") || (getSecret(character, \"WALLET_PUBLIC_KEY\") && !getSecret(character, \"WALLET_PUBLIC_KEY\")?.startsWith(\"0x\"))) &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PUBLIC_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_PRIVATE_KEY\") &&\n\t\t\t\tgetSecret(character, \"SOLANA_ADMIN_PRIVATE_KEY\")\n\t\t\t\t? nftGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"ZEROG_PRIVATE_KEY\") ? zgPlugin : null,\n\t\t\tgetSecret(character, \"COINMARKETCAP_API_KEY\") ? coinmarketcapPlugin : null,\n\t\t\tgetSecret(character, \"ZERION_API_KEY\") ? zerionPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_COMMERCE_KEY\") ? coinbaseCommercePlugin : null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"OPENAI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"VENICE_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NVIDIA_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"NINETEEN_AI_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"HEURIST_API_KEY\") ||\n\t\t\t\tgetSecret(character, \"LIVEPEER_GATEWAY_URL\")\n\t\t\t\t? imageGenerationPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FAL_API_KEY\") ? ThreeDGenerationPlugin : null,\n\t\t\t...(getSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") ? [coinbaseMassPaymentsPlugin, tradePlugin, tokenContractPlugin, advancedTradePlugin] : []),\n\t\t\t...(teeMode !== TEEMode.OFF && walletSecretSalt ? [teePlugin] : []),\n\t\t\tteeMode !== TEEMode.OFF && walletSecretSalt && getSecret(character, \"VLOG\") ? verifiableLogPlugin : null,\n\t\t\tgetSecret(character, \"SGX\") ? sgxPlugin : null,\n\t\t\tgetSecret(character, \"ENABLE_TEE_LOG\") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, \"SGX\")) ? teeLogPlugin : null,\n\t\t\tgetSecret(character, \"OMNIFLIX_API_URL\") && getSecret(character, \"OMNIFLIX_MNEMONIC\") ? OmniflixPlugin : null,\n\t\t\tgetSecret(character, \"COINBASE_API_KEY\") && getSecret(character, \"COINBASE_PRIVATE_KEY\") && getSecret(character, \"COINBASE_NOTIFICATION_URI\") ? webhookPlugin : null,\n \t\t goatPlugin,\n zilliqaPlugin,\n\t\t\tgetSecret(character, \"COINGECKO_API_KEY\") || getSecret(character, \"COINGECKO_PRO_API_KEY\") ? coingeckoPlugin : null,\n\t\t\tgetSecret(character, \"MORALIS_API_KEY\") ? moralisPlugin : null,\n\t\t\tgetSecret(character, \"EVM_PROVIDER_URL\") ? goatPlugin : null,\n\t\t\tgetSecret(character, \"ABSTRACT_PRIVATE_KEY\") ? abstractPlugin : null,\n\t\t\tgetSecret(character, \"B2_PRIVATE_KEY\") ? b2Plugin : null,\n\t\t\tgetSecret(character, \"BINANCE_API_KEY\") && getSecret(character, \"BINANCE_SECRET_KEY\") ? binancePlugin : null,\n\t\t\tgetSecret(character, \"FLOW_ADDRESS\") && getSecret(character, \"FLOW_PRIVATE_KEY\") ? flowPlugin : null,\n\t\t\tgetSecret(character, \"LENS_ADDRESS\") && getSecret(character, \"LENS_PRIVATE_KEY\") ? lensPlugin : null,\n\t\t\tgetSecret(character, \"APTOS_PRIVATE_KEY\") ? aptosPlugin : null,\n\t\t\tgetSecret(character, \"MIND_COLD_WALLET_ADDRESS\") ? mindNetworkPlugin : null,\n\t\t\tgetSecret(character, \"MVX_PRIVATE_KEY\") ? multiversxPlugin : null,\n\t\t\tgetSecret(character, \"ZKSYNC_PRIVATE_KEY\") ? zksyncEraPlugin : null,\n\t\t\tgetSecret(character, \"CRONOSZKEVM_PRIVATE_KEY\") ? cronosZkEVMPlugin : null,\n\t\t\tgetSecret(character, \"TEE_MARLIN\") ? teeMarlinPlugin : null,\n\t\t\tgetSecret(character, \"TON_PRIVATE_KEY\") ? tonPlugin : null,\n\t\t\tgetSecret(character, \"THIRDWEB_SECRET_KEY\") ? thirdwebPlugin : null,\n\t\t\tgetSecret(character, \"SUI_PRIVATE_KEY\") ? suiPlugin : null,\n\t\t\tgetSecret(character, \"STORY_PRIVATE_KEY\") ? storyPlugin : null,\n\t\t\tgetSecret(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\")\n\t\t\t\t? squidRouterPlugin\n\t\t\t\t: null,\n\t\t\tgetSecret(character, \"FUEL_PRIVATE_KEY\") ? fuelPlugin : null,\n\t\t\tgetSecret(character, \"AVALANCHE_PRIVATE_KEY\") ? avalanchePlugin : null,\n\t\t\tgetSecret(character, \"BIRDEYE_API_KEY\") ? birdeyePlugin : null,\n\t\t\tgetSecret(character, \"ECHOCHAMBERS_API_URL\") && getSecret(character, \"ECHOCHAMBERS_API_KEY\") ? echoChambersPlugin : null,\n\t\t\tgetSecret(character, \"LETZAI_API_KEY\") ? letzAIPlugin : null,\n\t\t\tgetSecret(character, \"STARGAZE_ENDPOINT\") ? stargazePlugin : null,\n\t\t\tgetSecret(character, \"GIPHY_API_KEY\") ? giphyPlugin : null,\n\t\t\tgetSecret(character, \"PASSPORT_API_KEY\") ? gitcoinPassportPlugin : null,\n\t\t\tgetSecret(character, \"GENLAYER_PRIVATE_KEY\") ? genLayerPlugin : null,\n\t\t\tgetSecret(character, \"AVAIL_SEED\") && getSecret(character, \"AVAIL_APP_ID\") ? availPlugin : null,\n\t\t\tgetSecret(character, \"OPEN_WEATHER_API_KEY\") ? openWeatherPlugin : null,\n\t\t\tgetSecret(character, \"OBSIDIAN_API_TOKEN\") ? obsidianPlugin : null,\n\t\t\tgetSecret(character, \"ARTHERA_PRIVATE_KEY\")?.startsWith(\"0x\") ? artheraPlugin : null,\n\t\t\tgetSecret(character, \"ALLORA_API_KEY\") ? alloraPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_PRIVATE_KEY\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"HYPERLIQUID_TESTNET\") ? hyperliquidPlugin : null,\n\t\t\tgetSecret(character, \"AKASH_MNEMONIC\") && getSecret(character, \"AKASH_WALLET_ADDRESS\") ? akashPlugin : null,\n\t\t\tgetSecret(character, \"CHAINBASE_API_KEY\") ? chainbasePlugin : null,\n\t\t\tgetSecret(character, \"QUAI_PRIVATE_KEY\") ? quaiPlugin : null,\n\t\t\tgetSecret(character, \"RESERVOIR_API_KEY\") ? createNFTCollectionsPlugin() : null,\n\t\t\tgetSecret(character, \"ZERO_EX_API_KEY\") ? zxPlugin : null,\n\t\t\tgetSecret(character, \"DKG_PRIVATE_KEY\") ? dkgPlugin : null,\n\t\t\tgetSecret(character, \"PYTH_TESTNET_PROGRAM_KEY\") || getSecret(character, \"PYTH_MAINNET_PROGRAM_KEY\") ? pythDataPlugin : null,\n\t\t\tgetSecret(character, \"LND_TLS_CERT\") && getSecret(character, \"LND_MACAROON\") && getSecret(character, \"LND_SOCKET\") ? lightningPlugin : null,\n\t\t\tgetSecret(character, \"OPENAI_API_KEY\") && parseBooleanFromText(getSecret(character, \"ENABLE_OPEN_AI_COMMUNITY_PLUGIN\")) ? openaiPlugin : null,\n\t\t\tgetSecret(character, \"DEVIN_API_TOKEN\") ? devinPlugin : null,\n\t\t\tgetSecret(character, \"INITIA_PRIVATE_KEY\") ? initiaPlugin : null,\n\t\t\tgetSecret(character, \"HOLDSTATION_PRIVATE_KEY\") ? holdstationPlugin : null,\n\t\t\tgetSecret(character, \"NVIDIA_NIM_API_KEY\") || getSecret(character, \"NVIDIA_NGC_API_KEY\") ? nvidiaNimPlugin : null,\n\t\t\tgetSecret(character, \"BNB_PRIVATE_KEY\") || getSecret(character, \"BNB_PUBLIC_KEY\")?.startsWith(\"0x\") ? bnbPlugin : null,\n\t\t\t(getSecret(character, \"EMAIL_INCOMING_USER\") && getSecret(character, \"EMAIL_INCOMING_PASS\")) || (getSecret(character, \"EMAIL_OUTGOING_USER\") && getSecret(character, \"EMAIL_OUTGOING_PASS\")) ? emailPlugin : null,\n\t\t\tgetSecret(character, \"SEI_PRIVATE_KEY\") ? seiPlugin : null,\n\t\t\tgetSecret(character, \"HYPERBOLIC_API_KEY\") ? hyperbolicPlugin : null,\n\t\t\tgetSecret(character, \"SUNO_API_KEY\") ? sunoPlugin : null,\n\t\t\tgetSecret(character, \"UDIO_AUTH_TOKEN\") ? udioPlugin : null,\n\t\t\tgetSecret(character, \"IMGFLIP_USERNAME\") && getSecret(character, \"IMGFLIP_PASSWORD\") ? imgflipPlugin : null,\n\t\t\tgetSecret(character, \"FUNDING_PRIVATE_KEY\") && getSecret(character, \"EVM_RPC_URL\") ? litPlugin : null,\n\t\t\tgetSecret(character, \"ETHSTORAGE_PRIVATE_KEY\") ? ethstoragePlugin : null,\n\t\t\tgetSecret(character, \"MINA_PRIVATE_KEY\") ? minaPlugin : null,\n\t\t\tgetSecret(character, \"FORM_PRIVATE_KEY\") ? formPlugin : null,\n\t\t\tgetSecret(character, \"ANKR_WALLET\") ? ankrPlugin : null,\n\t\t\tgetSecret(character, \"DCAP_EVM_PRIVATE_KEY\") && getSecret(character, \"DCAP_MODE\") ? dcapPlugin : null,\n\t\t\tgetSecret(character, \"QUICKINTEL_API_KEY\") ? quickIntelPlugin : null,\n\t\t\tgetSecret(character, \"GELATO_RELAY_API_KEY\") ? gelatoPlugin : null,\n\t\t\tgetSecret(character, \"TRIKON_WALLET_ADDRESS\") ? trikonPlugin : null,\n\t\t].flat().filter(Boolean),\n\t\tproviders: [],\n\t\tmanagers: [],\n\t\tcacheManager: cache,\n\t\tfetch: logFetch,\n\t\tverifiableInferenceAdapter,\n\t})\n}\n\nfunction initializeFsCache(baseDir: string, character: Character) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cacheDir = path.resolve(baseDir, character.id, \"cache\")\n\n\tconst cache = new CacheManager(new FsCacheAdapter(cacheDir))\n\treturn cache\n}\n\nfunction initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {\n\tif (!character?.id) {\n\t\tthrow new Error(\"initializeFsCache requires id to be set in character definition\")\n\t}\n\tconst cache = new CacheManager(new DbCacheAdapter(db, character.id))\n\treturn cache\n}\n\nfunction initializeCache(cacheStore: string, character: Character, baseDir?: string, db?: IDatabaseCacheAdapter) {\n\tswitch (cacheStore) {\n\t\tcase CacheStore.REDIS:\n\t\t\tif (process.env.REDIS_URL) {\n\t\t\t\telizaLogger.info(\"Connecting to Redis...\")\n\t\t\t\tconst redisClient = new RedisClient(process.env.REDIS_URL)\n\t\t\t\tif (!character?.id) {\n\t\t\t\t\tthrow new Error(\"CacheStore.REDIS requires id to be set in character definition\")\n\t\t\t\t}\n\t\t\t\treturn new CacheManager(\n\t\t\t\t\tnew DbCacheAdapter(redisClient, character.id) // Using DbCacheAdapter since RedisClient also implements IDatabaseCacheAdapter\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"REDIS_URL environment variable is not set.\")\n\t\t\t}\n\n\t\tcase CacheStore.DATABASE:\n\t\t\tif (db) {\n\t\t\t\telizaLogger.info(\"Using Database Cache...\")\n\t\t\t\treturn initializeDbCache(character, db)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Database adapter is not provided for CacheStore.Database.\")\n\t\t\t}\n\n\t\tcase CacheStore.FILESYSTEM:\n\t\t\telizaLogger.info(\"Using File System Cache...\")\n\t\t\tif (!baseDir) {\n\t\t\t\tthrow new Error(\"baseDir must be provided for CacheStore.FILESYSTEM.\")\n\t\t\t}\n\t\t\treturn initializeFsCache(baseDir, character)\n\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid cache store: ${cacheStore} or required configuration missing.`)\n\t}\n}\n\nasync function startAgent(character: Character, directClient: DirectClient): Promise<AgentRuntime> {\n\tlet db: IDatabaseAdapter & IDatabaseCacheAdapter\n\ttry {\n\t\tcharacter.id ??= stringToUuid(character.name)\n\t\tcharacter.username ??= character.name\n\n\t\tconst token = getTokenForProvider(character.modelProvider, character)\n\t\tconst dataDir = path.join(__dirname, \"../data\")\n\n\t\tif (!fs.existsSync(dataDir)) {\n\t\t\tfs.mkdirSync(dataDir, { recursive: true })\n\t\t}\n\n\t\tdb = initializeDatabase(dataDir) as IDatabaseAdapter & IDatabaseCacheAdapter\n\n\t\tawait db.init()\n\n\t\tconst cache = initializeCache(process.env.CACHE_STORE ?? CacheStore.DATABASE, character, \"\", db) // \"\" should be replaced with dir for file system caching. THOUGHTS: might probably make this into an env\n\t\tconst runtime: AgentRuntime = await createAgent(character, db, cache, token)\n\n\t\t// start services/plugins/process knowledge\n\t\tawait runtime.initialize()\n\n\t\t// start assigned clients\n\t\truntime.clients = await initializeClients(character, runtime)\n\n\t\t// add to container\n\t\tdirectClient.registerAgent(runtime)\n\n\t\t// report to console\n\t\telizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`)\n\n\t\treturn runtime\n\t} catch (error) {\n\t\telizaLogger.error(`Error starting agent for character ${character.name}:`, error)\n\t\telizaLogger.error(error)\n\t\tif (db) {\n\t\t\tawait db.close()\n\t\t}\n\t\tthrow error\n\t}\n}\n\nconst checkPortAvailable = (port: number): Promise<boolean> => {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\n\t\tserver.once(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\tresolve(false)\n\t\t\t}\n\t\t})\n\n\t\tserver.once(\"listening\", () => {\n\t\t\tserver.close()\n\t\t\tresolve(true)\n\t\t})\n\n\t\tserver.listen(port)\n\t})\n}\n\nconst hasValidRemoteUrls = () => process.env.REMOTE_CHARACTER_URLS && process.env.REMOTE_CHARACTER_URLS !== \"\" && process.env.REMOTE_CHARACTER_URLS.startsWith(\"http\")\n\nconst startAgents = async () => {\n\tconst directClient = new DirectClient()\n\tlet serverPort = Number.parseInt(settings.SERVER_PORT || \"3000\")\n\tconst args = parseArguments()\n\tconst charactersArg = args.characters || args.character\n\tlet characters = [defaultCharacter]\n\n\tif (process.env.IQ_WALLET_ADDRESS && process.env.IQSOlRPC) {\n\t\tcharacters = await loadCharacterFromOnchain()\n\t}\n\n\tconst notOnchainJson = !onchainJson || onchainJson == \"null\"\n\n\tif ((notOnchainJson && charactersArg) || hasValidRemoteUrls()) {\n\t\tcharacters = await loadCharacters(charactersArg)\n\t}\n\n\t// Normalize characters for injectable plugins\n\tcharacters = await Promise.all(characters.map(normalizeCharacter))\n\n\ttry {\n\t\tfor (const character of characters) {\n\t\t\tawait startAgent(character, directClient)\n\t\t}\n\t} catch (error) {\n\t\telizaLogger.error(\"Error starting agents:\", error)\n\t}\n\n\t// Find available port\n\twhile (!(await checkPortAvailable(serverPort))) {\n\t\telizaLogger.warn(`Port ${serverPort} is in use, trying ${serverPort + 1}`)\n\t\tserverPort++\n\t}\n\n\t// upload some agent functionality into directClient\n\tdirectClient.startAgent = async (character) => {\n\t\t// Handle plugins\n\t\tcharacter.plugins = await handlePluginImporting(character.plugins)\n\n\t\t// wrap it so we don't have to inject directClient later\n\t\treturn startAgent(character, directClient)\n\t}\n\n\tdirectClient.loadCharacterTryPath = loadCharacterTryPath\n\tdirectClient.jsonToCharacter = jsonToCharacter\n\n\tdirectClient.start(serverPort)\n\n\tif (serverPort !== Number.parseInt(settings.SERVER_PORT || \"3000\")) {\n\t\telizaLogger.log(`Server started on alternate port ${serverPort}`)\n\t}\n\n\telizaLogger.log(\"Run `pnpm start:client` to start the client and visit the outputted URL (http://localhost:5173) to chat with your agents. When running multiple agents, use client with different port `SERVER_PORT=3001 pnpm start:client`\")\n}\n\nstartAgents().catch((error) => {\n\telizaLogger.error(\"Unhandled error in startAgents:\", error)\n\tprocess.exit(1)\n})\n\n// Prevent unhandled exceptions from crashing the process if desired\nif (\n\tprocess.env.PREVENT_UNHANDLED_EXIT &&\n\tparseBooleanFromText(process.env.PREVENT_UNHANDLED_EXIT)\n) {\n\t// Handle uncaught exceptions to prevent the process from crashing\n\tprocess.on(\"uncaughtException\", function (err) {\n\t\tconsole.error(\"uncaughtException\", err);\n\t});\n\n\t// Handle unhandled rejections to prevent the process from crashing\n\tprocess.on(\"unhandledRejection\", function (err) {\n\t\tconsole.error(\"unhandledRejection\", err);\n\t});\n}\n"}}}}