@@ -151,13 +151,14 @@ def stop(self):
151
151
self .stop_requested = True
152
152
153
153
class ChatThread (threading .Thread ):
154
- def __init__ (self , parent , matches , prompt , question ):
154
+ def __init__ (self , parent , matches , prompt , question , chat_history = None ):
155
155
super ().__init__ ()
156
156
self .parent = parent
157
157
self .matches = matches
158
158
self .prompt = prompt
159
159
self .question = question
160
160
self .provider = parent .provider_combo .currentText ()
161
+ self .chat_history = chat_history or []
161
162
162
163
def run (self ):
163
164
try :
@@ -181,16 +182,35 @@ def run(self):
181
182
4. Clear, factual analysis based only on the provided code
182
183
183
184
When referring to matches, ALWAYS use the file path and line number (e.g., 'In file.cpp:123') rather than match numbers.
184
- Keep your responses concise and to the point."""
185
+ Keep your responses concise and to the point.
185
186
186
- messages = [
187
- {"role" : "user" , "content" : f"These are code search results for: '{ self .prompt } '\n \n { combined_contexts } " }
188
- ]
187
+ IMPORTANT: Always directly address the user's questions. If they ask a specific question about the code or results,
188
+ make sure to answer that question directly rather than continuing your previous analysis."""
189
189
190
- if self .question :
191
- messages .append ({"role" : "user" , "content" : self .question })
190
+ # Prepare messages
191
+ if not self .chat_history :
192
+ # First message in the conversation
193
+ messages = [
194
+ {"role" : "user" , "content" : f"These are code search results for: '{ self .prompt } '\n \n { combined_contexts } " }
195
+ ]
196
+
197
+ if self .question :
198
+ messages .append ({"role" : "user" , "content" : self .question })
199
+ else :
200
+ messages .append ({"role" : "user" , "content" : "Please analyze these findings." })
192
201
else :
193
- messages .append ({"role" : "user" , "content" : "Please analyze these findings." })
202
+ # We have existing chat history
203
+ # First message always contains the search context
204
+ messages = [
205
+ {"role" : "user" , "content" : f"These are code search results for: '{ self .prompt } '\n \n { combined_contexts } " }
206
+ ]
207
+ # Add a separator message
208
+ messages .append ({"role" : "assistant" , "content" : "I'll analyze these code search results. What would you like to know?" })
209
+ # Add the conversation history (limited to last 10 exchanges to prevent context overflow)
210
+ messages .extend (self .chat_history [- 10 :])
211
+ # Add the new question
212
+ if self .question :
213
+ messages .append ({"role" : "user" , "content" : self .question })
194
214
195
215
if self .provider == "anthropic" :
196
216
response = client .messages .create (
@@ -210,7 +230,19 @@ def run(self):
210
230
)
211
231
response_text = response .choices [0 ].message .content
212
232
213
- self .parent .signal_chat_response .emit (response_text )
233
+ # Save question and response to history
234
+ if self .question :
235
+ new_history = self .chat_history + [
236
+ {"role" : "user" , "content" : self .question },
237
+ {"role" : "assistant" , "content" : response_text }
238
+ ]
239
+ else :
240
+ new_history = self .chat_history + [
241
+ {"role" : "assistant" , "content" : response_text }
242
+ ]
243
+
244
+ # Use tuple to send both response and history
245
+ self .parent .signal_chat_response .emit ((response_text , new_history ))
214
246
215
247
except Exception as e :
216
248
self .parent .signal_error .emit (str (e ))
@@ -1099,13 +1131,14 @@ class AISearchGUI(QMainWindow):
1099
1131
signal_update_terms = Signal (str )
1100
1132
signal_search_complete = Signal (int )
1101
1133
signal_error = Signal (str )
1102
- signal_chat_response = Signal (str )
1134
+ signal_chat_response = Signal (object ) # Changed to object to support tuple
1103
1135
1104
1136
def __init__ (self ):
1105
1137
super ().__init__ ()
1106
1138
self .matches = []
1107
1139
self .search_thread = None
1108
1140
self .chat_thread = None
1141
+ self .chat_history = [] # Add chat history
1109
1142
self .settings = QSettings ("AICodeSearch" , "AISearchGUI" )
1110
1143
self .results_buffer = ResultsBuffer ()
1111
1144
self .update_timer = QTimer (self )
@@ -1917,6 +1950,7 @@ def clear_results(self):
1917
1950
self .chat_input .clear ()
1918
1951
self .file_list .clear ()
1919
1952
self .matches = []
1953
+ self .chat_history = [] # Clear chat history
1920
1954
self .chat_button .setEnabled (False )
1921
1955
self .chat_action .setEnabled (False )
1922
1956
self .refine_button .setEnabled (False )
@@ -1939,16 +1973,37 @@ def start_chat(self):
1939
1973
# Switch to chat tab
1940
1974
self .tabs .setCurrentIndex (1 )
1941
1975
1942
- # Start chat thread
1943
- self .chat_thread = ChatThread (self , self .matches , prompt , question )
1976
+ # Start chat thread with history
1977
+ self .chat_thread = ChatThread (self , self .matches , prompt , question , self . chat_history )
1944
1978
self .chat_thread .start ()
1945
1979
1946
- @Slot (str )
1947
- def update_chat (self , response ):
1980
+ @Slot (object )
1981
+ def update_chat (self , response_data ):
1948
1982
"""Update chat output with AI response"""
1983
+ # Unpack response and history
1984
+ if isinstance (response_data , tuple ):
1985
+ response , self .chat_history = response_data
1986
+ else :
1987
+ # For backward compatibility
1988
+ response = response_data
1989
+
1949
1990
# Store original markdown for copy functionality
1950
1991
self .chat_output .markdown_content = response
1951
1992
1993
+ # Clear previous content and show only the latest exchange
1994
+ self .chat_output .clear ()
1995
+
1996
+ # Add user question to the display if it exists
1997
+ if self .chat_input .toPlainText ().strip ():
1998
+ # Format with user question and AI response
1999
+ content = f"**You:** { self .chat_input .toPlainText ().strip ()} \n \n **AI:**\n \n { response } "
2000
+ self .chat_output .setMarkdown (content )
2001
+ # Clear input after sending
2002
+ self .chat_input .clear ()
2003
+ else :
2004
+ # Initial analysis (no user question)
2005
+ self .chat_output .setMarkdown (response )
2006
+
1952
2007
# Convert markdown to HTML
1953
2008
try :
1954
2009
# Set up extensions based on available libraries
@@ -1972,7 +2027,7 @@ def update_chat(self, response):
1972
2027
self .chat_output .document ().setDefaultStyleSheet (current_css + pygments_css )
1973
2028
1974
2029
html_content = markdown .markdown (
1975
- response ,
2030
+ self . chat_output . toMarkdown () ,
1976
2031
extensions = extensions ,
1977
2032
extension_configs = extension_configs
1978
2033
)
@@ -1986,15 +2041,11 @@ def update_chat(self, response):
1986
2041
1987
2042
# Set the HTML content
1988
2043
self .chat_output .setHtml (html_content )
1989
- except Exception as e :
1990
- # Fallback to plain text if markdown conversion fails
1991
- self .chat_output .setPlainText (response )
1992
- self .statusBar ().showMessage (f"Markdown rendering error: { str (e )} " )
1993
-
1994
- self .progress_bar .setVisible (False )
1995
- self .chat_button .setEnabled (True )
1996
- # Remove chat_action reference
1997
- self .statusBar ().showMessage ("Chat response received" )
2044
+
2045
+ # Hide progress and enable chat button
2046
+ finally :
2047
+ self .progress_bar .setVisible (False )
2048
+ self .chat_button .setEnabled (True )
1998
2049
1999
2050
def loadSettings (self ):
2000
2051
"""Load saved settings"""
0 commit comments