mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-17 03:57:27 +00:00
fix: render new panels after tool updates
This commit is contained in:
parent
a10014da6d
commit
876b20cd3b
3 changed files with 108 additions and 4 deletions
|
|
@ -153,11 +153,11 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
}
|
||||
|
||||
public void addToolStatusPanel(JComponent component) {
|
||||
currentlyProcessedTextPane = null;
|
||||
currentlyProcessedEditorPanel = null;
|
||||
currentlyProcessedMermaidPanel = null;
|
||||
streamOutputParser.clear();
|
||||
finishCurrentStreamingSection();
|
||||
streamOutputParser.startNewVisualSection();
|
||||
contentPanel.add(component);
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
}
|
||||
|
||||
public void updateMessage(String partialMessage) {
|
||||
|
|
@ -379,6 +379,12 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
private void finishCurrentStreamingSection() {
|
||||
currentlyProcessedTextPane = null;
|
||||
currentlyProcessedEditorPanel = null;
|
||||
currentlyProcessedMermaidPanel = null;
|
||||
}
|
||||
|
||||
private void processCode(Segment item) {
|
||||
if (isMermaidCode(item)) {
|
||||
processMermaid(item.getContent());
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ class SseMessageParser : MessageParser {
|
|||
buffer.clear()
|
||||
}
|
||||
|
||||
fun startNewVisualSection() {
|
||||
buffer.clear()
|
||||
parserState = when (val state = parserState) {
|
||||
is ParserState.Outside -> ParserState.Outside
|
||||
is ParserState.CodeHeaderWaiting -> state.copy(content = "")
|
||||
is ParserState.InCode -> state.copy(content = "")
|
||||
is ParserState.InSearch -> state.copy(searchContent = "")
|
||||
is ParserState.InReplace -> state.copy(searchContent = "", replaceContent = "")
|
||||
is ParserState.InThinking -> ParserState.InThinking()
|
||||
}
|
||||
}
|
||||
|
||||
override fun parse(input: String): List<Segment> {
|
||||
val segments = mutableListOf<Segment>()
|
||||
var position = 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package ee.carlrobert.codegpt.toolwindow.chat.ui
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.editor.ResponseEditorPanel
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import testsupport.IntegrationTest
|
||||
import java.awt.Component
|
||||
import java.awt.Container
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.JTextPane
|
||||
|
||||
class ChatMessageResponseBodyTest : IntegrationTest() {
|
||||
|
||||
fun testToolPanelStartsNewTextPaneForSubsequentStreamedText() {
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
val disposable = Disposer.newDisposable()
|
||||
try {
|
||||
val responseBody = ChatMessageResponseBody(project, false, disposable)
|
||||
|
||||
responseBody.updateMessage("Hello")
|
||||
responseBody.addToolStatusPanel(JPanel())
|
||||
responseBody.updateMessage(" world")
|
||||
|
||||
val textPanes = findComponents(responseBody, JTextPane::class.java)
|
||||
assertThat(textPanes).hasSize(2)
|
||||
assertThat(textPanes.first().text).contains("Hello")
|
||||
assertThat(textPanes.last().text).contains("world")
|
||||
assertThat(textPanes.last().text).doesNotContain("Hello")
|
||||
} finally {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testToolPanelStartsNewCodePanelForSubsequentStreamedCode() {
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
val disposable = Disposer.newDisposable()
|
||||
try {
|
||||
val responseBody = ChatMessageResponseBody(project, false, disposable)
|
||||
|
||||
responseBody.updateMessage("```kotlin\nfun main() {\n")
|
||||
responseBody.addToolStatusPanel(JPanel())
|
||||
responseBody.updateMessage(" println(\"x\")\n}\n```")
|
||||
|
||||
val editorPanels = findComponents(responseBody, ResponseEditorPanel::class.java)
|
||||
assertThat(editorPanels).hasSize(2)
|
||||
assertThat(editorPanels.first().getEditor()?.document?.text)
|
||||
.contains("fun main() {")
|
||||
.doesNotContain("println(\"x\")")
|
||||
assertThat(editorPanels.last().getEditor()?.document?.text)
|
||||
.contains("println(\"x\")")
|
||||
.contains("}")
|
||||
.doesNotContain("fun main() {")
|
||||
|
||||
val textPanes = findComponents(responseBody, JTextPane::class.java)
|
||||
assertThat(textPanes).isEmpty()
|
||||
|
||||
editorPanels.forEach { panel ->
|
||||
panel.getEditor()?.let { editor ->
|
||||
EditorFactory.getInstance().releaseEditor(editor)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Component> findComponents(root: Component, type: Class<T>): List<T> {
|
||||
val matches = mutableListOf<T>()
|
||||
|
||||
fun visit(component: Component) {
|
||||
if (type.isInstance(component)) {
|
||||
matches.add(type.cast(component))
|
||||
}
|
||||
if (component is Container) {
|
||||
component.components.forEach(::visit)
|
||||
}
|
||||
}
|
||||
|
||||
visit(root)
|
||||
return matches
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue