mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-07-10 01:39:13 +00:00
fix: improve thinking panel lifecycle and response rendering
This commit is contained in:
parent
6ae3fff7cf
commit
3a6e62c4f4
4 changed files with 56 additions and 29 deletions
|
|
@ -54,14 +54,13 @@ import ee.carlrobert.codegpt.toolwindow.chat.parser.Text;
|
|||
import ee.carlrobert.codegpt.toolwindow.chat.parser.Thinking;
|
||||
import ee.carlrobert.codegpt.toolwindow.ui.ResponseBodyProgressPanel;
|
||||
import ee.carlrobert.codegpt.toolwindow.ui.WebpageList;
|
||||
import ee.carlrobert.codegpt.ui.ThoughtProcessPanel;
|
||||
import ee.carlrobert.codegpt.ui.ThinkingPanel;
|
||||
import ee.carlrobert.codegpt.ui.UIUtil;
|
||||
import ee.carlrobert.codegpt.ui.hover.PsiLinkHoverPreview;
|
||||
import ee.carlrobert.codegpt.util.EditorUtil;
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JEditorPane;
|
||||
|
|
@ -87,6 +86,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 4, true, false));
|
||||
private final StringBuilder accumulatedThinking = new StringBuilder();
|
||||
|
||||
private ThinkingPanel currentThinkingPanel;
|
||||
private ResponseEditorPanel currentlyProcessedEditorPanel;
|
||||
private MermaidResponsePanel currentlyProcessedMermaidPanel;
|
||||
private JEditorPane currentlyProcessedTextPane;
|
||||
|
|
@ -142,10 +142,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
currentlyProcessedEditorPanel = null;
|
||||
currentlyProcessedMermaidPanel = null;
|
||||
}
|
||||
var thoughtProcessPanel = getExistingThoughtProcessPanel();
|
||||
if (thoughtProcessPanel != null && !thoughtProcessPanel.isFinished()) {
|
||||
thoughtProcessPanel.setFinished();
|
||||
}
|
||||
finishThinkingSection(false);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Something went wrong while processing input", e);
|
||||
}
|
||||
|
|
@ -153,6 +150,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
}
|
||||
|
||||
public void addToolStatusPanel(JComponent component) {
|
||||
finishThinkingSection(false);
|
||||
finishCurrentStreamingSection();
|
||||
streamOutputParser.startNewVisualSection();
|
||||
contentPanel.add(component);
|
||||
|
|
@ -259,10 +257,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
|
||||
public void finishThinking() {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
var thoughtProcessPanel = getExistingThoughtProcessPanel();
|
||||
if (thoughtProcessPanel != null && !thoughtProcessPanel.isFinished()) {
|
||||
thoughtProcessPanel.setFinished();
|
||||
}
|
||||
finishThinkingSection(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -270,6 +265,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
contentPanel.removeAll();
|
||||
streamOutputParser.clear();
|
||||
accumulatedThinking.setLength(0);
|
||||
currentThinkingPanel = null;
|
||||
|
||||
// Reset for the next incoming message
|
||||
prepareProcessingText(true);
|
||||
|
|
@ -314,21 +310,26 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
private void processThinkingOutput(String thoughtProcess) {
|
||||
progressPanel.setVisible(false);
|
||||
|
||||
var thoughtProcessPanel = getExistingThoughtProcessPanel();
|
||||
if (thoughtProcessPanel == null) {
|
||||
thoughtProcessPanel = new ThoughtProcessPanel();
|
||||
thoughtProcessPanel.updateText(thoughtProcess);
|
||||
contentPanel.add(thoughtProcessPanel);
|
||||
} else {
|
||||
thoughtProcessPanel.updateText(thoughtProcess);
|
||||
if (currentThinkingPanel == null || currentThinkingPanel.isFinished()) {
|
||||
currentThinkingPanel = new ThinkingPanel();
|
||||
contentPanel.add(currentThinkingPanel);
|
||||
}
|
||||
currentThinkingPanel.updateText(thoughtProcess);
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
}
|
||||
|
||||
private ThoughtProcessPanel getExistingThoughtProcessPanel() {
|
||||
return (ThoughtProcessPanel) Stream.of(contentPanel.getComponents())
|
||||
.filter(it -> it instanceof ThoughtProcessPanel)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
private void finishThinkingSection(boolean resetStreamingSection) {
|
||||
if (currentThinkingPanel != null && !currentThinkingPanel.isFinished()) {
|
||||
currentThinkingPanel.setFinished();
|
||||
}
|
||||
currentThinkingPanel = null;
|
||||
accumulatedThinking.setLength(0);
|
||||
if (resetStreamingSection) {
|
||||
finishCurrentStreamingSection();
|
||||
}
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
}
|
||||
|
||||
private void processResponse(Segment item, boolean caretVisible) {
|
||||
|
|
@ -337,9 +338,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
return;
|
||||
}
|
||||
|
||||
var thoughtProcessPanel = getExistingThoughtProcessPanel();
|
||||
if (thoughtProcessPanel != null && !thoughtProcessPanel.isFinished()) {
|
||||
thoughtProcessPanel.setFinished();
|
||||
if (currentThinkingPanel != null && !currentThinkingPanel.isFinished()) {
|
||||
finishThinkingSection(true);
|
||||
}
|
||||
|
||||
if (item instanceof CodeEnd) {
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ import com.intellij.icons.AllIcons
|
|||
import com.intellij.ui.JBColor
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.components.BorderLayoutPanel
|
||||
import ee.carlrobert.codegpt.util.MarkdownUtil
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import ee.carlrobert.codegpt.util.MarkdownUtil
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.event.ItemEvent
|
||||
import javax.swing.*
|
||||
|
||||
class ThoughtProcessPanel : JPanel(BorderLayout()) {
|
||||
class ThinkingPanel : BorderLayoutPanel() {
|
||||
|
||||
private var finished: Boolean = false
|
||||
private val startedAtMillis = System.currentTimeMillis()
|
||||
private val responseBodyContent = UIUtil.createTextPane("", false).apply {
|
||||
foreground = JBUI.CurrentTheme.Label.disabledForeground()
|
||||
}
|
||||
|
|
@ -31,7 +32,7 @@ class ThoughtProcessPanel : JPanel(BorderLayout()) {
|
|||
fun setFinished() {
|
||||
if (finished) return
|
||||
|
||||
toggleButton.text = CodeGPTBundle.get("thoughtProcess.title")
|
||||
toggleButton.text = formatFinishedTitle()
|
||||
toggleButton.isSelected = false
|
||||
finished = true
|
||||
|
||||
|
|
@ -44,12 +45,18 @@ class ThoughtProcessPanel : JPanel(BorderLayout()) {
|
|||
)
|
||||
)
|
||||
)
|
||||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
|
||||
fun updateText(text: String) {
|
||||
responseBodyContent.text = MarkdownUtil.convertMdToHtml(text)
|
||||
}
|
||||
|
||||
fun getTitleText(): String = toggleButton.text
|
||||
|
||||
fun getRenderedText(): String = responseBodyContent.text
|
||||
|
||||
private fun createContentPanel(): JPanel {
|
||||
val panel = JPanel().apply {
|
||||
isOpaque = false
|
||||
|
|
@ -64,7 +71,11 @@ class ThoughtProcessPanel : JPanel(BorderLayout()) {
|
|||
}
|
||||
|
||||
private fun createToggleButton() =
|
||||
JToggleButton(CodeGPTBundle.get("thoughtProcess.thinking"), AllIcons.General.ArrowUp, true).apply {
|
||||
JToggleButton(
|
||||
CodeGPTBundle.get("thoughtProcess.thinking"),
|
||||
AllIcons.General.ArrowRight,
|
||||
true
|
||||
).apply {
|
||||
isFocusPainted = false
|
||||
isContentAreaFilled = false
|
||||
background = background
|
||||
|
|
@ -77,4 +88,14 @@ class ThoughtProcessPanel : JPanel(BorderLayout()) {
|
|||
contentPanel.isVisible = e.stateChange == ItemEvent.SELECTED
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatFinishedTitle(): String {
|
||||
val elapsedSeconds = ((System.currentTimeMillis() - startedAtMillis) / 1000).toInt()
|
||||
.coerceAtLeast(1)
|
||||
return if (elapsedSeconds < 60) {
|
||||
CodeGPTBundle.get("thoughtProcess.duration.seconds", elapsedSeconds)
|
||||
} else {
|
||||
CodeGPTBundle.get("thoughtProcess.duration.minutes", elapsedSeconds / 60)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -478,6 +478,8 @@ userInput.addContextTooltip=Add Context
|
|||
# Thought process panel
|
||||
thoughtProcess.thinking=Thinking...
|
||||
thoughtProcess.title=Thought Process
|
||||
thoughtProcess.duration.seconds=Thought for {0} sec
|
||||
thoughtProcess.duration.minutes=Thought for {0} min
|
||||
agent.credits.label=ProxyAI credits
|
||||
agent.credits.remainingValue={0} left
|
||||
agent.credits.tooltip.remaining=Remaining: {0}
|
||||
|
|
|
|||
|
|
@ -323,6 +323,10 @@ smartTextPane.stopButton.title=\u505C\u6B62
|
|||
smartTextPane.stopButton.description=\u505C\u6B62\u8865\u5168
|
||||
smartTextPane.promptEnhancer.title=\u589E\u5F3A\u63D0\u793A
|
||||
smartTextPane.promptEnhancer.description=\u589E\u5F3A Agent \u6A21\u5F0F\u7684\u63D0\u793A
|
||||
thoughtProcess.thinking=Thinking...
|
||||
thoughtProcess.title=Thought Process
|
||||
thoughtProcess.duration.seconds=Thought for {0} sec
|
||||
thoughtProcess.duration.minutes=Thought for {0} min
|
||||
promptEnhancer.thinking=\u6B63\u5728\u589E\u5F3A\u63D0\u793A...
|
||||
chatMessageResponseBody.webPages.title=\u7F51\u9875
|
||||
chatMessageResponseBody.webDocs.startProgress.label=\u6B63\u5728\u5206\u6790\u7F51\u9875\u5185\u5BB9...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue