diff --git a/src/app/globals.css b/src/app/globals.css index f75daca..79cbba7 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -11,3 +11,17 @@ display: none; } } + +@layer utilities { + @keyframes high-bounce { + 0%, + 100% { + transform: translateY(0); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + 50% { + transform: translateY(-9px); + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } + } +} diff --git a/src/components/AgentActionDisplay.tsx b/src/components/AgentActionDisplay.tsx index 83bfba0..ccd0d6e 100644 --- a/src/components/AgentActionDisplay.tsx +++ b/src/components/AgentActionDisplay.tsx @@ -9,6 +9,9 @@ import { Search, Zap, Microscope, + Ban, + CircleCheck, + ListPlus, } from 'lucide-react'; import { AgentActionEvent } from './ChatWindow'; @@ -42,6 +45,22 @@ const AgentActionDisplay = ({ return ; case 'PROCEEDING_WITH_FULL_ANALYSIS': return ; + case 'SKIPPING_IRRELEVANT_SOURCE': + return ; + case 'CONTEXT_UPDATED': + return ( + + ); + case 'INFORMATION_GATHERING_COMPLETE': + return ( + + ); default: return ; } @@ -64,12 +83,12 @@ const AgentActionDisplay = ({ latestEvent.action === 'INFORMATION_GATHERING_COMPLETE' ? 'Agent Log' : formatActionName(latestEvent.action)} - {isLoading && + {/* {isLoading && latestEvent.action !== 'INFORMATION_GATHERING_COMPLETE' && ( - )} + )} */} {isExpanded ? ( @@ -103,7 +122,9 @@ const AgentActionDisplay = ({
{event.details.sourceUrl && (
- Source: + + Source: + {event.details.sourceUrl} @@ -113,14 +134,18 @@ const AgentActionDisplay = ({ )} {event.details.skipReason && (
- Reason: + + Reason: + {event.details.skipReason}
)} {event.details.searchQuery && event.details.searchQuery !== event.details.query && (
- Search Query: + + Search Query: + "{event.details.searchQuery}" @@ -128,37 +153,45 @@ const AgentActionDisplay = ({ )} {event.details.sourcesFound !== undefined && (
- Sources Found: + + Sources Found: + {event.details.sourcesFound}
)} {/* {(event.details.documentCount !== undefined && event.details.documentCount > 0) && (
- Documents: + Documents: {event.details.documentCount}
)} */} {event.details.contentLength !== undefined && (
- Content Length: - {event.details.contentLength} chars + + Content Length: + + {event.details.contentLength} characters
)} {event.details.searchInstructions !== undefined && (
- Search Instructions: + + Search Instructions: + {event.details.searchInstructions}
)} - {event.details.previewCount !== undefined && ( + {/* {event.details.previewCount !== undefined && (
- Preview Sources: + Preview Sources: {event.details.previewCount}
- )} + )} */} {event.details.processingType && (
- Processing Type: + + Processing Type: + {event.details.processingType.replace('-', ' ')} @@ -166,51 +199,41 @@ const AgentActionDisplay = ({ )} {event.details.insufficiencyReason && (
- Reason: + + Reason: + {event.details.insufficiencyReason}
)} {event.details.reason && (
- Reason: + + Reason: + {event.details.reason}
)} - {event.details.taskCount !== undefined && ( + {/* {event.details.taskCount !== undefined && (
- Tasks: + Tasks: {event.details.taskCount}
- )} + )} */} {event.details.currentTask && (
- Current Task: + + Current Task: + "{event.details.currentTask}"
)} - {event.details.taskIndex !== undefined && - event.details.totalTasks !== undefined && ( -
- Progress: - - Task {event.details.taskIndex} of{' '} - {event.details.totalTasks} - -
- )} - {event.details.completedTask && ( -
- Completed: - - "{event.details.completedTask}" - -
- )} {event.details.nextTask && (
- Next: + + Next: + "{event.details.nextTask}" @@ -218,7 +241,9 @@ const AgentActionDisplay = ({ )} {event.details.currentSearchFocus && (
- Search Focus: + + Search Focus: + "{event.details.currentSearchFocus}" diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx index c28686e..77b708c 100644 --- a/src/components/MessageBox.tsx +++ b/src/components/MessageBox.tsx @@ -93,7 +93,10 @@ const MessageBox = ({ ) : ( <>
-

+

{message.content}

) : ( -
-
-
-
+
+
+
+
+
+
)}
diff --git a/src/lib/agents/analyzerAgent.ts b/src/lib/agents/analyzerAgent.ts index e496130..bcbf84d 100644 --- a/src/lib/agents/analyzerAgent.ts +++ b/src/lib/agents/analyzerAgent.ts @@ -25,18 +25,32 @@ import next from 'next'; // Define Zod schemas for structured output const NextActionSchema = z.object({ - action: z.enum(['good_content', 'need_user_info', 'need_more_info']).describe('The next action to take based on content analysis'), - reasoning: z.string().describe('Brief explanation of why this action was chosen') + action: z + .enum(['good_content', 'need_user_info', 'need_more_info']) + .describe('The next action to take based on content analysis'), + reasoning: z + .string() + .describe('Brief explanation of why this action was chosen'), }); const UserInfoRequestSchema = z.object({ - question: z.string().describe('A detailed question to ask the user for additional information'), - reasoning: z.string().describe('Explanation of why this information is needed') + question: z + .string() + .describe('A detailed question to ask the user for additional information'), + reasoning: z + .string() + .describe('Explanation of why this information is needed'), }); const SearchRefinementSchema = z.object({ - question: z.string().describe('A refined search question to gather more specific information'), - reasoning: z.string().describe('Explanation of what information is missing and why this search will help') + question: z + .string() + .describe('A refined search question to gather more specific information'), + reasoning: z + .string() + .describe( + 'Explanation of what information is missing and why this search will help', + ), }); export class AnalyzerAgent { @@ -120,9 +134,7 @@ export class AnalyzerAgent { console.log('Next action response:', nextActionResponse); - if ( - nextActionResponse.action !== 'good_content' - ) { + if (nextActionResponse.action !== 'good_content') { // If we don't have enough information, but we still have available tasks, proceed with the next task if (state.tasks && state.tasks.length > 0) { @@ -135,13 +147,14 @@ export class AnalyzerAgent { } } - if ( - nextActionResponse.action === 'need_user_info' - ) { + if (nextActionResponse.action === 'need_user_info') { // Use structured output for user info request - const userInfoLlm = this.llm.withStructuredOutput(UserInfoRequestSchema, { - name: 'request_user_info', - }); + const userInfoLlm = this.llm.withStructuredOutput( + UserInfoRequestSchema, + { + name: 'request_user_info', + }, + ); const moreUserInfoPrompt = await ChatPromptTemplate.fromTemplate( additionalUserInputPrompt, @@ -193,9 +206,12 @@ export class AnalyzerAgent { // If we need more information from the LLM, generate a more specific search query // Use structured output for search refinement - const searchRefinementLlm = this.llm.withStructuredOutput(SearchRefinementSchema, { - name: 'refine_search', - }); + const searchRefinementLlm = this.llm.withStructuredOutput( + SearchRefinementSchema, + { + name: 'refine_search', + }, + ); const moreInfoPrompt = await ChatPromptTemplate.fromTemplate( additionalWebSearchPrompt, @@ -268,7 +284,7 @@ export class AnalyzerAgent { type: 'agent_action', data: { action: 'INFORMATION_GATHERING_COMPLETE', - message: 'Sufficient information gathered, ready to respond.', + message: 'Ready to respond.', details: { documentCount: state.relevantDocuments.length, searchIterations: state.searchInstructionHistory.length, diff --git a/src/lib/agents/taskManagerAgent.ts b/src/lib/agents/taskManagerAgent.ts index e7381d8..5dca421 100644 --- a/src/lib/agents/taskManagerAgent.ts +++ b/src/lib/agents/taskManagerAgent.ts @@ -10,8 +10,16 @@ import { setTemperature } from '../utils/modelUtils'; // Define Zod schema for structured task breakdown output const TaskBreakdownSchema = z.object({ - tasks: z.array(z.string()).describe('Array of specific, focused tasks broken down from the original query'), - reasoning: z.string().describe('Explanation of how and why the query was broken down into these tasks') + tasks: z + .array(z.string()) + .describe( + 'Array of specific, focused tasks broken down from the original query', + ), + reasoning: z + .string() + .describe( + 'Explanation of how and why the query was broken down into these tasks', + ), }); type TaskBreakdown = z.infer; @@ -136,7 +144,9 @@ export class TaskManagerAgent { console.log('Task breakdown response:', taskBreakdownResult); // Extract tasks from structured response - const taskLines = taskBreakdownResult.tasks.filter((task) => task.trim().length > 0); + const taskLines = taskBreakdownResult.tasks.filter( + (task) => task.trim().length > 0, + ); if (taskLines.length === 0) { // Fallback: if no tasks found, use the original query diff --git a/src/lib/agents/webSearchAgent.ts b/src/lib/agents/webSearchAgent.ts index de973b9..4508210 100644 --- a/src/lib/agents/webSearchAgent.ts +++ b/src/lib/agents/webSearchAgent.ts @@ -22,8 +22,14 @@ import computeSimilarity from '../utils/computeSimilarity'; // Define Zod schema for structured search query output const SearchQuerySchema = z.object({ - searchQuery: z.string().describe('The optimized search query to use for web search'), - reasoning: z.string().describe('Explanation of how the search query was optimized for better results') + searchQuery: z + .string() + .describe('The optimized search query to use for web search'), + reasoning: z + .string() + .describe( + 'Explanation of how the search query was optimized for better results', + ), }); type SearchQuery = z.infer; @@ -333,7 +339,7 @@ export class WebSearchAgent { type: 'agent_action', data: { action: 'ANALYZING_SOURCE', - message: `Analyzing content from: ${result.title || result.url}`, + message: `Analyzing and summarizing content from: ${result.title || result.url}`, details: { query: currentTask, sourceUrl: result.url, diff --git a/src/lib/utils/analyzePreviewContent.ts b/src/lib/utils/analyzePreviewContent.ts index c03cdca..be731e7 100644 --- a/src/lib/utils/analyzePreviewContent.ts +++ b/src/lib/utils/analyzePreviewContent.ts @@ -18,8 +18,17 @@ export type PreviewContent = { // Zod schema for structured preview analysis output const PreviewAnalysisSchema = z.object({ - isSufficient: z.boolean().describe('Whether the preview content is sufficient to answer the task query'), - reason: z.string().nullable().describe('Specific reason why full content analysis is required (only if isSufficient is false)') + isSufficient: z + .boolean() + .describe( + 'Whether the preview content is sufficient to answer the task query', + ), + reason: z + .string() + .nullable() + .describe( + 'Specific reason why full content analysis is required (only if isSufficient is false)', + ), }); export const analyzePreviewContent = async ( @@ -123,9 +132,11 @@ You must return a JSON object with: console.log( `Preview content determined to be insufficient. Reason: ${analysisResult.reason}`, ); - return { - isSufficient: false, - reason: analysisResult.reason || 'Preview content insufficient for complete answer' + return { + isSufficient: false, + reason: + analysisResult.reason || + 'Preview content insufficient for complete answer', }; } } catch (error) { diff --git a/src/lib/utils/summarizeWebContent.ts b/src/lib/utils/summarizeWebContent.ts index 008736e..e04677d 100644 --- a/src/lib/utils/summarizeWebContent.ts +++ b/src/lib/utils/summarizeWebContent.ts @@ -33,7 +33,7 @@ export const summarizeWebContent = async ( console.log( `Summarizing content from URL: ${url} using ${i === 0 ? 'html' : 'text'}`, ); - + const prompt = `${systemPrompt}You are a web content summarizer, tasked with creating a detailed, accurate summary of content from a webpage. # Instructions @@ -82,9 +82,9 @@ ${i === 0 ? content.metadata.html : content.pageContent}`; `LLM response for URL "${url}" indicates it's not relevant (empty or very short response)`, ); - return { - document: null, - notRelevantReason: 'Content not relevant to query' + return { + document: null, + notRelevantReason: 'Content not relevant to query', }; }