mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-21 02:11:29 +00:00
feat: display web docs progress
This commit is contained in:
parent
ce0b90f232
commit
03feba0a4f
11 changed files with 195 additions and 32 deletions
|
|
@ -25,4 +25,6 @@ public final class Icons {
|
|||
public static final Icon Ollama = IconLoader.getIcon("/icons/ollama.svg", Icons.class);
|
||||
public static final Icon User = IconLoader.getIcon("/icons/user.svg", Icons.class);
|
||||
public static final Icon Upload = IconLoader.getIcon("/icons/upload.svg", Icons.class);
|
||||
public static final Icon GreenCheckmark =
|
||||
IconLoader.getIcon("/icons/greenCheckmark.svg", Icons.class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import ee.carlrobert.codegpt.toolwindow.ui.ChatToolWindowLandingPanel;
|
|||
import ee.carlrobert.codegpt.ui.OverlayUtil;
|
||||
import ee.carlrobert.codegpt.ui.textarea.AppliedActionInlay;
|
||||
import ee.carlrobert.codegpt.ui.textarea.UserInputPanel;
|
||||
import ee.carlrobert.codegpt.ui.textarea.suggestion.item.CreateDocumentationActionItem;
|
||||
import ee.carlrobert.codegpt.ui.textarea.suggestion.item.DocumentationActionItem;
|
||||
import ee.carlrobert.codegpt.ui.textarea.suggestion.item.PersonaActionItem;
|
||||
import ee.carlrobert.codegpt.ui.textarea.suggestion.item.WebSearchActionItem;
|
||||
|
|
@ -175,7 +176,8 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
.withReloadAction(() -> reloadMessage(message, conversation, conversationType))
|
||||
.withDeleteAction(() -> removeMessage(message.getId(), conversation))
|
||||
.addContent(
|
||||
new ChatMessageResponseBody(project, true, false, message.isWebSearchIncluded(), this));
|
||||
new ChatMessageResponseBody(project, true, false, message.isWebSearchIncluded(),
|
||||
message.getDocumentationDetails() != null, this));
|
||||
}
|
||||
|
||||
private void reloadMessage(
|
||||
|
|
@ -265,7 +267,8 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
|
||||
var addedDocumentation = CodeGPTKeys.ADDED_DOCUMENTATION.get(project);
|
||||
var appliedInlayExists = appliedInlayActions.stream()
|
||||
.anyMatch(it -> it.getSuggestion() instanceof DocumentationActionItem);
|
||||
.anyMatch(it -> it.getSuggestion() instanceof DocumentationActionItem
|
||||
|| it.getSuggestion() instanceof CreateDocumentationActionItem);
|
||||
if (addedDocumentation != null && appliedInlayExists) {
|
||||
message.setDocumentationDetails(addedDocumentation);
|
||||
CodeGPTKeys.ADDED_DOCUMENTATION.set(project, null);
|
||||
|
|
@ -273,7 +276,7 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
|
||||
var addedPersona = CodeGPTKeys.ADDED_PERSONA.get(project);
|
||||
var personaInlayExists = appliedInlayActions.stream()
|
||||
.anyMatch(it -> it.getSuggestion() instanceof PersonaActionItem);
|
||||
.anyMatch(it -> it.getSuggestion() instanceof PersonaActionItem);
|
||||
if (addedPersona != null && personaInlayExists) {
|
||||
message.setPersonaDetails(addedPersona);
|
||||
CodeGPTKeys.ADDED_PERSONA.set(project, null);
|
||||
|
|
|
|||
|
|
@ -121,8 +121,7 @@ abstract class ToolWindowCompletionResponseEventListener implements
|
|||
|
||||
@Override
|
||||
public void handleCodeGPTEvent(CodeGPTEvent event) {
|
||||
ApplicationManager.getApplication().invokeLater(() ->
|
||||
responseContainer.displayWebSearchItem(event.getEvent().getDetails()));
|
||||
responseContainer.handleCodeGPTEvent(event);
|
||||
}
|
||||
|
||||
private void stopStreaming(ChatMessageResponseBody responseContainer) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import static ee.carlrobert.codegpt.util.MarkdownUtil.convertMdToHtml;
|
|||
import static java.lang.String.format;
|
||||
import static javax.swing.event.HyperlinkEvent.EventType.ACTIVATED;
|
||||
|
||||
import com.intellij.icons.AllIcons.General;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
|
|
@ -14,12 +15,19 @@ import com.intellij.openapi.util.io.FileUtil;
|
|||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import com.intellij.util.ui.JBFont;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.vladsch.flexmark.ast.FencedCodeBlock;
|
||||
import com.vladsch.flexmark.parser.Parser;
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle;
|
||||
import ee.carlrobert.codegpt.Icons;
|
||||
import ee.carlrobert.codegpt.actions.ActionType;
|
||||
import ee.carlrobert.codegpt.events.Details;
|
||||
import ee.carlrobert.codegpt.events.AnalysisCompletedEventDetails;
|
||||
import ee.carlrobert.codegpt.events.AnalysisFailedEventDetails;
|
||||
import ee.carlrobert.codegpt.events.CodeGPTEvent;
|
||||
import ee.carlrobert.codegpt.events.EventDetails;
|
||||
import ee.carlrobert.codegpt.events.WebSearchEventDetails;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettingsConfigurable;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.StreamParser;
|
||||
|
|
@ -29,11 +37,16 @@ import ee.carlrobert.codegpt.ui.UIUtil;
|
|||
import ee.carlrobert.codegpt.util.EditorUtil;
|
||||
import ee.carlrobert.codegpt.util.MarkdownUtil;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.FlowLayout;
|
||||
import java.util.Objects;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
public class ChatMessageResponseBody extends JPanel {
|
||||
|
||||
|
|
@ -41,8 +54,10 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
private final Disposable parentDisposable;
|
||||
private final StreamParser streamParser;
|
||||
private final boolean readOnly;
|
||||
private final DefaultListModel<Details> webpageListModel = new DefaultListModel<>();
|
||||
private final DefaultListModel<WebSearchEventDetails> webpageListModel = new DefaultListModel<>();
|
||||
private final WebpageList webpageList = new WebpageList(webpageListModel);
|
||||
private final JPanel webDocProgressContainer = new JPanel();
|
||||
private final AsyncProcessIcon spinner = new AsyncProcessIcon("sign_in_spinner");
|
||||
private ResponseEditorPanel currentlyProcessedEditorPanel;
|
||||
private JTextPane currentlyProcessedTextPane;
|
||||
private JPanel webpageListPanel;
|
||||
|
|
@ -56,7 +71,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
Project project,
|
||||
boolean withGhostText,
|
||||
Disposable parentDisposable) {
|
||||
this(project, withGhostText, false, false, parentDisposable);
|
||||
this(project, withGhostText, false, false, false, parentDisposable);
|
||||
}
|
||||
|
||||
public ChatMessageResponseBody(
|
||||
|
|
@ -64,13 +79,14 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
boolean withGhostText,
|
||||
boolean readOnly,
|
||||
boolean webSearchIncluded,
|
||||
boolean webDocIncluded,
|
||||
Disposable parentDisposable) {
|
||||
super(new BorderLayout());
|
||||
this.project = project;
|
||||
this.parentDisposable = parentDisposable;
|
||||
this.streamParser = new StreamParser();
|
||||
this.readOnly = readOnly;
|
||||
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
setOpaque(false);
|
||||
|
||||
if (webSearchIncluded) {
|
||||
|
|
@ -78,6 +94,12 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
add(webpageListPanel);
|
||||
}
|
||||
|
||||
if (webDocIncluded) {
|
||||
webDocProgressContainer.setLayout(new BoxLayout(webDocProgressContainer, BoxLayout.Y_AXIS));
|
||||
webDocProgressContainer.setBorder(JBUI.Borders.emptyBottom(8));
|
||||
add(webDocProgressContainer);
|
||||
}
|
||||
|
||||
if (withGhostText) {
|
||||
prepareProcessingText(!readOnly);
|
||||
currentlyProcessedTextPane.setText(
|
||||
|
|
@ -161,10 +183,30 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
});
|
||||
}
|
||||
|
||||
public void displayWebSearchItem(Details details) {
|
||||
webpageListModel.addElement(details);
|
||||
webpageList.revalidate();
|
||||
webpageList.repaint();
|
||||
public void handleCodeGPTEvent(CodeGPTEvent codegptEvent) {
|
||||
ApplicationManager.getApplication()
|
||||
.invokeLater(() -> {
|
||||
var event = codegptEvent.getEvent();
|
||||
if (event.getDetails() instanceof WebSearchEventDetails webSearchEventDetails) {
|
||||
displayWebSearchItem(webSearchEventDetails);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getType()) {
|
||||
case WEB_SEARCH_ITEM -> {
|
||||
if (event.getDetails() != null
|
||||
&& event.getDetails() instanceof WebSearchEventDetails eventDetails) {
|
||||
displayWebSearchItem(eventDetails);
|
||||
}
|
||||
}
|
||||
|
||||
case ANALYZE_WEB_DOC_STARTED -> showWebDocsProgress();
|
||||
case ANALYZE_WEB_DOC_COMPLETED -> completeWebDocsProgress(event.getDetails());
|
||||
case ANALYZE_WEB_DOC_FAILED -> failWebDocsProgress(event.getDetails());
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void hideCaret() {
|
||||
|
|
@ -236,6 +278,45 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
add(currentlyProcessedEditorPanel);
|
||||
}
|
||||
|
||||
private void displayWebSearchItem(WebSearchEventDetails details) {
|
||||
webpageListModel.addElement(details);
|
||||
webpageList.revalidate();
|
||||
webpageList.repaint();
|
||||
}
|
||||
|
||||
private void showWebDocsProgress() {
|
||||
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
wrapper.add(spinner);
|
||||
wrapper.add(Box.createHorizontalStrut(4));
|
||||
wrapper.add(new JBLabel(
|
||||
CodeGPTBundle.get("chatMessageResponseBody.webDocs.startProgress.label")).withFont(
|
||||
JBFont.small()));
|
||||
updateWebDocsProgress(wrapper);
|
||||
}
|
||||
|
||||
private void completeWebDocsProgress(EventDetails eventDetails) {
|
||||
if (eventDetails instanceof AnalysisCompletedEventDetails defaultEventDetails) {
|
||||
updateWebDocsProgressLabel(defaultEventDetails.getDescription(), Icons.GreenCheckmark);
|
||||
}
|
||||
}
|
||||
|
||||
private void failWebDocsProgress(EventDetails eventDetails) {
|
||||
if (eventDetails instanceof AnalysisFailedEventDetails failedEventDetails) {
|
||||
updateWebDocsProgressLabel(failedEventDetails.getError(), General.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWebDocsProgressLabel(String text, Icon icon) {
|
||||
updateWebDocsProgress(new JBLabel(text, icon, SwingConstants.LEADING).withFont(JBFont.small()));
|
||||
}
|
||||
|
||||
private void updateWebDocsProgress(Component content) {
|
||||
webDocProgressContainer.removeAll();
|
||||
webDocProgressContainer.add(JBUI.Panels.simplePanel(content));
|
||||
webDocProgressContainer.revalidate();
|
||||
webDocProgressContainer.repaint();
|
||||
}
|
||||
|
||||
private JTextPane createTextPane(String text, boolean caretVisible) {
|
||||
var textPane = UIUtil.createTextPane(text, false, event -> {
|
||||
if (FileUtil.exists(event.getDescription()) && ACTIVATED.equals(event.getEventType())) {
|
||||
|
|
@ -258,7 +339,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
var title = new JPanel(new BorderLayout());
|
||||
title.setOpaque(false);
|
||||
title.setBorder(JBUI.Borders.empty(8, 0));
|
||||
title.add(new JBLabel(CodeGPTBundle.get("chatMessageResponseBody.webPagesTitle"))
|
||||
title.add(new JBLabel(CodeGPTBundle.get("chatMessageResponseBody.webPages.title"))
|
||||
.withFont(JBUI.Fonts.miniFont()), BorderLayout.LINE_START);
|
||||
var listPanel = new JPanel(new BorderLayout());
|
||||
listPanel.add(webpageList, BorderLayout.LINE_START);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import ee.carlrobert.codegpt.CodeGPTBundle;
|
|||
import ee.carlrobert.codegpt.CodeGPTKeys;
|
||||
import ee.carlrobert.codegpt.Icons;
|
||||
import ee.carlrobert.codegpt.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.events.Details;
|
||||
import ee.carlrobert.codegpt.events.WebSearchEventDetails;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettings;
|
||||
import ee.carlrobert.codegpt.toolwindow.ui.WebpageList;
|
||||
import java.awt.BorderLayout;
|
||||
|
|
@ -66,9 +66,10 @@ public class UserMessagePanel extends JPanel {
|
|||
var panel = new JPanel(new BorderLayout());
|
||||
panel.setOpaque(false);
|
||||
if (addedDocumentation != null) {
|
||||
var listModel = new DefaultListModel<Details>();
|
||||
listModel.addElement(new Details(UUID.randomUUID().toString(), addedDocumentation.getName(),
|
||||
addedDocumentation.getUrl(), addedDocumentation.getUrl()));
|
||||
var listModel = new DefaultListModel<WebSearchEventDetails>();
|
||||
listModel.addElement(
|
||||
new WebSearchEventDetails(UUID.randomUUID(), addedDocumentation.getName(),
|
||||
addedDocumentation.getUrl(), addedDocumentation.getUrl()));
|
||||
panel.add(createWebpageListPanel(new WebpageList(listModel)), BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ public class UserMessagePanel extends JPanel {
|
|||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
parentDisposable)
|
||||
.withResponse(prompt);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue