From c4559429a345efdf495fd03e654769b5a257451b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 5 Feb 2025 11:54:19 -0800 Subject: [PATCH] Fixed typo in tavily tool, acknowledge known error in deepseek-v3 function calling with infinite loops, consolidate providers in registry under providers directory, fixed error handing from 3P APIs --- app/api/proxy/route.ts | 13 ++---------- providers/registry.ts | 26 +++++++++++++++++++++++ providers/service.ts | 46 +++++++++++++++++++++-------------------- tools/tavily/extract.ts | 2 +- 4 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 providers/registry.ts diff --git a/app/api/proxy/route.ts b/app/api/proxy/route.ts index dd1aec4656..70558060c9 100644 --- a/app/api/proxy/route.ts +++ b/app/api/proxy/route.ts @@ -1,22 +1,13 @@ import { NextResponse } from 'next/server' -import { anthropicProvider } from '@/providers/anthropic' -import { googleProvider } from '@/providers/google' -import { openaiProvider } from '@/providers/openai' -import { ProviderConfig } from '@/providers/types' +import { getProvider } from '@/providers/registry' import { getTool } from '@/tools' -const providers: Record = { - 'anthropic/chat': anthropicProvider, - 'openai/chat': openaiProvider, - 'google/chat': googleProvider, -} - export async function POST(request: Request) { try { const { toolId, params } = await request.json() // Check if this is a provider chat request - const provider = providers[toolId] + const provider = getProvider(toolId) if (provider) { const { apiKey, ...restParams } = params if (!apiKey) { diff --git a/providers/registry.ts b/providers/registry.ts new file mode 100644 index 0000000000..053b094be6 --- /dev/null +++ b/providers/registry.ts @@ -0,0 +1,26 @@ +import { anthropicProvider } from './anthropic' +import { deepseekProvider } from './deepseek' +import { googleProvider } from './google' +import { openaiProvider } from './openai' +import { ProviderConfig } from './types' +import { xAIProvider } from './xai' + +export type ProviderId = 'openai' | 'anthropic' | 'google' | 'deepseek' | 'xai' + +export const providers: Record = { + openai: openaiProvider, + anthropic: anthropicProvider, + google: googleProvider, + deepseek: deepseekProvider, + xai: xAIProvider, +} + +export function getProvider(id: string): ProviderConfig | undefined { + // Handle both formats: 'openai' and 'openai/chat' + const providerId = id.split('/')[0] as ProviderId + return providers[providerId] +} + +export function getProviderChatId(providerId: ProviderId): string { + return `${providerId}/chat` +} diff --git a/providers/service.ts b/providers/service.ts index 007acfcb37..e75497e2dd 100644 --- a/providers/service.ts +++ b/providers/service.ts @@ -1,25 +1,12 @@ import { executeTool, getTool } from '@/tools' -import { anthropicProvider } from './anthropic' -import { deepseekProvider } from './deepseek' -import { googleProvider } from './google' -import { openaiProvider } from './openai' -import { ProviderConfig, ProviderRequest, ProviderResponse, TokenInfo } from './types' -import { xAIProvider } from './xai' - -// Register providers -const providers: Record = { - openai: openaiProvider, - anthropic: anthropicProvider, - google: googleProvider, - deepseek: deepseekProvider, - xai: xAIProvider, -} +import { getProvider } from './registry' +import { ProviderRequest, ProviderResponse, TokenInfo } from './types' export async function executeProviderRequest( providerId: string, request: ProviderRequest ): Promise { - const provider = providers[providerId] + const provider = getProvider(providerId) if (!provider) { throw new Error(`Provider not found: ${providerId}`) } @@ -65,15 +52,30 @@ export async function executeProviderRequest( const hasFunctionCall = provider.hasFunctionCall(currentResponse) console.log('Has function call:', hasFunctionCall) + // Break if we have content and no function call if (!hasFunctionCall) { console.log('No function call detected, breaking loop') break } - // Transform function call using provider-specific logic + // Safety check: if we have the same function call multiple times in a row + // with the same arguments, break to prevent infinite loops let functionCall try { functionCall = provider.transformFunctionCallResponse(currentResponse, request.tools) + + // Check if this is a duplicate call + const lastCall = toolCalls[toolCalls.length - 1] + if ( + lastCall && + lastCall.name === functionCall.name && + JSON.stringify(lastCall.arguments) === JSON.stringify(functionCall.arguments) + ) { + console.log( + 'Detected duplicate function call, breaking loop to prevent infinite recursion' + ) + break + } } catch (error) { console.log('Error transforming function call:', error) break @@ -167,12 +169,12 @@ async function makeProxyRequest(providerId: string, payload: any, apiKey: string }), }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.error || 'Provider API error') + const data = await response.json() + + if (!data.success) { + throw new Error(data.error || 'Provider API error') } - const { output } = await response.json() console.log('Proxy request completed') - return output + return data.output } diff --git a/tools/tavily/extract.ts b/tools/tavily/extract.ts index 60b96df92e..735c6264b9 100644 --- a/tools/tavily/extract.ts +++ b/tools/tavily/extract.ts @@ -23,7 +23,7 @@ export interface ExtractResponse extends ToolResponse { } export const extractTool: ToolConfig = { - id: 'tavily.extract', + id: 'tavily_extract', name: 'Tavily Extract', description: 'Extract web page content from URLs using Tavily Extract', version: '1.0.0',