diff --git a/.env.example b/.env.example index 6af463fc..3b6fb3ba 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,7 @@ NEXT_PUBLIC_PRIVY_APP_ID= NEXT_PUBLIC_EAP_RECEIVE_WALLET_ADDRESS= NEXT_PUBLIC_HELIUS_RPC_URL= +NEXT_PUBLIC_DISABLED_TOOLS=[] #["getTokenOrders", "holders", "resolveWalletAddressFromDomain"] OPENAI_API_KEY= PRIVY_APP_SECRET= WALLET_ENCRYPTION_KEY= diff --git a/src/ai/generic/jina.tsx b/src/ai/generic/jina.tsx index 4e8d3400..29b3044e 100644 --- a/src/ai/generic/jina.tsx +++ b/src/ai/generic/jina.tsx @@ -65,6 +65,7 @@ export const jinaTools = { .describe('The URL of the web page to read and convert to text'), }), isCollapsible: true, + requiredEnvVars: ['JINA_API_KEY'], execute: async ({ url }: { url: string }) => { try { const response = await fetch(`https://r.jina.ai/${url}`, { diff --git a/src/ai/generic/telegram.tsx b/src/ai/generic/telegram.tsx index 57edc32a..c42fd961 100644 --- a/src/ai/generic/telegram.tsx +++ b/src/ai/generic/telegram.tsx @@ -103,6 +103,7 @@ export const telegramTools = { parameters: z.object({ username: z.string().optional(), }), + requiredEnvVars: ['TELEGRAM_BOT_USERNAME'], execute: async function ({ username }: { username?: string }) { try { const response = await verifyTelegramSetupAction({ @@ -150,6 +151,10 @@ export const telegramTools = { username: z.string().optional(), message: z.string(), }), + requiredEnvVars: [ + 'TELEGRAM_BOT_TOKEN', + 'TELEGRAM_BOT_USERNAME', + ], execute: async function ({ username, message, diff --git a/src/ai/providers.tsx b/src/ai/providers.tsx index 7c18fc3c..a3234c28 100644 --- a/src/ai/providers.tsx +++ b/src/ai/providers.tsx @@ -117,6 +117,7 @@ export interface ToolConfig { agentKit?: any; userId?: any; requiresConfirmation?: boolean; + requiredEnvVars?: string[]; } export function DefaultToolResultRenderer({ result }: { result: unknown }) { @@ -152,6 +153,30 @@ export const defaultTools: Record = { ...birdeyeTools, }; +export function filterTools( + tools: Record, +): Record { + const disabledTools = process.env.NEXT_PUBLIC_DISABLED_TOOLS + ? JSON.parse(process.env.NEXT_PUBLIC_DISABLED_TOOLS) + : []; + + return Object.fromEntries( + Object.entries(tools).filter(([toolName, toolConfig]) => { + if (disabledTools.includes(toolName)) { + return false; + } + if(toolConfig.requiredEnvVars){ + for (const envVar of toolConfig.requiredEnvVars) { + if(!process.env[envVar] || process.env[envVar] == ''){ + return false; + } + } + } + return true; + }), + ); +} + export const coreTools: Record = { ...actionTools, ...utilTools, @@ -234,8 +259,9 @@ export function getToolConfig(toolName: string): ToolConfig | undefined { export function getToolsFromRequiredTools( toolNames: string[], ): Record { + const enabledTools = filterTools(defaultTools); return toolNames.reduce((acc: Record, toolName) => { - const tool = defaultTools[toolName]; + const tool = enabledTools[toolName]; if (tool) { acc[toolName] = tool; } diff --git a/src/ai/solana/birdeye.tsx b/src/ai/solana/birdeye.tsx index e286bb85..8b90db54 100644 --- a/src/ai/solana/birdeye.tsx +++ b/src/ai/solana/birdeye.tsx @@ -18,6 +18,7 @@ export const birdeyeTools = { .nativeEnum(BirdeyeTimeframe) .describe('The timeframe to search for'), }), + requiredEnvVars: ['BIRDEYE_API_KEY'], execute: async ({ timeframe }: { timeframe: BirdeyeTimeframe }) => { try { const traders = await getTopTraders({ timeframe }); diff --git a/src/ai/solana/chart.tsx b/src/ai/solana/chart.tsx index 38923d9e..9dd42981 100644 --- a/src/ai/solana/chart.tsx +++ b/src/ai/solana/chart.tsx @@ -57,6 +57,7 @@ export const priceChartTool = { description: 'Retrieves and displays price history for a Solana token via CoinGecko market data, falling back to DEX if unavailable.', parameters: chartToolParameters, + requiredEnvVars: ['CG_API_KEY'], execute: async ({ contractAddress, timeFrame, @@ -104,6 +105,7 @@ export const dexChartTool = { isExpandedByDefault: true, description: 'Retrieves and displays price history data from the DEX.', parameters: chartToolParameters, + requiredEnvVars: ['CG_API_KEY'], execute: async ({ contractAddress, timeFrame,