diff --git a/ai-hub/app/core/pipelines/question_decider.py b/ai-hub/app/core/pipelines/question_decider.py index f5db8e2..56b5d4b 100644 --- a/ai-hub/app/core/pipelines/question_decider.py +++ b/ai-hub/app/core/pipelines/question_decider.py @@ -32,7 +32,7 @@ * The `code_diff` field must be empty. * **Decision: 'code_change'** - * Choose this if the user's request involves modifying or adding to the code (e.g., "fix this bug," "implement this feature," "refactor this function"). + * Choose this if the user's request involves modifying or adding to the code (e.g., "fix this bug," "implement this feature," "refactor this function", "show me full code"). * You must have all the relevant files with content in `retrieved_paths_with_content` to propose the change. * The `answer` field can be an optional, high-level summary of the change. * The `code_diff` field must contain the full and complete git diff showing the exact modifications, could be multiple file diffs. diff --git a/ui/client-app/src/components/ChatArea.css b/ui/client-app/src/components/ChatArea.css new file mode 100644 index 0000000..4b4c6d6 --- /dev/null +++ b/ui/client-app/src/components/ChatArea.css @@ -0,0 +1,3 @@ +.chat-area-fixed-height { + height: calc(100vh - 72px); /* Subtract input + padding */ + } \ No newline at end of file diff --git a/ui/client-app/src/components/ChatArea.js b/ui/client-app/src/components/ChatArea.js index be3cf35..b897700 100644 --- a/ui/client-app/src/components/ChatArea.js +++ b/ui/client-app/src/components/ChatArea.js @@ -1,10 +1,11 @@ -// src/components/ChatArea.js import React, { useState, useRef, useEffect } from "react"; import ChatWindow from "./ChatWindow"; +import './ChatArea.css'; const ChatArea = ({ chatHistory, onSendMessage, isProcessing }) => { const [inputValue, setInputValue] = useState(""); const inputRef = useRef(null); + const chatScrollRef = useRef(null); const handleSendMessage = (e) => { e.preventDefault(); @@ -14,44 +15,47 @@ } }; + // Scroll chat to bottom on new message useEffect(() => { - if (inputRef.current) { - inputRef.current.focus(); + if (chatScrollRef.current) { + chatScrollRef.current.scrollTop = chatScrollRef.current.scrollHeight; } - }, [isProcessing]); + }, [chatHistory]); return ( -
- {/* Chat history display area */} -
+
+ {/* Scrollable ChatWindow */} +
- {/* Message input and send button area */} -
- setInputValue(e.target.value)} - disabled={isProcessing} - className="flex-grow p-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" - placeholder={isProcessing ? "AI is thinking..." : "Type a message..."} - /> - -
+ > + Send + + +
); }; -export default ChatArea; \ No newline at end of file +export default ChatArea; diff --git a/ui/client-app/src/components/ChatWindow.js b/ui/client-app/src/components/ChatWindow.js index f802ed9..ce79bc1 100644 --- a/ui/client-app/src/components/ChatWindow.js +++ b/ui/client-app/src/components/ChatWindow.js @@ -1,10 +1,10 @@ -import React, { useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import ReactMarkdown from 'react-markdown'; import './ChatWindow.css'; import FileListComponent from "./FileList"; import DiffViewer from "./DiffViewer"; -// Individual message component for better modularity +// Individual message component const ChatMessage = ({ message }) => { const [selectedFile, setSelectedFile] = useState(null); const [isReasoningExpanded, setIsReasoningExpanded] = useState(false); @@ -13,36 +13,31 @@ setIsReasoningExpanded(!isReasoningExpanded); }; - // A simple handler to close the diff viewer - const handleCloseDiff = () => { - setSelectedFile(null); - }; - - const handleFileClick = (file) => { - setSelectedFile(file); - }; + const handleCloseDiff = () => { + setSelectedFile(null); + }; - const messageClasses = `max-w-md p-4 rounded-lg shadow-md ${ - message.isUser - ? "bg-indigo-500 text-white ml-auto" - : "bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-gray-100 mr-auto" - }`; + const handleFileClick = (file) => { + setSelectedFile(file); + }; + + const assistantMessageClasses = `p-4 rounded-lg shadow-md w-full bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-gray-100`; + const userMessageClasses = `max-w-md p-4 rounded-lg shadow-md bg-indigo-500 text-white ml-auto`; return ( -
+
{message.reasoning && (
- -
{message.reasoning}
@@ -50,23 +45,33 @@ )} {message.text} {message.code_diff && ( - - )} + + )} {selectedFile && }
); }; -// Main ChatWindow component remains the same -const ChatWindow = ({ chatHistory }) => { +// Main ChatWindow component with dynamic height calculation +const ChatWindow = ({ chatHistory, maxHeight }) => { + const containerRef = useRef(null); + + useEffect(() => { + if (containerRef.current) { + containerRef.current.scrollTop = containerRef.current.scrollHeight; + } + }, [chatHistory]); + return ( -
+
{chatHistory.map((message, index) => (
@@ -75,4 +80,4 @@ ); }; -export default ChatWindow; \ No newline at end of file +export default ChatWindow; diff --git a/ui/client-app/src/components/InteractionLog.js b/ui/client-app/src/components/InteractionLog.js index 3d43c14..517c27e 100644 --- a/ui/client-app/src/components/InteractionLog.js +++ b/ui/client-app/src/components/InteractionLog.js @@ -1,34 +1,84 @@ -// src/components/InteractionLog.js -import React from "react"; +import React, { useState, useEffect, useRef } from "react"; const InteractionLog = ({ logs }) => { + const [expandedLogs, setExpandedLogs] = useState({}); + const [containerHeight, setContainerHeight] = useState("500px"); + + const scrollRef = useRef(null); + + // Auto-size based on window height + useEffect(() => { + const updateHeight = () => { + const windowHeight = window.innerHeight; + const offset = 300; // adjust this based on layout + setContainerHeight(`${windowHeight - offset}px`); + }; + + updateHeight(); + window.addEventListener("resize", updateHeight); + return () => window.removeEventListener("resize", updateHeight); + }, []); + + // Auto-scroll to bottom on new logs + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + } + }, [logs]); + + const toggleExpand = (index) => { + setExpandedLogs((prev) => ({ + ...prev, + [index]: !prev[index], + })); + }; + + const getPreviewText = (message, maxLength = 200) => { + if (message.length <= maxLength) return message; + return message.slice(0, maxLength) + "…"; + }; + return ( -
+
{logs.length > 0 ? ( - logs.map((log, index) => ( -
-

- {log.type.charAt(0).toUpperCase() + log.type.slice(1)}: -

-
-                {log.message}
-              
-
- )) + logs.map((log, index) => { + const isExpanded = expandedLogs[index]; + + return ( +
toggleExpand(index)} + > +

+ {log.type.charAt(0).toUpperCase() + log.type.slice(1)}: +

+
+                  {isExpanded ? log.message : getPreviewText(log.message)}
+                
+ {!isExpanded && log.message.length > 200 && ( +

+ Click to expand +

+ )} +
+ ); + }) ) : (

No interactions yet. @@ -39,4 +89,4 @@ ); }; -export default InteractionLog; \ No newline at end of file +export default InteractionLog; diff --git a/ui/client-app/src/hooks/useCodeAssistant.js b/ui/client-app/src/hooks/useCodeAssistant.js index 17c067c..63c98a4 100644 --- a/ui/client-app/src/hooks/useCodeAssistant.js +++ b/ui/client-app/src/hooks/useCodeAssistant.js @@ -179,7 +179,7 @@ if (readFiles.length > 0) { const displayMessage = readFiles.length > 10 ? `Read ${readFiles.length} files successfully.` - : `Read files and send successfully: [${readFiles.join(', ')}]`; + : `Read files and send successfully: [${readFiles.map(f => `"${f}"`).join(', ')}]`; newMessages.push({ type: "local", message: displayMessage }); } return [...prev, ...newMessages]; diff --git a/ui/client-app/src/pages/CodingAssistantPage.js b/ui/client-app/src/pages/CodingAssistantPage.js index 05532d5..1618a89 100644 --- a/ui/client-app/src/pages/CodingAssistantPage.js +++ b/ui/client-app/src/pages/CodingAssistantPage.js @@ -39,27 +39,32 @@ return (

{/* Main content area */} -
-
- {/* Left Column: Chat and Code Access */} -
+
+ {/* Adjusted grid for narrow right panel */} +
+ {/* Left Column: Chat Area */} +
{/* Area 1: Chat with LLM */}

Chat with the LLM

+ {/* Note: ChatArea component needs to be implemented with a