diff --git a/examples/chat-ui/src/hooks/useStreamResponse.ts b/examples/chat-ui/src/hooks/useStreamResponse.ts index da194fd..eede3bd 100644 --- a/examples/chat-ui/src/hooks/useStreamResponse.ts +++ b/examples/chat-ui/src/hooks/useStreamResponse.ts @@ -1,11 +1,12 @@ -import { useState, useRef } from 'react' -import { streamText, tool, jsonSchema } from 'ai' +import { useRef, useState } from 'react' +import { jsonSchema, streamText, tool } from 'ai' import { createGroq } from '@ai-sdk/groq' import { createAnthropic } from '@ai-sdk/anthropic' -import { type Message, type Conversation } from '../types' +import { type Conversation, type Message } from '../types' import { type Model } from '../types/models' import { getApiKey } from '../utils/apiKeys' import { type Tool } from 'use-mcp/react' +import { debugLog } from '../utils/debugLog.ts' interface UseStreamResponseProps { conversationId?: number @@ -33,25 +34,25 @@ export const useStreamResponse = ({ const convertMcpToolsToAiTools = (mcpTools: Tool[]) => { const aiTools: Record = {} - console.log(`[useStreamResponse] Converting ${mcpTools.length} MCP tools to AI format`) + debugLog(`[useStreamResponse] Converting ${mcpTools.length} MCP tools to AI format`) mcpTools.forEach((mcpTool) => { const schema = mcpTool.inputSchema || { type: 'object', properties: {} } - console.log(`[useStreamResponse] Converting tool: ${mcpTool.name}`, { description: mcpTool.description, schema }) + debugLog(`[useStreamResponse] Converting tool: ${mcpTool.name}`, { description: mcpTool.description, schema }) aiTools[mcpTool.name] = tool({ description: mcpTool.description, parameters: jsonSchema(schema as any), execute: async (args: unknown, options?: any) => { - console.log(`[useStreamResponse] Tool "${mcpTool.name}" execute called with args:`, args) - console.log(`[useStreamResponse] Tool execute options:`, options) + debugLog(`[useStreamResponse] Tool "${mcpTool.name}" execute called with args:`, args) + debugLog(`[useStreamResponse] Tool execute options:`, options) try { // Call the MCP tool using the callTool method attached to the tool if ('callTool' in mcpTool && typeof mcpTool.callTool === 'function') { - console.log(`[useStreamResponse] Calling MCP tool "${mcpTool.name}"...`) + debugLog(`[useStreamResponse] Calling MCP tool "${mcpTool.name}"...`) const result = await mcpTool.callTool(args as Record) - console.log(`[useStreamResponse] Tool "${mcpTool.name}" returned result:`, result) + debugLog(`[useStreamResponse] Tool "${mcpTool.name}" returned result:`, result) return result } else { throw new Error(`Tool ${mcpTool.name} does not have a callable implementation`) @@ -64,7 +65,7 @@ export const useStreamResponse = ({ }) }) - console.log(`[useStreamResponse] Converted tools:`, Object.keys(aiTools)) + debugLog(`[useStreamResponse] Converted tools:`, Object.keys(aiTools)) return aiTools } @@ -90,10 +91,10 @@ export const useStreamResponse = ({ const streamResponse = async (messages: Message[]) => { let aiResponse = '' - console.log(`[useStreamResponse] streamResponse called with ${messages.length} messages`) - console.log(`[useStreamResponse] Messages:`, messages) - console.log(`[useStreamResponse] Current conversationId:`, conversationId) - console.log(`[useStreamResponse] MCP tools available:`, mcpTools.length) + debugLog(`[useStreamResponse] streamResponse called with ${messages.length} messages`) + debugLog(`[useStreamResponse] Messages:`, messages) + debugLog(`[useStreamResponse] Current conversationId:`, conversationId) + debugLog(`[useStreamResponse] MCP tools available:`, mcpTools.length) // Check if API key is available let apiKey = getApiKey(selectedModel.provider.id) @@ -111,27 +112,27 @@ export const useStreamResponse = ({ try { const modelInstance = getModelInstance(selectedModel, apiKey) - console.log(`[useStreamResponse] Adding empty assistant message to conversation ${conversationId}`) + debugLog(`[useStreamResponse] Adding empty assistant message to conversation ${conversationId}`) setConversations((prev) => { const updated = [...prev] const conv = updated.find((c) => c.id === conversationId) if (conv) { - console.log(`[useStreamResponse] Found conversation, adding assistant message. Current message count: ${conv.messages.length}`) + debugLog(`[useStreamResponse] Found conversation, adding assistant message. Current message count: ${conv.messages.length}`) conv.messages.push({ role: 'assistant', content: '' }) - console.log(`[useStreamResponse] After adding assistant message, message count: ${conv.messages.length}`) + debugLog(`[useStreamResponse] After adding assistant message, message count: ${conv.messages.length}`) } else { - console.warn(`[useStreamResponse] Could not find conversation with id: ${conversationId}`) + debugLog(`[useStreamResponse] Could not find conversation with id: ${conversationId}`) } return updated }) - console.log(`[useStreamResponse] Setting stream started to true`) + debugLog(`[useStreamResponse] Setting stream started to true`) setStreamStarted(true) // Convert MCP tools to AI package format const aiTools = convertMcpToolsToAiTools(mcpTools) - console.log(`[useStreamResponse] Starting streamText with ${Object.keys(aiTools).length} tools available`) - console.log(`[useStreamResponse] Messages:`, messages.map(m => ({ role: m.role, content: m.content.substring(0, 100) + '...' }))) + debugLog(`[useStreamResponse] Starting streamText with ${Object.keys(aiTools).length} tools available`) + debugLog(`[useStreamResponse] Messages:`, messages.map(m => ({ role: m.role, content: m.content.substring(0, 100) + '...' }))) const result = await streamText({ model: modelInstance, @@ -142,7 +143,7 @@ export const useStreamResponse = ({ tools: Object.keys(aiTools).length > 0 ? aiTools : undefined, maxSteps: 5, // Allow up to 5 steps for tool calling onStepFinish({ text, toolCalls, toolResults, finishReason, usage }) { - console.log(`[useStreamResponse] Step finished:`, { + debugLog(`[useStreamResponse] Step finished:`, { text: text ? text.substring(0, 100) + '...' : 'no text', toolCallsCount: toolCalls?.length || 0, toolResultsCount: toolResults?.length || 0, @@ -150,17 +151,17 @@ export const useStreamResponse = ({ usage }) if (toolCalls && toolCalls.length > 0) { - console.log(`[useStreamResponse] Tool calls in step:`, toolCalls) + debugLog(`[useStreamResponse] Tool calls in step:`, toolCalls) } if (toolResults && toolResults.length > 0) { - console.log(`[useStreamResponse] Tool results in step:`, toolResults) + debugLog(`[useStreamResponse] Tool results in step:`, toolResults) } }, abortSignal: controller.signal, }) - console.log(`[useStreamResponse] streamText result obtained, starting to process stream`) - console.log(`[useStreamResponse] Result object:`, { + debugLog(`[useStreamResponse] streamText result obtained, starting to process stream`) + debugLog(`[useStreamResponse] Result object:`, { hasTextStream: !!result.textStream, hasToolCalls: !!result.toolCalls, hasToolResults: !!result.toolResults, @@ -169,30 +170,30 @@ export const useStreamResponse = ({ // Log tool calls if they exist if (result.toolCalls) { - console.log(`[useStreamResponse] Tool calls detected:`, result.toolCalls) + debugLog(`[useStreamResponse] Tool calls detected:`, result.toolCalls) } // Log tool results if they exist if (result.toolResults) { - console.log(`[useStreamResponse] Tool results detected:`, result.toolResults) + debugLog(`[useStreamResponse] Tool results detected:`, result.toolResults) } let chunkCount = 0 for await (const chunk of result.textStream) { try { chunkCount++ - console.log(`[useStreamResponse] Processing chunk ${chunkCount}:`, JSON.stringify(chunk)) + debugLog(`[useStreamResponse] Processing chunk ${chunkCount}:`, JSON.stringify(chunk)) aiResponse += chunk aiResponseRef.current = aiResponse - console.log(`[useStreamResponse] Updated aiResponse (length: ${aiResponse.length}):`, aiResponse.substring(0, 200) + '...') + debugLog(`[useStreamResponse] Updated aiResponse (length: ${aiResponse.length}):`, aiResponse.substring(0, 200) + '...') //custom extraction of tag const titleMatch = aiResponse.match(/(.*?)<\/chat-title>/) if (titleMatch) { const title = titleMatch[1].trim() - console.log(`[useStreamResponse] Extracted title: ${title}`) + debugLog(`[useStreamResponse] Extracted title: ${title}`) setConversations((prev) => { const updated = [...prev] const conv = updated.find((c) => c.id === conversationId) @@ -208,10 +209,10 @@ export const useStreamResponse = ({ const updated = [...prev] const conv = updated.find((c) => c.id === conversationId) if (conv) { - console.log(`[useStreamResponse] Updating conversation message content (length: ${aiResponse.length})`) + debugLog(`[useStreamResponse] Updating conversation message content (length: ${aiResponse.length})`) conv.messages[conv.messages.length - 1].content = aiResponse } else { - console.warn(`[useStreamResponse] Could not find conversation with id: ${conversationId}`) + debugLog(`[useStreamResponse] Could not find conversation with id: ${conversationId}`) } return updated }) @@ -222,10 +223,10 @@ export const useStreamResponse = ({ } } - console.log(`[useStreamResponse] Finished processing ${chunkCount} chunks. Final response length: ${aiResponse.length}`) + debugLog(`[useStreamResponse] Finished processing ${chunkCount} chunks. Final response length: ${aiResponse.length}`) } catch (error: unknown) { if (controller.signal.aborted) { - console.log('[useStreamResponse] Stream aborted') + debugLog('[useStreamResponse] Stream aborted') } else { console.error('[useStreamResponse] Error generating response:', error) // Log additional error details @@ -238,14 +239,14 @@ export const useStreamResponse = ({ const updated = [...prev] const conv = updated.find((c) => c.id === conversationId) if (conv && conv.messages[conv.messages.length - 1].role === 'assistant') { - console.log('[useStreamResponse] Removing assistant message due to error') + debugLog('[useStreamResponse] Removing assistant message due to error') conv.messages.pop() } return updated }) } } finally { - console.log('[useStreamResponse] Cleaning up stream state') + debugLog('[useStreamResponse] Cleaning up stream state') setStreamStarted(false) setController(new AbortController()) } diff --git a/examples/chat-ui/src/utils/debugLog.ts b/examples/chat-ui/src/utils/debugLog.ts new file mode 100644 index 0000000..92cd37a --- /dev/null +++ b/examples/chat-ui/src/utils/debugLog.ts @@ -0,0 +1,6 @@ +// Debug logging helper +export const debugLog = (...args: any[]) => { + if (typeof window !== 'undefined' && localStorage.getItem('USE_MCP_DEBUG') === 'true') { + console.log(...args) + } +}