#178 - Add support for running local LLMs via LLaMA C/C++ port (#249)

* Initial implementation of integrating llama.cpp to run LLaMA models locally

* Move submodule

* Copy llama submodule to bundle

* Support for downloading models from IDE

* Code cleanup

* Store port field

* Replace service selection radio group with dropdown

* Add quantization support + other fixes

* Add option to override host

* Fix override host handler

* Disable port field when override host enabled

* Design updates

* Fix llama settings configuration, design changes, clean up code

* Improve You.com coupon design

* Add new Phind model and help tooltip

* Fetch you.com subscription

* Add CodeBooga model, fix downloadable model selection

* Chat history support

* Code refactoring, minor bug fixes

* UI updates, several bug fixes, removed code llama python model

* Code cleanup, enable llama port only on macOS

* Change downloaded gguf models path

* Move some of the labels to codegpt bundle

* Minor fixes

* Remove ToRA model, add help texts

* Fix test

* Modify description
This commit is contained in:
Carl-Robert 2023-11-03 12:00:24 +02:00 committed by GitHub
parent ca2eb9b6fa
commit 45908e69df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 2748 additions and 533 deletions

View file

@ -21,6 +21,9 @@ public class ModelIconLabel extends JBLabel {
if ("azure.chat.completion".equals(clientCode)) {
setIcon(Icons.AzureIcon);
}
if ("llama.chat.completion".equals(clientCode)) {
setIcon(Icons.LlamaIcon);
}
setText(formatModelName(modelCode));
setFont(JBFont.small().asBold());
setHorizontalAlignment(SwingConstants.LEADING);

View file

@ -5,27 +5,32 @@ import static ee.carlrobert.codegpt.util.ThemeUtils.getPanelBackgroundColor;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import com.intellij.ide.HelpTooltip;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.JBUI.Borders;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.actions.ActionType;
import ee.carlrobert.codegpt.completions.CompletionRequestHandler;
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
import ee.carlrobert.codegpt.completions.you.YouSerpResult;
import ee.carlrobert.codegpt.completions.you.YouSubscriptionNotifier;
import ee.carlrobert.codegpt.completions.you.YouUserManager;
import ee.carlrobert.codegpt.completions.you.auth.AuthenticationNotifier;
import ee.carlrobert.codegpt.completions.you.auth.SignedOutNotifier;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.ConversationService;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
import ee.carlrobert.codegpt.settings.state.AzureSettingsState;
import ee.carlrobert.codegpt.settings.state.LlamaSettingsState;
import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
import ee.carlrobert.codegpt.settings.state.SettingsState;
import ee.carlrobert.codegpt.settings.state.YouSettingsState;
@ -38,6 +43,7 @@ import ee.carlrobert.codegpt.toolwindow.chat.components.UserMessagePanel;
import ee.carlrobert.codegpt.toolwindow.chat.components.UserPromptTextArea;
import ee.carlrobert.codegpt.util.EditorUtils;
import ee.carlrobert.codegpt.util.OverlayUtils;
import ee.carlrobert.codegpt.util.SwingUtils;
import ee.carlrobert.codegpt.util.file.FileUtils;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
@ -50,6 +56,7 @@ import java.util.UUID;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import org.jetbrains.annotations.NotNull;
@ -57,6 +64,8 @@ import org.jetbrains.annotations.Nullable;
public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPanel {
private static final Logger LOG = Logger.getInstance(BaseChatToolWindowTabPanel.class);
private final boolean useContextualSearch;
private final JPanel rootPanel;
private final ScrollablePanel scrollablePanel;
@ -105,10 +114,31 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
public void displayLandingView() {
scrollablePanel.removeAll();
scrollablePanel.add(getLandingView());
var youUserManager = YouUserManager.getInstance();
if (SettingsState.getInstance().isUseYouService() &&
(!youUserManager.isAuthenticated() || !youUserManager.isSubscribed())) {
scrollablePanel.add(new ResponsePanel().addContent(createTextPane()));
}
scrollablePanel.repaint();
scrollablePanel.revalidate();
}
private JTextPane createTextPane() {
var textPane = SwingUtils.createTextPane(SwingUtils::handleHyperlinkClicked);
textPane.setBackground(getPanelBackgroundColor());
textPane.setFocusable(false);
textPane.setText(
"<html>\n"
+ "<body>\n"
+ " <p style=\"margin: 4px 0;\">Use CodeGPT coupon for free month of GPT-4.</p>\n"
+ " <p style=\"margin: 4px 0;\">\n"
+ " <a href=\"https://you.com/plans\">Sign up here</a>\n"
+ " </p>\n"
+ "</body>\n"
+ "</html>");
return textPane;
}
@Override
public void startNewConversation(Message message) {
conversation = conversationService.startConversation();
@ -165,7 +195,9 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
requestHandler.withContextualSearch(useContextualSearch);
requestHandler.addMessageListener(partialMessage -> {
try {
responseContainer.update(partialMessage);
LOG.debug(partialMessage);
ApplicationManager.getApplication()
.invokeLater(() -> responseContainer.update(partialMessage));
} catch (Exception e) {
responseContainer.displayDefaultError();
throw new RuntimeException("Error while updating the content", e);
@ -354,23 +386,33 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
JBUI.Borders.empty(8)));
wrapper.setBackground(getPanelBackgroundColor());
wrapper.add(userPromptTextArea, BorderLayout.SOUTH);
if (model != null) {
var header = new JPanel(new BorderLayout());
header.setBackground(getPanelBackgroundColor());
header.setBorder(JBUI.Borders.emptyBottom(8));
if ("YouCode".equals(model)) {
var messageBusConnection = ApplicationManager.getApplication().getMessageBus().connect();
subscribeToYouModelChangeTopic();
subscribeToYouAuthTopic();
subscribeToYouSubscriptionTopic(messageBusConnection);
subscribeToSignedOutTopic(messageBusConnection);
header.add(gpt4CheckBox, BorderLayout.LINE_START);
}
header.add(modelIconWrapper, BorderLayout.LINE_END);
wrapper.add(header);
}
rootPanel.add(wrapper, gbc);
userPromptTextArea.requestFocusInWindow();
userPromptTextArea.requestFocus();
}
private void subscribeToSignedOutTopic(MessageBusConnection messageBusConnection) {
messageBusConnection.subscribe(
SignedOutNotifier.SIGNED_OUT_TOPIC,
(SignedOutNotifier) () -> gpt4CheckBox.setEnabled(false));
}
private void subscribeToYouModelChangeTopic() {
project.getMessageBus()
.connect()
@ -379,24 +421,26 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
(YouModelChangeNotifier) gpt4CheckBox::setSelected);
}
private void subscribeToYouAuthTopic() {
ApplicationManager.getApplication()
.getMessageBus()
.connect()
.subscribe(AuthenticationNotifier.AUTHENTICATION_TOPIC,
(AuthenticationNotifier) () -> gpt4CheckBox.setEnabled(true));
private void subscribeToYouSubscriptionTopic(MessageBusConnection messageBusConnection) {
messageBusConnection.subscribe(
YouSubscriptionNotifier.SUBSCRIPTION_TOPIC,
(YouSubscriptionNotifier) () -> {
displayLandingView();
gpt4CheckBox.setEnabled(true);
});
}
private JBCheckBox createGPT4ModelCheckBox() {
var gpt4CheckBox = new JBCheckBox("Use GPT-4 model");
var gpt4CheckBox = new JBCheckBox(CodeGPTBundle.get("toolwindow.chat.youProCheckBox.text"));
gpt4CheckBox.setOpaque(false);
gpt4CheckBox.setEnabled(YouUserManager.getInstance().isAuthenticated());
gpt4CheckBox.setEnabled(YouUserManager.getInstance().isSubscribed());
gpt4CheckBox.setSelected(YouSettingsState.getInstance().isUseGPT4Model());
gpt4CheckBox.setToolTipText(getTooltipText(gpt4CheckBox.isSelected()));
gpt4CheckBox.addChangeListener(e -> {
var selected = ((JBCheckBox) e.getSource()).isSelected();
var tooltipText = getTooltipText(selected);
gpt4CheckBox.setToolTipText(tooltipText);
// TODO: Remove
project.getMessageBus()
.syncPublisher(YouModelChangeNotifier.YOU_MODEL_CHANGE_NOTIFIER_TOPIC)
.modelChanged(selected);
@ -406,9 +450,12 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
}
private String getTooltipText(boolean selected) {
return selected ?
"Turn off for faster responses" :
"<html>Turn on for complex queries, enable by creating an account on you.com<br />and signing in from plugin settings.<br />Use CodeGPT coupon for free month of GPT-4.</html>";
if (YouUserManager.getInstance().isSubscribed()) {
return selected ?
CodeGPTBundle.get("toolwindow.chat.youProCheckBox.disable") :
CodeGPTBundle.get("toolwindow.chat.youProCheckBox.enable");
}
return CodeGPTBundle.get("toolwindow.chat.youProCheckBox.notAllowed");
}
private String getClientCode() {
@ -422,6 +469,9 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
if (settings.isUseYouService()) {
return "you.chat.completion";
}
if (settings.isUseLlamaService()) {
return "llama.chat.completion";
}
return null;
}
@ -436,7 +486,25 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
if (settings.isUseYouService()) {
return "YouCode";
}
if (settings.isUseLlamaService()) {
var llamaSettings = LlamaSettingsState.getInstance();
if (llamaSettings.isUseCustomModel()) {
var filePath = llamaSettings.getCustomLlamaModelPath();
int lastSeparatorIndex = filePath.lastIndexOf('/');
if (lastSeparatorIndex == -1) {
return filePath;
}
return filePath.substring(lastSeparatorIndex + 1);
}
var huggingFaceModel = llamaSettings.getHuggingFaceModel();
var llamaModel = LlamaModel.findByHuggingFaceModel(huggingFaceModel);
return String.format(
"%s %dB (Q%d)",
llamaModel.getLabel(),
huggingFaceModel.getParameterSize(),
huggingFaceModel.getQuantization());
}
return null;
return "Unknown";
}
}

View file

@ -11,6 +11,7 @@ public class StreamParser {
private boolean isProcessingCode;
public List<StreamParseResponse> parse(String message) {
message = message.replace("\r", "");
messageBuilder.append(message);
Pattern pattern = Pattern.compile(CODE_BLOCK_STARTING_REGEX);

View file

@ -22,7 +22,6 @@ import com.vladsch.flexmark.util.data.MutableDataSet;
import ee.carlrobert.codegpt.actions.ActionType;
import ee.carlrobert.codegpt.completions.you.YouSerpResult;
import ee.carlrobert.codegpt.settings.SettingsConfigurable;
import ee.carlrobert.codegpt.settings.state.SettingsState;
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
import ee.carlrobert.codegpt.toolwindow.chat.ResponseNodeRenderer;
import ee.carlrobert.codegpt.toolwindow.chat.StreamParser;
@ -231,13 +230,13 @@ public class ChatMessageResponseBody extends JPanel {
add(currentlyProcessedElement);
}
private void prepareProcessingCodeResponse(String code, String language) {
private void prepareProcessingCodeResponse(String code, String markdownLanguage) {
hideCarets();
currentlyProcessedTextPane = null;
currentlyProcessedEditor = new ResponseEditor(
project,
code,
language,
markdownLanguage,
parentDisposable);
currentlyProcessedElement = new ResponseWrapper();
@ -249,15 +248,13 @@ public class ChatMessageResponseBody extends JPanel {
var editor = currentlyProcessedEditor.getEditor();
var document = editor.getDocument();
var application = ApplicationManager.getApplication();
Runnable updateDocumentRunnable = () -> {
application.runWriteAction(() ->
WriteCommandAction.runWriteCommandAction(project, () -> {
document.replaceString(0, document.getTextLength(), code);
editor.getCaretModel().moveToOffset(code.length());
editor.getComponent().revalidate();
editor.getComponent().repaint();
}));
};
Runnable updateDocumentRunnable = () -> application.runWriteAction(() ->
WriteCommandAction.runWriteCommandAction(project, () -> {
document.replaceString(0, document.getTextLength(), code);
editor.getCaretModel().moveToOffset(code.length());
editor.getComponent().revalidate();
editor.getComponent().repaint();
}));
if (application.isUnitTestMode()) {
application.invokeAndWait(updateDocumentRunnable);
@ -267,8 +264,7 @@ public class ChatMessageResponseBody extends JPanel {
}
private JTextPane createTextPane() {
var textPane = new JTextPane();
textPane.addHyperlinkListener(event -> {
var textPane = SwingUtils.createTextPane(event -> {
if (FileUtil.exists(event.getDescription()) && ACTIVATED.equals(event.getEventType())) {
VirtualFile file = LocalFileSystem.getInstance().findFileByPath(event.getDescription());
FileEditorManager.getInstance(project).openFile(Objects.requireNonNull(file), true);
@ -277,14 +273,10 @@ public class ChatMessageResponseBody extends JPanel {
SwingUtils.handleHyperlinkClicked(event);
});
textPane.setContentType("text/html");
textPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true);
textPane.setCaretPosition(textPane.getDocument().getLength());
textPane.setBackground(getBackground());
textPane.setFocusable(true);
textPane.getCaret().setVisible(true);
textPane.setEditable(false);
textPane.setCaretPosition(textPane.getDocument().getLength());
textPane.setBorder(JBUI.Borders.empty());
textPane.setBackground(getBackground());
return textPane;
}

View file

@ -9,6 +9,7 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.JBFont;
import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.Icons;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
@ -82,7 +83,10 @@ public class ResponsePanel extends JPanel {
public void addReloadAction(Runnable onReload) {
addIconActionButton(new IconActionButton(
new AnAction("Reload Response", "Reload response description", Actions.Refresh) {
new AnAction(
CodeGPTBundle.get("toolwindow.chat.response.action.reloadResponse.text"),
CodeGPTBundle.get("toolwindow.chat.response.action.reloadResponse.description"),
Actions.Refresh) {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
enableActions(false);
@ -93,7 +97,10 @@ public class ResponsePanel extends JPanel {
public void addDeleteAction(Runnable onDelete) {
addIconActionButton(new IconActionButton(
new AnAction("Delete Response", "Delete response description", Actions.GC) {
new AnAction(
CodeGPTBundle.get("toolwindow.chat.response.action.deleteResponse.text"),
CodeGPTBundle.get("toolwindow.chat.response.action.deleteResponse.description"),
Actions.GC) {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
onDelete.run();
@ -109,7 +116,10 @@ public class ResponsePanel extends JPanel {
}
private JBLabel getIconLabel() {
return new JBLabel("CodeGPT", Icons.DefaultIcon, SwingConstants.LEADING)
return new JBLabel(
CodeGPTBundle.get("project.label"),
Icons.DefaultIcon,
SwingConstants.LEADING)
.setAllowAutoWrapping(true)
.withFont(JBFont.label().asBold());
}

View file

@ -7,6 +7,7 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBTextArea;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.Icons;
import ee.carlrobert.codegpt.completions.CompletionRequestHandler;
import ee.carlrobert.codegpt.util.SwingUtils;
@ -55,7 +56,7 @@ public class UserPromptTextArea extends JPanel {
textArea.setBackground(BACKGROUND_COLOR);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.getEmptyText().setText("Ask me anything");
textArea.getEmptyText().setText(CodeGPTBundle.get("toolwindow.chat.textArea.emptyText"));
textArea.setBorder(JBUI.Borders.empty(8, 4));
var input = textArea.getInputMap();
input.put(KeyStroke.getKeyStroke("ENTER"), TEXT_SUBMIT);
@ -171,6 +172,7 @@ public class UserPromptTextArea extends JPanel {
}
}
// TODO: IconActionButton?
private JButton createIconButton(Icon icon, @Nullable Runnable submitListener) {
var button = SwingUtils.createIconButton(icon);
if (submitListener != null) {

View file

@ -4,7 +4,6 @@ import static com.intellij.openapi.ui.DialogWrapper.OK_EXIT_CODE;
import static ee.carlrobert.codegpt.util.ThemeUtils.getPanelBackgroundColor;
import static javax.swing.event.HyperlinkEvent.EventType.ACTIVATED;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
@ -14,9 +13,6 @@ import ee.carlrobert.codegpt.indexes.CodebaseIndexingTask;
import ee.carlrobert.codegpt.indexes.FolderStructureTreePanel;
import ee.carlrobert.codegpt.settings.SettingsConfigurable;
import ee.carlrobert.codegpt.toolwindow.chat.components.ResponsePanel;
import ee.carlrobert.codegpt.completions.you.YouUserManager;
import ee.carlrobert.codegpt.completions.you.auth.AuthenticationNotifier;
import ee.carlrobert.codegpt.completions.you.auth.SignedOutNotifier;
import ee.carlrobert.codegpt.util.OverlayUtils;
import ee.carlrobert.codegpt.util.SwingUtils;
import ee.carlrobert.vector.VectorStore;
@ -25,6 +21,7 @@ import javax.swing.event.HyperlinkEvent;
@FunctionalInterface
interface ActionEvent {
void handleAction(String prompt);
}
@ -43,43 +40,30 @@ class ContextualChatToolWindowLandingPanel extends ResponsePanel {
.connect()
.subscribe(CodebaseIndexingCompletedNotifier.INDEXING_COMPLETED_TOPIC,
(CodebaseIndexingCompletedNotifier) () -> updateContent(createContent()));
var messageBusConnection = ApplicationManager.getApplication().getMessageBus().connect();
messageBusConnection.subscribe(AuthenticationNotifier.AUTHENTICATION_TOPIC, (AuthenticationNotifier) () -> updateContent(createContent()));
messageBusConnection.subscribe(SignedOutNotifier.SIGNED_OUT_TOPIC, (SignedOutNotifier) () -> updateContent(createContent()));
}
private JTextPane createContent() {
var description = createTextPane();
var userManager = YouUserManager.getInstance();
if (userManager.getAuthenticationResponse() == null) {
description.setText("<html>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">It looks like you haven't logged in. Please <a href=\"LOGIN\">log in</a> to use the feature.</p>" +
"</html>");
return description;
}
if (!userManager.isSubscribed()) {
description.setText("<html>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">You are not currently subscribed to any plan.</p>" +
"</html>");
return description;
}
if (VectorStore.getInstance(CodeGPTPlugin.getPluginBasePath()).isIndexExists()) {
description.setText("<html>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">Feel free to ask me anything about your codebase, and I'll be your helpful guide, dedicated to providing you with the best answers possible!</p>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">Here are a few examples of how I might be helpful:</p>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">Feel free to ask me anything about your codebase, and I'll be your helpful guide, dedicated to providing you with the best answers possible!</p>"
+
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">Here are a few examples of how I might be helpful:</p>"
+
"<ul>" +
"<li><a href=\"LIST_DEPENDENCIES\">List all the dependencies that the project uses</a></li" +
"<li><a href=\"SCHEDULED_TASKS\">Are there any scheduled tasks or background jobs running in our codebase, and if so, what are they responsible for?</a></li>" +
"<li><a href=\"AUTHENTICATION_MECHANISM\">Can you provide an overview of the authentication and authorization mechanism implemented in our application?</a></li>" +
"<li><a href=\"LIST_DEPENDENCIES\">List all the dependencies that the project uses</a></li"
+
"<li><a href=\"SCHEDULED_TASKS\">Are there any scheduled tasks or background jobs running in our codebase, and if so, what are they responsible for?</a></li>"
+
"<li><a href=\"AUTHENTICATION_MECHANISM\">Can you provide an overview of the authentication and authorization mechanism implemented in our application?</a></li>"
+
"</html>");
} else {
description.setText("<html>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">It looks like you haven't indexed your codebase yet.</p>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\"><a href=\"START_INDEXING\">Start indexing</a> your codebase to get access to contextual chat experience.</p>" +
"<p style=\"margin-top: 4px; margin-bottom: 4px;\">It looks like you haven't indexed your codebase yet.</p>"
+
"<p style=\"margin-top: 4px; margin-bottom: 4px;\"><a href=\"START_INDEXING\">Start indexing</a> your codebase to get access to contextual chat experience.</p>"
+
"</html>");
}
@ -87,13 +71,8 @@ class ContextualChatToolWindowLandingPanel extends ResponsePanel {
}
private JTextPane createTextPane() {
var textPane = new JTextPane();
textPane.addHyperlinkListener(this::handleHyperlinkClicked);
var textPane = SwingUtils.createTextPane(this::handleHyperlinkClicked);
textPane.setBackground(getPanelBackgroundColor());
textPane.setContentType("text/html");
textPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true);
textPane.setFocusable(false);
textPane.setEditable(false);
return textPane;
}
@ -112,7 +91,8 @@ class ContextualChatToolWindowLandingPanel extends ResponsePanel {
"Are there any scheduled tasks or background jobs running in our codebase, and if so, what are they responsible for?");
break;
case "AUTHENTICATION_MECHANISM":
actionEvent.handleAction("Can you provide an overview of the authentication and authorization mechanism implemented in our application?");
actionEvent.handleAction(
"Can you provide an overview of the authentication and authorization mechanism implemented in our application?");
break;
case "START_INDEXING":
var folderStructureTreePanel = new FolderStructureTreePanel(project);

View file

@ -1,14 +1,9 @@
package ee.carlrobert.codegpt.toolwindow.chat.contextual;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import ee.carlrobert.codegpt.completions.you.YouUserManager;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.indexes.CodebaseIndexingCompletedNotifier;
import ee.carlrobert.codegpt.toolwindow.chat.BaseChatToolWindowTabPanel;
import ee.carlrobert.codegpt.completions.you.auth.AuthenticationNotifier;
import ee.carlrobert.codegpt.completions.you.auth.SignedOutNotifier;
import javax.swing.JComponent;
import org.jetbrains.annotations.NotNull;
@ -17,19 +12,6 @@ public class ContextualChatToolWindowTabPanel extends BaseChatToolWindowTabPanel
public ContextualChatToolWindowTabPanel(@NotNull Project project) {
super(project, true);
displayLandingView();
userPromptTextArea.setTextAreaEnabled(YouUserManager.getInstance().isSubscribed());
project.getMessageBus()
.connect()
.subscribe(CodebaseIndexingCompletedNotifier.INDEXING_COMPLETED_TOPIC,
(CodebaseIndexingCompletedNotifier) () -> userPromptTextArea.setTextAreaEnabled(
YouUserManager.getInstance().isSubscribed()));
var messageBusConnection = ApplicationManager.getApplication().getMessageBus().connect();
messageBusConnection.subscribe(AuthenticationNotifier.AUTHENTICATION_TOPIC,
(AuthenticationNotifier) () -> userPromptTextArea.setTextAreaEnabled(
YouUserManager.getInstance().isSubscribed()));
messageBusConnection.subscribe(SignedOutNotifier.SIGNED_OUT_TOPIC, (SignedOutNotifier) () -> userPromptTextArea.setTextAreaEnabled(false));
}
@Override

View file

@ -33,6 +33,8 @@ public class CopyAction extends TrackableAction {
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
locationOnScreen.y = locationOnScreen.y - 16;
OverlayUtils.showInfoBalloon("Code copied!", locationOnScreen);
OverlayUtils.showInfoBalloon(
CodeGPTBundle.get("toolwindow.chat.editor.action.copy.success"),
locationOnScreen);
}
}

View file

@ -34,7 +34,9 @@ public class EditAction extends TrackableAction {
settings.setCaretRowShown(!viewer);
event.getPresentation().setIcon(viewer ? Actions.EditSource : Actions.Show);
event.getPresentation().setText(viewer ? "Edit Source" : "Disable Editing");
event.getPresentation().setText(viewer ?
CodeGPTBundle.get("toolwindow.chat.editor.action.edit.title") :
CodeGPTBundle.get("toolwindow.chat.editor.action.disableEditing.title"));
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
locationOnScreen.y = locationOnScreen.y - 16;

View file

@ -41,13 +41,8 @@ class StandardChatToolWindowLandingPanel extends ResponsePanel {
}
private JTextPane createTextPane() {
var textPane = new JTextPane();
textPane.addHyperlinkListener(this::handleHyperlinkClicked);
var textPane = SwingUtils.createTextPane(this::handleHyperlinkClicked);
textPane.setBackground(getPanelBackgroundColor());
textPane.setContentType("text/html");
textPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true);
textPane.setFocusable(false);
textPane.setEditable(false);
return textPane;
}

View file

@ -3,8 +3,6 @@ package ee.carlrobert.codegpt.toolwindow.chat.standard;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.Constraints;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.DefaultCompactActionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;