Moving most of the debug logging behind localStorage.USE_MCP_DEBUG
This commit is contained in:
parent
e94958865a
commit
d25f6c19a3
2 changed files with 44 additions and 37 deletions
|
|
@ -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<string, any> = {}
|
||||
|
||||
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<string, unknown>)
|
||||
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 <chat-title> tag
|
||||
const titleMatch = aiResponse.match(/<chat-title>(.*?)<\/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())
|
||||
}
|
||||
|
|
|
|||
6
examples/chat-ui/src/utils/debugLog.ts
Normal file
6
examples/chat-ui/src/utils/debugLog.ts
Normal file
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue