import { MessageUI } from '@/lib/types/database' import { ToolResult } from '@/lib/services/tool-executor' export interface ContextInfo { filesFound: number fileNames: string[] } export interface StreamingActivity { planning: string currentExecution: { name: string description: string args?: any } | null toolResults: Array<{ name: string result: string success: boolean }> } /** * Generate a summary of tool operations for display */ export function generateToolSummary(results: ToolResult[]): string { let summary = "đŸ› ī¸ **File Operations Completed:**\n\n" results.forEach((result, i) => { if (result.name === 'search_files') { summary += `${i + 1}. 🔍 **Search Files**: Found ${(result as any).result?.length || 0} file(s)\n` } else if (result.name === 'read_file') { summary += `${i + 1}. 📖 **Read File**: ${(result as any).result?.name || 'file'}\n` } else if (result.name === 'update_file') { summary += `${i + 1}. âœī¸ **Updated File**: ${(result as any).result?.name || 'file'}\n 📝 ${(result as any).result?.change_summary || 'updated'}\n` } }) return summary } /** * Build comprehensive message content that includes all AI activity */ export function buildComprehensiveMessageContent( finalResponse: string, streamingActivity: StreamingActivity ): string { let comprehensiveContent = '' // Add planning phase if it occurred if (streamingActivity.planning) { comprehensiveContent += `📋 **AI Planning:** ${streamingActivity.planning}\n\n` } // Add tool execution results if any if (streamingActivity.toolResults.length > 0) { comprehensiveContent += `đŸ› ī¸ **Actions Performed:**\n` streamingActivity.toolResults.forEach((result, index) => { const status = result.success ? '✅' : '❌' comprehensiveContent += `${status} **${result.name}:** ${result.result}\n` }) comprehensiveContent += '\n' } // Add the main AI response if (finalResponse.trim()) { comprehensiveContent += finalResponse } return comprehensiveContent } /** * Build content for stopped/interrupted execution */ export function buildStoppedMessageContent( partialContent: string, streamingActivity: StreamingActivity ): string { let stoppedContent = '' // Add planning phase if it occurred if (streamingActivity.planning) { stoppedContent += `📋 **AI Planning:** ${streamingActivity.planning}\n\n` } // Add current tool execution if it was in progress if (streamingActivity.currentExecution) { stoppedContent += `âš™ī¸ **Was Executing:** ${streamingActivity.currentExecution.description} *(interrupted)*\n\n` } // Add completed tool execution results if any if (streamingActivity.toolResults.length > 0) { stoppedContent += `đŸ› ī¸ **Actions Performed Before Stop:**\n` streamingActivity.toolResults.forEach((result, index) => { const status = result.success ? '✅' : '❌' stoppedContent += `${status} **${result.name}:** ${result.result}\n` }) stoppedContent += '\n' } // Add the partial content if (partialContent) { stoppedContent += partialContent + '\n\n' } // Add stop indicator stoppedContent += 'âšī¸ *Execution stopped by user*' return stoppedContent } /** * Compose all display messages including streaming content */ export function composeDisplayMessages( messages: MessageUI[], isStreaming: boolean, streamingMessage: string, aiPlanning: string, currentToolExecution: { name: string description: string args?: any } | null, toolExecutionResults: Array<{ name: string result: string success: boolean }> ): (MessageUI & { _isStreaming?: boolean })[] { // Enhanced message composition that avoids duplicates const baseMessages = [...messages] // Only add streaming message if we have content and are actively streaming if (isStreaming && (streamingMessage || aiPlanning || currentToolExecution)) { // Create a comprehensive streaming message that includes all current AI activity let streamingContent = '' if (aiPlanning) { streamingContent += `📋 **Planning:** ${aiPlanning}\n\n` } if (currentToolExecution) { streamingContent += `âš™ī¸ **Executing:** ${currentToolExecution.description}\n\n` } // Add tool execution results if (toolExecutionResults.length > 0) { streamingContent += `📊 **Tool Results:**\n` toolExecutionResults.forEach((result, index) => { const status = result.success ? '✅' : '❌' streamingContent += `${status} ${result.name}: ${result.result}\n` }) streamingContent += '\n' } // Add the main content with proper separation if (streamingMessage) { // If we have tool activity and then content, add proper separation if ((aiPlanning || currentToolExecution || toolExecutionResults.length > 0) && !streamingMessage.startsWith('\n')) { streamingContent += '\n' } streamingContent += streamingMessage } // Only add streaming message if we have any content if (streamingContent.trim()) { baseMessages.push({ id: 'streaming-temp', // Use a consistent ID to prevent React key issues type: 'ai' as const, content: streamingContent, timestamp: new Date(), // Add temporary property for streaming identification _isStreaming: true } as MessageUI & { _isStreaming: boolean }) } } return baseMessages } /** * Check if tool results contain file-modifying operations */ export function hasFileModifyingOperations(toolResults: ToolResult[]): boolean { return toolResults.some((result: ToolResult) => ['update_file', 'create_file', 'delete_file', 'move_file'].includes(result.name) ) } /** * Create error message for display */ export function createErrorMessage(): MessageUI { return { id: Date.now() + 1, type: 'ai', content: 'Sorry, I encountered an error while processing your request. Please try again.', timestamp: new Date() } } // Shared utility for deleting messages export const deleteMessage = async (messageId: string): Promise => { // Get auth headers with session token const { data: { session } } = await import('@/lib/supabase').then(m => m.supabase.auth.getSession()) const headers: Record = { 'Content-Type': 'application/json' } if (session?.access_token) { headers['Authorization'] = `Bearer ${session.access_token}` } const response = await fetch(`/api/chat/messages/${messageId}`, { method: 'DELETE', headers, }) if (!response.ok) { const errorData = await response.json() throw new Error(errorData.error || 'Failed to delete message') } }