mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-19 07:54:46 +00:00
Change project's name, heavy refactoring
This commit is contained in:
parent
c0cea7cc43
commit
483abe146b
80 changed files with 969 additions and 968 deletions
|
|
@ -1 +1 @@
|
|||
rootProject.name = "ChatGPT"
|
||||
rootProject.name = "CodeGPT"
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.official;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseError {
|
||||
|
||||
private Error error;
|
||||
|
||||
public Error getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(Error error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static class Error {
|
||||
private String message;
|
||||
private String type;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import ee.carlrobert.chatgpt.client.BaseApiResponse;
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponse implements BaseApiResponse {
|
||||
|
||||
private String id;
|
||||
private List<ApiResponseChoice> choices;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<ApiResponseChoice> getChoices() {
|
||||
return choices;
|
||||
}
|
||||
|
||||
public void setChoices(List<ApiResponseChoice> choices) {
|
||||
this.choices = choices;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseChoice {
|
||||
|
||||
private ApiResponseChoiceDelta delta;
|
||||
|
||||
public ApiResponseChoiceDelta getDelta() {
|
||||
return delta;
|
||||
}
|
||||
|
||||
public void setDelta(ApiResponseChoiceDelta delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseChoiceDelta {
|
||||
|
||||
private String role;
|
||||
private String content;
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.official.text.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import ee.carlrobert.chatgpt.client.BaseApiResponse;
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponse implements BaseApiResponse {
|
||||
|
||||
private String id;
|
||||
private List<ApiResponseChoice> choices;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<ApiResponseChoice> getChoices() {
|
||||
return choices;
|
||||
}
|
||||
|
||||
public void setChoices(List<ApiResponseChoice> choices) {
|
||||
this.choices = choices;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseDetail {
|
||||
|
||||
private String detail;
|
||||
|
||||
public String getDetail() {
|
||||
return detail;
|
||||
}
|
||||
|
||||
public void setDetail(String detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseError {
|
||||
|
||||
private ApiResponseErrorDetails detail;
|
||||
|
||||
public ApiResponseErrorDetails getDetail() {
|
||||
return detail;
|
||||
}
|
||||
|
||||
public void setDetail(ApiResponseErrorDetails detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseErrorDetails {
|
||||
|
||||
private String message;
|
||||
private String type;
|
||||
private String code;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseMessage {
|
||||
|
||||
private String id;
|
||||
private ApiResponseMessageAuthor author;
|
||||
private ApiResponseMessageContent content;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ApiResponseMessageAuthor getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(ApiResponseMessageAuthor author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public ApiResponseMessageContent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(ApiResponseMessageContent content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseMessageAuthor {
|
||||
|
||||
private String role;
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import icons.Icons;
|
||||
|
||||
public class ActionGroup extends DefaultActionGroup {
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
event.getPresentation().setIcon(Icons.DefaultIcon);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowService;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AskAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent event) {
|
||||
event.getPresentation().setEnabled(event.getProject() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
var project = event.getProject();
|
||||
if (project != null) {
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var toolWindow = toolWindowService.getToolWindow(project);
|
||||
var contentManager = toolWindow.getContentManager();
|
||||
|
||||
Arrays.stream(contentManager.getContents())
|
||||
.filter(it -> "Chat".equals(it.getTabName()))
|
||||
.findFirst()
|
||||
.ifPresentOrElse(
|
||||
contentManager::setSelectedContent,
|
||||
() -> contentManager.setSelectedContent(Objects.requireNonNull(contentManager.getContent(0)))
|
||||
);
|
||||
|
||||
ConversationsState.getInstance().startConversation();
|
||||
|
||||
toolWindow.show();
|
||||
toolWindow.setTitle("Chat");
|
||||
toolWindowService.removeAll();
|
||||
toolWindowService.paintLandingView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations.message;
|
||||
|
||||
public class Message {
|
||||
|
||||
private String prompt;
|
||||
private String response;
|
||||
|
||||
public String getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
public void setPrompt(String prompt) {
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(String response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow;
|
||||
|
||||
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.JBScrollPane;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.GenerateButton;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.TextArea;
|
||||
import java.awt.Adjustable;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatGptToolWindow {
|
||||
|
||||
private final Project project;
|
||||
private JPanel chatGptToolWindowContent;
|
||||
private JScrollPane scrollPane;
|
||||
private JTextArea textArea;
|
||||
private JScrollPane textAreaScrollPane;
|
||||
private JButton generateButton;
|
||||
|
||||
public ChatGptToolWindow(@NotNull Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public void handleSubmit() {
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var searchText = textArea.getText();
|
||||
toolWindowService.paintUserMessage(searchText);
|
||||
toolWindowService.sendMessage(searchText, project, this::scrollToBottom);
|
||||
textArea.setText("");
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
public JPanel getContent() {
|
||||
return chatGptToolWindowContent;
|
||||
}
|
||||
|
||||
private void scrollToBottom() {
|
||||
JScrollBar verticalBar = this.scrollPane.getVerticalScrollBar();
|
||||
verticalBar.addAdjustmentListener(new AdjustmentListener() {
|
||||
public void adjustmentValueChanged(AdjustmentEvent e) {
|
||||
Adjustable adjustable = e.getAdjustable();
|
||||
adjustable.setValue(adjustable.getMaximum());
|
||||
verticalBar.removeAdjustmentListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
textAreaScrollPane = new JBScrollPane() {
|
||||
@Override
|
||||
public JScrollBar createVerticalScrollBar() {
|
||||
JScrollBar verticalScrollBar = new JScrollPane.ScrollBar(1);
|
||||
verticalScrollBar.setPreferredSize(new Dimension(0, 0));
|
||||
return verticalScrollBar;
|
||||
}
|
||||
};
|
||||
textAreaScrollPane.setBorder(null);
|
||||
textAreaScrollPane.setViewportBorder(null);
|
||||
textAreaScrollPane.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createMatteBorder(1, 0, 0, 0, JBColor.border()),
|
||||
BorderFactory.createEmptyBorder(0, 5, 0, 10)));
|
||||
textAreaScrollPane.setViewportView(textArea);
|
||||
|
||||
textArea = new TextArea(this::handleSubmit, textAreaScrollPane);
|
||||
|
||||
ScrollablePanel scrollablePanel = new ScrollablePanel();
|
||||
scrollablePanel.setLayout(new BoxLayout(scrollablePanel, BoxLayout.Y_AXIS));
|
||||
|
||||
scrollPane = new JBScrollPane();
|
||||
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.setViewportView(scrollablePanel);
|
||||
scrollPane.setBorder(JBUI.Borders.empty(0, 8));
|
||||
scrollPane.setViewportBorder(null);
|
||||
|
||||
generateButton = new GenerateButton();
|
||||
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
toolWindowService.setGenerateButton((GenerateButton) generateButton); // TODO: Remove casting
|
||||
toolWindowService.setScrollPane(scrollPane);
|
||||
toolWindowService.setScrollablePanel(scrollablePanel);
|
||||
toolWindowService.paintLandingView();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowFactory;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.ui.content.ContentManagerListener;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.conversations.ConversationsToolWindow;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.JPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatGptToolWindowFactory implements ToolWindowFactory, DumbAware {
|
||||
|
||||
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
addContent(toolWindow, new ChatGptToolWindow(project).getContent(), "Chat");
|
||||
|
||||
var conversationToolWidow = new ConversationsToolWindow(project, toolWindow);
|
||||
addContent(toolWindow, conversationToolWidow.getContent(), "Conversation History");
|
||||
toolWindow.addContentManagerListener(new ContentManagerListener() {
|
||||
public void selectionChanged(@NotNull ContentManagerEvent event) {
|
||||
if ("Conversation History".equals(event.getContent().getTabName()) && event.getContent().isSelected()) {
|
||||
conversationToolWidow.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var conversation = ConversationsState.getCurrentConversation();
|
||||
if (conversation != null) {
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var contentManager = toolWindow.getContentManager();
|
||||
Arrays.stream(contentManager.getContents())
|
||||
.filter(content -> "Chat".equals(content.getTabName()))
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
content -> {
|
||||
if (contentManager.isSelected(content)) {
|
||||
toolWindowService.displayConversation(conversation);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void addContent(@NotNull ToolWindow toolWindow, JPanel content, String displayName) {
|
||||
toolWindow.getContentManager().addContent(ApplicationManager.getApplication()
|
||||
.getService(ContentFactory.class)
|
||||
.createContent(content, displayName, false));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow;
|
||||
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.createIconLabel;
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.createTextArea;
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.justifyLeft;
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.ui.LafManager;
|
||||
import com.intellij.ide.ui.LafManagerListener;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import ee.carlrobert.chatgpt.client.ClientFactory;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsConfigurable;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.GenerateButton;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.GenerateButton.Mode;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.SyntaxTextArea;
|
||||
import icons.Icons;
|
||||
import java.awt.Adjustable;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ToolWindowService implements LafManagerListener {
|
||||
|
||||
private static final List<SyntaxTextArea> textAreas = new ArrayList<>();
|
||||
private boolean isLandingViewVisible;
|
||||
private ScrollablePanel scrollablePanel;
|
||||
private JScrollPane scrollPane;
|
||||
private GenerateButton generateButton;
|
||||
|
||||
public void setScrollablePanel(ScrollablePanel scrollablePanel) {
|
||||
this.scrollablePanel = scrollablePanel;
|
||||
}
|
||||
|
||||
public void setScrollPane(JScrollPane scrollPane) {
|
||||
this.scrollPane = scrollPane;
|
||||
}
|
||||
|
||||
public void setGenerateButton(GenerateButton generateButton) {
|
||||
this.generateButton = generateButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lookAndFeelChanged(@NotNull LafManager source) {
|
||||
for (var textArea : textAreas) {
|
||||
textArea.changeStyleViaThemeXml();
|
||||
}
|
||||
}
|
||||
|
||||
public ToolWindow getToolWindow(@NotNull Project project) {
|
||||
return ToolWindowManager.getInstance(project).getToolWindow("CodeGPT");
|
||||
}
|
||||
|
||||
public void paintUserMessage(String userMessage) {
|
||||
if (isLandingViewVisible || ConversationsState.getCurrentConversation() == null) {
|
||||
removeAll();
|
||||
}
|
||||
addSpacing(8);
|
||||
addIconLabel(AllIcons.General.User, "User:");
|
||||
addSpacing(8);
|
||||
scrollablePanel.add(createTextArea(userMessage));
|
||||
}
|
||||
|
||||
public void sendMessage(String prompt, Project project, @Nullable Runnable scrollToBottom) {
|
||||
addSpacing(8);
|
||||
addIconLabel(Icons.DefaultImageIcon, "ChatGPT:");
|
||||
addSpacing(8);
|
||||
|
||||
var settings = SettingsState.getInstance();
|
||||
if (settings.isGPTOptionSelected && settings.apiKey.isEmpty()) {
|
||||
notifyMissingCredential(project, "API key not provided.");
|
||||
} else if (settings.isChatGPTOptionSelected && settings.accessToken.isEmpty()) {
|
||||
notifyMissingCredential(project, "Access token not provided.");
|
||||
} else {
|
||||
var textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN);
|
||||
scrollablePanel.add(textArea);
|
||||
textAreas.add(textArea);
|
||||
|
||||
var client = new ClientFactory().getClient();
|
||||
generateButton.setVisible(true);
|
||||
generateButton.setMode(Mode.STOP, client::cancelRequest);
|
||||
|
||||
var conversationMessage = new Message();
|
||||
conversationMessage.setPrompt(prompt);
|
||||
new SwingWorker<Void, String>() {
|
||||
protected Void doInBackground() {
|
||||
client.getCompletionsAsync(
|
||||
prompt,
|
||||
this::publish,
|
||||
(completedConversation) -> {
|
||||
ConversationsState.getInstance().saveConversation(completedConversation);
|
||||
stopGenerating(prompt, textArea, project, scrollToBottom);
|
||||
},
|
||||
(errorMessage) -> {
|
||||
var currentConversation = ConversationsState.getCurrentConversation();
|
||||
if (currentConversation != null) {
|
||||
conversationMessage.setResponse(errorMessage);
|
||||
currentConversation.addMessage(conversationMessage);
|
||||
ConversationsState.getInstance().saveConversation(currentConversation);
|
||||
}
|
||||
textArea.append(errorMessage);
|
||||
stopGenerating(prompt, textArea, project, scrollToBottom);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void process(List<String> chunks) {
|
||||
for (String text : chunks) {
|
||||
try {
|
||||
textArea.append(text);
|
||||
conversationMessage.setResponse(textArea.getText());
|
||||
if (scrollToBottom != null) {
|
||||
scrollToBottom.run();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
textArea.append("Something went wrong. Please try again later.");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public void displayConversation(Conversation conversation) {
|
||||
removeAll();
|
||||
conversation.getMessages().forEach(message -> {
|
||||
paintUserMessage(message.getPrompt());
|
||||
|
||||
addSpacing(8);
|
||||
addIconLabel(Icons.DefaultImageIcon, "ChatGPT:");
|
||||
addSpacing(8);
|
||||
|
||||
var textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN);
|
||||
textArea.setText(message.getResponse());
|
||||
textArea.displayCopyButton();
|
||||
textArea.hideCaret();
|
||||
scrollablePanel.add(textArea);
|
||||
textAreas.add(textArea);
|
||||
});
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
public void paintLandingView() {
|
||||
isLandingViewVisible = true;
|
||||
|
||||
var imageIconPanel = new JPanel();
|
||||
imageIconPanel.setLayout(new GridBagLayout());
|
||||
var imageIconLabel = new JLabel(Icons.SunImageIcon);
|
||||
imageIconLabel.setHorizontalAlignment(JLabel.CENTER);
|
||||
imageIconPanel.add(imageIconLabel);
|
||||
scrollablePanel.add(imageIconPanel);
|
||||
|
||||
addSpacing(16);
|
||||
|
||||
var questions = List.of("How do I make an HTTP request in Javascript?",
|
||||
"What is the difference between px, dip, dp, and sp?",
|
||||
"How do I undo the most recent local commits in Git?",
|
||||
"What is the difference between stack and heap?");
|
||||
for (var question : questions) {
|
||||
var panel = new JPanel();
|
||||
panel.setLayout(new GridBagLayout());
|
||||
var label = new JLabel(question, SwingConstants.CENTER);
|
||||
label.setHorizontalAlignment(JLabel.CENTER);
|
||||
panel.add(label);
|
||||
scrollablePanel.add(panel);
|
||||
addSpacing(16);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
isLandingViewVisible = false;
|
||||
generateButton.setVisible(false);
|
||||
scrollablePanel.removeAll();
|
||||
}
|
||||
|
||||
private void stopGenerating(String prompt, SyntaxTextArea textArea, Project project, @Nullable Runnable scrollToBottom) {
|
||||
generateButton.setMode(Mode.REFRESH, () -> {
|
||||
sendMessage(prompt, project, scrollToBottom);
|
||||
if (scrollToBottom != null) {
|
||||
scrollToBottom.run();
|
||||
}
|
||||
});
|
||||
textArea.displayCopyButton();
|
||||
textArea.hideCaret();
|
||||
if (scrollToBottom != null) {
|
||||
scrollToBottom.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void addSpacing(int height) {
|
||||
scrollablePanel.add(Box.createVerticalStrut(height));
|
||||
}
|
||||
|
||||
private void addIconLabel(Icon icon, String text) {
|
||||
scrollablePanel.add(justifyLeft(createIconLabel(icon, text)));
|
||||
}
|
||||
|
||||
private void notifyMissingCredential(Project project, String text) {
|
||||
var label = new JLabel(format("<html>%s <font color='#589df6'><u>Open Settings</u></font> to set one.</html>", text));
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(project, SettingsConfigurable.class);
|
||||
}
|
||||
});
|
||||
scrollablePanel.add(justifyLeft(label));
|
||||
}
|
||||
|
||||
private void scrollToBottom() {
|
||||
JScrollBar verticalBar = scrollPane.getVerticalScrollBar();
|
||||
verticalBar.addAdjustmentListener(new AdjustmentListener() {
|
||||
public void adjustmentValueChanged(AdjustmentEvent e) {
|
||||
Adjustable adjustable = e.getAdjustable();
|
||||
adjustable.setValue(adjustable.getMaximum());
|
||||
verticalBar.removeAdjustmentListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
public class ApiRequestDetails {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
public interface BaseApiResponse {
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
public enum BaseModel {
|
||||
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.util.Map;
|
||||
|
|
@ -73,12 +72,11 @@ public abstract class Client {
|
|||
var username = settings.proxyUsername;
|
||||
var password = settings.proxyPassword;
|
||||
if (settings.isProxyAuthSelected) {
|
||||
builder.proxyAuthenticator((route, response) -> {
|
||||
String credential = Credentials.basic(username, password);
|
||||
return response.request().newBuilder()
|
||||
.header("Proxy-Authorization", credential)
|
||||
.build();
|
||||
});
|
||||
builder.proxyAuthenticator((route, response) ->
|
||||
response.request()
|
||||
.newBuilder()
|
||||
.header("Proxy-Authorization", Credentials.basic(username, password))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
public enum ClientCode {
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package ee.carlrobert.chatgpt.client;
|
||||
package ee.carlrobert.codegpt.client;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.unofficial.UnofficialChatGPTClient;
|
||||
import ee.carlrobert.chatgpt.client.official.chat.ChatCompletionClient;
|
||||
import ee.carlrobert.chatgpt.client.official.text.TextCompletionClient;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.client.unofficial.UnofficialChatGPTClient;
|
||||
import ee.carlrobert.codegpt.client.official.chat.ChatCompletionClient;
|
||||
import ee.carlrobert.codegpt.client.official.text.TextCompletionClient;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
|
||||
public class ClientFactory {
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package ee.carlrobert.codegpt.client.official;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseError {
|
||||
|
||||
private final ErrorDetails error;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseError(@JsonProperty("error") ErrorDetails error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public ErrorDetails getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static class ErrorDetails {
|
||||
private final String message;
|
||||
private final String type;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ErrorDetails(@JsonProperty("message") String message, @JsonProperty("type") String type) {
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client.official;
|
||||
package ee.carlrobert.codegpt.client.official;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat;
|
||||
package ee.carlrobert.codegpt.client.official.chat;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.chatgpt.client.Client;
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.chatgpt.client.official.chat.request.ApiRequest;
|
||||
import ee.carlrobert.chatgpt.client.official.chat.request.ApiRequestMessage;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.codegpt.client.Client;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.client.official.chat.request.ApiRequest;
|
||||
import ee.carlrobert.codegpt.client.official.chat.request.ApiRequestMessage;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
|
@ -54,8 +54,7 @@ public class ChatCompletionClient extends Client {
|
|||
Consumer<Conversation> onComplete,
|
||||
Consumer<String> onFailure) {
|
||||
return new ChatCompletionClientEventListener(client, onMessageReceived, finalMessage -> {
|
||||
var message = new Message();
|
||||
message.setPrompt(prompt);
|
||||
var message = new Message(prompt);
|
||||
message.setResponse(finalMessage);
|
||||
conversation.setUpdatedOn(LocalDateTime.now());
|
||||
conversation.addMessage(message);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat;
|
||||
package ee.carlrobert.codegpt.client.official.chat;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ee.carlrobert.chatgpt.client.official.CompletionClientEventListener;
|
||||
import ee.carlrobert.chatgpt.client.official.chat.response.ApiResponse;
|
||||
import ee.carlrobert.codegpt.client.official.CompletionClientEventListener;
|
||||
import ee.carlrobert.codegpt.client.official.chat.response.ApiResponse;
|
||||
import java.util.function.Consumer;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat.request;
|
||||
package ee.carlrobert.codegpt.client.official.chat.request;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.client.official.chat.request;
|
||||
package ee.carlrobert.codegpt.client.official.chat.request;
|
||||
|
||||
public class ApiRequestMessage {
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package ee.carlrobert.codegpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import ee.carlrobert.codegpt.client.BaseApiResponse;
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponse implements BaseApiResponse {
|
||||
|
||||
private final String id;
|
||||
private final List<ApiResponseChoice> choices;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponse(
|
||||
@JsonProperty("id") String id,
|
||||
@JsonProperty("choices") List<ApiResponseChoice> choices) {
|
||||
this.id = id;
|
||||
this.choices = choices;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<ApiResponseChoice> getChoices() {
|
||||
return choices;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package ee.carlrobert.codegpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseChoice {
|
||||
|
||||
private final ApiResponseChoiceDelta delta;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseChoice(@JsonProperty("delta") ApiResponseChoiceDelta delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
public ApiResponseChoiceDelta getDelta() {
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package ee.carlrobert.codegpt.client.official.chat.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseChoiceDelta {
|
||||
|
||||
private final String role;
|
||||
private final String content;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseChoiceDelta(
|
||||
@JsonProperty("role") String role,
|
||||
@JsonProperty("content") String content) {
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
package ee.carlrobert.chatgpt.client.official.text;
|
||||
package ee.carlrobert.codegpt.client.official.text;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.chatgpt.client.BaseModel;
|
||||
import ee.carlrobert.chatgpt.client.Client;
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.codegpt.client.BaseModel;
|
||||
import ee.carlrobert.codegpt.client.Client;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -53,11 +53,8 @@ public class TextCompletionClient extends Client {
|
|||
Consumer<Conversation> onComplete,
|
||||
Consumer<String> onFailure) {
|
||||
return new TextCompletionClientEventListener(client, onMessageReceived, (finalMessage) -> {
|
||||
var message = new Message();
|
||||
message.setPrompt(prompt);
|
||||
message.setResponse(finalMessage);
|
||||
conversation.setUpdatedOn(LocalDateTime.now());
|
||||
conversation.addMessage(message);
|
||||
conversation.addMessage(new Message(prompt, finalMessage));
|
||||
onComplete.accept(conversation);
|
||||
}, onFailure);
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package ee.carlrobert.chatgpt.client.official.text;
|
||||
package ee.carlrobert.codegpt.client.official.text;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ee.carlrobert.chatgpt.client.official.CompletionClientEventListener;
|
||||
import ee.carlrobert.chatgpt.client.official.text.response.ApiResponse;
|
||||
import ee.carlrobert.codegpt.client.official.CompletionClientEventListener;
|
||||
import ee.carlrobert.codegpt.client.official.text.response.ApiResponse;
|
||||
import java.util.function.Consumer;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ee.carlrobert.codegpt.client.official.text.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import ee.carlrobert.codegpt.client.BaseApiResponse;
|
||||
import java.util.List;
|
||||
|
||||
// TODO: BaseCompletionApiResponse / CompletionApiResponse
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponse implements BaseApiResponse {
|
||||
|
||||
private final String id;
|
||||
private final List<ApiResponseChoice> choices;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponse(
|
||||
@JsonProperty("id") String id,
|
||||
@JsonProperty("choices") List<ApiResponseChoice> choices) {
|
||||
this.id = id;
|
||||
this.choices = choices;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<ApiResponseChoice> getChoices() {
|
||||
return choices;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,28 @@
|
|||
package ee.carlrobert.chatgpt.client.official.text.response;
|
||||
package ee.carlrobert.codegpt.client.official.text.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseChoice {
|
||||
|
||||
private String text;
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
private final String text;
|
||||
private final String finishReason;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseChoice(
|
||||
@JsonProperty("text") String text,
|
||||
@JsonProperty("finish_reason") String finishReason) {
|
||||
this.text = text;
|
||||
this.finishReason = finishReason;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getFinishReason() {
|
||||
return finishReason;
|
||||
}
|
||||
|
||||
public void setFinishReason(String finishReason) {
|
||||
this.finishReason = finishReason;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial;
|
||||
package ee.carlrobert.codegpt.client.unofficial;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.chatgpt.client.Client;
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.client.ApiRequestDetails;
|
||||
import ee.carlrobert.codegpt.client.Client;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -34,8 +34,7 @@ public class UnofficialChatGPTClient extends Client {
|
|||
Consumer<Conversation> onComplete,
|
||||
Consumer<String> onFailure) {
|
||||
return new UnofficialClientEventListener(client, prompt, onMessageReceived, (response) -> {
|
||||
var message = new Message();
|
||||
message.setPrompt(prompt);
|
||||
var message = new Message(prompt);
|
||||
message.setResponse(response.getFullMessage());
|
||||
|
||||
conversation.setUnofficialClientConversationId(response.getConversationId());
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial;
|
||||
package ee.carlrobert.codegpt.client.unofficial;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ee.carlrobert.chatgpt.client.unofficial.response.ApiResponse;
|
||||
import ee.carlrobert.codegpt.client.unofficial.response.ApiResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
|
@ -13,13 +13,16 @@ import javax.annotation.Nullable;
|
|||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.sse.EventSource;
|
||||
import okhttp3.sse.EventSourceListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnofficialClientEventListener extends EventSourceListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UnofficialClientEventListener.class);
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final String prompt;
|
||||
private final Consumer<String> onMessageReceived;
|
||||
|
|
@ -47,14 +50,12 @@ public class UnofficialClientEventListener extends EventSourceListener {
|
|||
|
||||
public void onClosed(@NotNull EventSource eventSource) {
|
||||
if (!eventReceived) {
|
||||
var client = UnofficialChatGPTClient.getInstance().buildClient();
|
||||
var clientInstance = UnofficialChatGPTClient.getInstance();
|
||||
try {
|
||||
var response = client.newCall(UnofficialChatGPTClient.getInstance().buildHttpRequest(prompt)).execute();
|
||||
ResponseBody responseBody = response.body();
|
||||
if (responseBody != null) {
|
||||
tryExtractingErrorMessage(responseBody.string()).ifPresent(onFailure);
|
||||
responseBody.close();
|
||||
}
|
||||
var response = clientInstance.buildClient()
|
||||
.newCall(clientInstance.buildHttpRequest(prompt))
|
||||
.execute();
|
||||
tryExtractingErrorResponse(response);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -97,11 +98,7 @@ public class UnofficialClientEventListener extends EventSourceListener {
|
|||
@Nullable Response response) {
|
||||
if (isRequestNotCancelled() && response != null) {
|
||||
try {
|
||||
var responseBody = response.body();
|
||||
if (responseBody != null) {
|
||||
tryExtractingErrorMessage(responseBody.string()).ifPresent(onFailure);
|
||||
responseBody.close();
|
||||
}
|
||||
tryExtractingErrorResponse(response);
|
||||
} catch (Exception e) {
|
||||
onFailure.accept("Something went wrong. Please try again later.");
|
||||
}
|
||||
|
|
@ -114,6 +111,18 @@ public class UnofficialClientEventListener extends EventSourceListener {
|
|||
return client.dispatcher().runningCalls().stream().noneMatch(Call::isCanceled);
|
||||
}
|
||||
|
||||
private void tryExtractingErrorResponse(Response response) {
|
||||
try (response) {
|
||||
var responseBody = response.body();
|
||||
if (responseBody != null) {
|
||||
tryExtractingErrorMessage(responseBody.string()).ifPresent(onFailure);
|
||||
responseBody.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> tryExtractingErrorMessage(String jsonPayload) {
|
||||
try {
|
||||
var error = objectMapper.readValue(jsonPayload, Map.class);
|
||||
|
|
@ -1,32 +1,32 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
package ee.carlrobert.codegpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import ee.carlrobert.chatgpt.client.BaseApiResponse;
|
||||
import ee.carlrobert.codegpt.client.BaseApiResponse;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponse implements BaseApiResponse {
|
||||
|
||||
private ApiResponseMessage message;
|
||||
@JsonProperty("conversation_id")
|
||||
private String conversationId;
|
||||
private final ApiResponseMessage message;
|
||||
private final String conversationId;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponse(
|
||||
@JsonProperty("message") ApiResponseMessage message,
|
||||
@JsonProperty("conversation_id") String conversationId) {
|
||||
this.message = message;
|
||||
this.conversationId = conversationId;
|
||||
}
|
||||
|
||||
public ApiResponseMessage getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(ApiResponseMessage message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getConversationId() {
|
||||
return conversationId;
|
||||
}
|
||||
|
||||
public void setConversationId(String conversationId) {
|
||||
this.conversationId = conversationId;
|
||||
}
|
||||
|
||||
public String getFullMessage() {
|
||||
return String.join("", message.getContent().getParts());
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package ee.carlrobert.codegpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseMessage {
|
||||
|
||||
private final String id;
|
||||
private final ApiResponseMessageAuthor author;
|
||||
private final ApiResponseMessageContent content;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseMessage(
|
||||
@JsonProperty("id") String id,
|
||||
@JsonProperty("author") ApiResponseMessageAuthor author,
|
||||
@JsonProperty("content") ApiResponseMessageContent content) {
|
||||
this.id = id;
|
||||
this.author = author;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ApiResponseMessageAuthor getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public ApiResponseMessageContent getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package ee.carlrobert.codegpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseMessageAuthor {
|
||||
|
||||
private final String role;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseMessageAuthor(@JsonProperty("role") String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,26 @@
|
|||
package ee.carlrobert.chatgpt.client.unofficial.response;
|
||||
package ee.carlrobert.codegpt.client.unofficial.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ApiResponseMessageContent {
|
||||
|
||||
@JsonProperty("content_type")
|
||||
private String contentType;
|
||||
private List<String> parts;
|
||||
private final String contentType;
|
||||
private final List<String> parts;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public ApiResponseMessageContent(String contentType, List<String> parts) {
|
||||
this.contentType = contentType;
|
||||
this.parts = parts;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public List<String> getParts() {
|
||||
return parts;
|
||||
}
|
||||
|
||||
public void setParts(List<String> parts) {
|
||||
this.parts = parts;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ContentManagerService;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AskAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent event) {
|
||||
event.getPresentation().setEnabled(event.getProject() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
var project = event.getProject();
|
||||
if (project != null) {
|
||||
ConversationsState.getInstance().startConversation();
|
||||
ContentManagerService.getInstance(project).displayChatTab();
|
||||
|
||||
var chatToolWindow = project.getService(ToolWindowService.class).getChatToolWindow();
|
||||
chatToolWindow.show();
|
||||
chatToolWindow.clearWindow();
|
||||
chatToolWindow.displayLandingView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowService;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ContentManagerService;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class BaseAction extends AnAction {
|
||||
|
|
@ -33,25 +32,15 @@ public abstract class BaseAction extends AnAction {
|
|||
event.getPresentation().setEnabled(menuAllowed);
|
||||
}
|
||||
|
||||
protected void sendMessage(Project project, String prompt) {
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var toolWindow = toolWindowService.getToolWindow(project);
|
||||
var contentManager = toolWindow.getContentManager();
|
||||
|
||||
Arrays.stream(contentManager.getContents())
|
||||
.filter(it -> "Chat".equals(it.getTabName()))
|
||||
.findFirst()
|
||||
.ifPresentOrElse(
|
||||
contentManager::setSelectedContent,
|
||||
() -> contentManager.setSelectedContent(Objects.requireNonNull(contentManager.getContent(0)))
|
||||
);
|
||||
|
||||
protected void sendMessage(@NotNull Project project, String prompt) {
|
||||
ConversationsState.getInstance().startConversation();
|
||||
ContentManagerService.getInstance(project).displayChatTab();
|
||||
|
||||
toolWindowService.getToolWindow(project).show();
|
||||
toolWindowService.removeAll();
|
||||
toolWindowService.paintUserMessage(prompt);
|
||||
toolWindowService.sendMessage(prompt, project, null);
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var chatToolWindow = toolWindowService.getChatToolWindow();
|
||||
chatToolWindow.show();
|
||||
chatToolWindow.clearWindow();
|
||||
chatToolWindow.displayUserMessage(prompt);
|
||||
toolWindowService.sendMessage(prompt, project);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.addShiftEnterInputMap;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.addShiftEnterInputMap;
|
||||
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UI;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.components.SyntaxTextArea;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.SyntaxTextArea;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTextArea;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.action;
|
||||
package ee.carlrobert.codegpt.ide.action;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations;
|
||||
package ee.carlrobert.codegpt.ide.conversations;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.BaseModel;
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.client.BaseModel;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.ide.conversations.message.Message;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations;
|
||||
package ee.carlrobert.codegpt.ide.conversations;
|
||||
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations;
|
||||
package ee.carlrobert.codegpt.ide.conversations;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
|
|
@ -6,11 +6,11 @@ import com.intellij.openapi.components.State;
|
|||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import com.intellij.util.xmlb.annotations.OptionTag;
|
||||
import ee.carlrobert.chatgpt.client.ClientCode;
|
||||
import ee.carlrobert.chatgpt.client.ClientFactory;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.converter.ConversationConverter;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.converter.ConversationsConverter;
|
||||
import ee.carlrobert.chatgpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.client.ClientCode;
|
||||
import ee.carlrobert.codegpt.client.ClientFactory;
|
||||
import ee.carlrobert.codegpt.ide.conversations.converter.ConversationConverter;
|
||||
import ee.carlrobert.codegpt.ide.conversations.converter.ConversationsConverter;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
|
@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@State(
|
||||
name = "ee.carlrobert.chatgpt.ide.conversations.ConversationsState",
|
||||
name = "ee.carlrobert.codegpt.ide.conversations.ConversationsState",
|
||||
storages = @Storage("ChatGPTConversations.xml")
|
||||
)
|
||||
public class ConversationsState implements PersistentStateComponent<ConversationsState> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations.converter;
|
||||
package ee.carlrobert.codegpt.ide.conversations.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations.converter;
|
||||
package ee.carlrobert.codegpt.ide.conversations.converter;
|
||||
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
|
||||
public class ConversationConverter extends BaseConverter<Conversation> {
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package ee.carlrobert.chatgpt.ide.conversations.converter;
|
||||
package ee.carlrobert.codegpt.ide.conversations.converter;
|
||||
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsContainer;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsContainer;
|
||||
|
||||
public class ConversationsConverter extends BaseConverter<ConversationsContainer> {
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package ee.carlrobert.codegpt.ide.conversations.message;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class Message {
|
||||
|
||||
private final String prompt;
|
||||
private String response;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public Message(@JsonProperty("prompt") String prompt) {
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
public Message(String prompt, String response) {
|
||||
this.prompt = prompt;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public String getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(String response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package ee.carlrobert.chatgpt.ide.settings;
|
||||
package ee.carlrobert.codegpt.ide.settings;
|
||||
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import ee.carlrobert.chatgpt.client.BaseModel;
|
||||
import ee.carlrobert.codegpt.client.BaseModel;
|
||||
import java.awt.Component;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
|
|
@ -16,14 +16,8 @@ public class BaseModelComboBox extends ComboBox<BaseModel> {
|
|||
|
||||
private BasicComboBoxRenderer getBasicComboBoxRenderer() {
|
||||
return new BasicComboBoxRenderer() {
|
||||
public Component getListCellRendererComponent(
|
||||
JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, value, index,
|
||||
isSelected, cellHasFocus);
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
if (value != null) {
|
||||
BaseModel model = (BaseModel) value;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.settings;
|
||||
package ee.carlrobert.codegpt.ide.settings;
|
||||
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.ui.PortField;
|
||||
|
|
@ -10,7 +10,7 @@ import com.intellij.ui.components.JBTextField;
|
|||
import com.intellij.util.ui.FormBuilder;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UI;
|
||||
import ee.carlrobert.chatgpt.client.BaseModel;
|
||||
import ee.carlrobert.codegpt.client.BaseModel;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.io.IOException;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package ee.carlrobert.chatgpt.ide.settings;
|
||||
package ee.carlrobert.codegpt.ide.settings;
|
||||
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import javax.swing.JComponent;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
package ee.carlrobert.chatgpt.ide.settings;
|
||||
package ee.carlrobert.codegpt.ide.settings;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import ee.carlrobert.chatgpt.client.BaseModel;
|
||||
import ee.carlrobert.codegpt.client.BaseModel;
|
||||
import java.net.Proxy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@State(
|
||||
name = "ee.carlrobert.chatgpt.ide.settings.SettingsState",
|
||||
name = "ee.carlrobert.codegpt.ide.settings.SettingsState",
|
||||
storages = @Storage("CodeGPTSettings.xml")
|
||||
)
|
||||
public class SettingsState implements PersistentStateComponent<SettingsState> {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="ee.carlrobert.chatgpt.ide.toolwindow.ChatGptToolWindow">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="ee.carlrobert.codegpt.ide.toolwindow.ChatGptToolWindow">
|
||||
<grid id="27dc6" binding="chatGptToolWindowContent" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<scrollpane id="8c1de" binding="scrollPane" custom-create="true">
|
||||
<scrollpane id="8c1de" class="ee.carlrobert.codegpt.ide.toolwindow.components.ScrollPane" binding="scrollPane" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<component id="2426b" class="javax.swing.JButton" binding="generateButton" custom-create="true">
|
||||
<component id="2426b" class="ee.carlrobert.codegpt.ide.toolwindow.components.GenerateButton" binding="generateButton" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow;
|
||||
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.createIconLabel;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.createTextArea;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.justifyLeft;
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsConfigurable;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.GenerateButton;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.LandingView;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.ScrollPane;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.SyntaxTextArea;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.TextArea;
|
||||
import icons.Icons;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatGptToolWindow {
|
||||
|
||||
private static final List<SyntaxTextArea> textAreas = new ArrayList<>();
|
||||
private final Project project;
|
||||
private final ToolWindow toolWindow;
|
||||
private JPanel chatGptToolWindowContent;
|
||||
private ScrollPane scrollPane;
|
||||
private ScrollablePanel scrollablePanel;
|
||||
private JTextArea textArea;
|
||||
private JScrollPane textAreaScrollPane;
|
||||
private GenerateButton generateButton;
|
||||
private boolean isLandingViewVisible;
|
||||
|
||||
public ChatGptToolWindow(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
this.project = project;
|
||||
this.toolWindow = toolWindow;
|
||||
}
|
||||
|
||||
public JPanel getContent() {
|
||||
return chatGptToolWindowContent;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
toolWindow.show();
|
||||
}
|
||||
|
||||
public void displayUserMessage(String userMessage) {
|
||||
if (isLandingViewVisible || ConversationsState.getCurrentConversation() == null) {
|
||||
clearWindow();
|
||||
}
|
||||
|
||||
addIconLabel(AllIcons.General.User, "User:");
|
||||
scrollablePanel.add(createTextArea(userMessage));
|
||||
scrollablePanel.validate();
|
||||
scrollablePanel.repaint();
|
||||
}
|
||||
|
||||
public void displayLandingView() {
|
||||
isLandingViewVisible = true;
|
||||
clearWindow();
|
||||
|
||||
var landingView = new LandingView();
|
||||
scrollablePanel.add(landingView.createImageIconPanel());
|
||||
addSpacing(16);
|
||||
landingView.getQuestionPanels().forEach(panel -> {
|
||||
scrollablePanel.add(panel);
|
||||
addSpacing(16);
|
||||
});
|
||||
|
||||
scrollablePanel.validate();
|
||||
scrollablePanel.repaint();
|
||||
}
|
||||
|
||||
public void displayConversation(Conversation conversation) {
|
||||
clearWindow();
|
||||
|
||||
conversation.getMessages().forEach(message -> {
|
||||
displayUserMessage(message.getPrompt());
|
||||
|
||||
addIconLabel(Icons.DefaultImageIcon, "ChatGPT:");
|
||||
var textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN);
|
||||
textArea.setText(message.getResponse());
|
||||
textArea.displayCopyButton();
|
||||
textArea.hideCaret();
|
||||
scrollablePanel.add(textArea);
|
||||
textAreas.add(textArea);
|
||||
});
|
||||
|
||||
scrollToBottom();
|
||||
scrollablePanel.validate();
|
||||
scrollablePanel.repaint();
|
||||
}
|
||||
|
||||
public void displayResponse(String prompt) {
|
||||
addIconLabel(Icons.DefaultImageIcon, "ChatGPT:");
|
||||
|
||||
var settings = SettingsState.getInstance();
|
||||
if (settings.isGPTOptionSelected && settings.apiKey.isEmpty()) {
|
||||
notifyMissingCredential(project, "API key not provided.");
|
||||
} else if (settings.isChatGPTOptionSelected && settings.accessToken.isEmpty()) {
|
||||
notifyMissingCredential(project, "Access token not provided.");
|
||||
} else {
|
||||
var textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN);
|
||||
addTextArea(textArea);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearWindow() {
|
||||
isLandingViewVisible = false;
|
||||
generateButton.setVisible(false);
|
||||
scrollablePanel.removeAll();
|
||||
textAreas.clear();
|
||||
}
|
||||
|
||||
public void addSpacing(int height) {
|
||||
scrollablePanel.add(Box.createVerticalStrut(height));
|
||||
}
|
||||
|
||||
public void addIconLabel(Icon icon, String text) {
|
||||
addSpacing(8);
|
||||
scrollablePanel.add(justifyLeft(createIconLabel(icon, text)));
|
||||
addSpacing(8);
|
||||
}
|
||||
|
||||
public void notifyMissingCredential(Project project, String text) {
|
||||
var label = new JLabel(format("<html>%s <font color='#589df6'><u>Open Settings</u></font> to set one.</html>", text));
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(project, SettingsConfigurable.class);
|
||||
}
|
||||
});
|
||||
scrollablePanel.add(justifyLeft(label));
|
||||
}
|
||||
|
||||
public void displayGenerateButton(Runnable onClick) {
|
||||
generateButton.setVisible(true);
|
||||
generateButton.setMode(GenerateButton.Mode.STOP, onClick);
|
||||
}
|
||||
|
||||
public void stopGenerating(SyntaxTextArea textArea, Runnable onRefresh) {
|
||||
generateButton.setMode(GenerateButton.Mode.REFRESH, onRefresh);
|
||||
textArea.displayCopyButton();
|
||||
textArea.hideCaret();
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
public void scrollToBottom() {
|
||||
scrollPane.scrollToBottom();
|
||||
}
|
||||
|
||||
public void addTextArea(SyntaxTextArea textArea) {
|
||||
scrollablePanel.add(textArea);
|
||||
textAreas.add(textArea);
|
||||
}
|
||||
|
||||
public void changeStyle() {
|
||||
for (var textArea : textAreas) {
|
||||
textArea.changeStyleViaThemeXml();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSubmit() {
|
||||
var searchText = textArea.getText();
|
||||
|
||||
displayUserMessage(searchText);
|
||||
|
||||
displayResponse()
|
||||
project.getService(ToolWindowService.class).sendMessage(searchText, project);
|
||||
|
||||
|
||||
textArea.setText("");
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
textAreaScrollPane = new JBScrollPane() {
|
||||
public JScrollBar createVerticalScrollBar() {
|
||||
JScrollBar verticalScrollBar = new JScrollPane.ScrollBar(1);
|
||||
verticalScrollBar.setPreferredSize(new Dimension(0, 0));
|
||||
return verticalScrollBar;
|
||||
}
|
||||
};
|
||||
textAreaScrollPane.setBorder(null);
|
||||
textAreaScrollPane.setViewportBorder(null);
|
||||
textAreaScrollPane.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createMatteBorder(1, 0, 0, 0, JBColor.border()),
|
||||
BorderFactory.createEmptyBorder(0, 5, 0, 10)));
|
||||
textAreaScrollPane.setViewportView(textArea);
|
||||
|
||||
textArea = new TextArea(this::handleSubmit, textAreaScrollPane);
|
||||
|
||||
scrollablePanel = new ScrollablePanel();
|
||||
scrollablePanel.setLayout(new BoxLayout(scrollablePanel, BoxLayout.Y_AXIS));
|
||||
|
||||
scrollPane = new ScrollPane(scrollablePanel);
|
||||
generateButton = new GenerateButton();
|
||||
|
||||
displayLandingView();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow;
|
||||
|
||||
public class ChatToolWindowContent {
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import javax.swing.JPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ContentManagerService {
|
||||
|
||||
private static ContentManagerService instance;
|
||||
private final ContentManager contentManager;
|
||||
|
||||
private ContentManagerService(Project project) {
|
||||
this.contentManager = requireNonNull(ToolWindowManager.getInstance(project).getToolWindow("CodeGPT")).getContentManager();
|
||||
}
|
||||
|
||||
public static ContentManagerService getInstance(@NotNull Project project) {
|
||||
if (instance == null) {
|
||||
instance = new ContentManagerService(project);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void addContent(JPanel content, String displayName) {
|
||||
contentManager.addContent(ApplicationManager.getApplication()
|
||||
.getService(ContentFactory.class)
|
||||
.createContent(content, displayName, false));
|
||||
}
|
||||
|
||||
public void displayChatTab() {
|
||||
tryFindChatTabContent().ifPresentOrElse(
|
||||
contentManager::setSelectedContent,
|
||||
() -> contentManager.setSelectedContent(requireNonNull(contentManager.getContent(0)))
|
||||
);
|
||||
}
|
||||
|
||||
public Optional<Content> tryFindChatTabContent() {
|
||||
return Arrays.stream(contentManager.getContents())
|
||||
.filter(content -> "Chat".equals(content.getTabName()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public boolean isChatTabSelected() {
|
||||
return tryFindChatTabContent()
|
||||
.filter(contentManager::isSelected)
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow;
|
||||
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowFactory;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.ui.content.ContentManagerListener;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.conversations.ConversationsToolWindow;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ProjectToolWindowFactory implements ToolWindowFactory, DumbAware {
|
||||
|
||||
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var chatToolWindow = new ChatGptToolWindow(project, toolWindow);
|
||||
var conversationsToolWindow = new ConversationsToolWindow(project);
|
||||
toolWindowService.setChatToolWindow(chatToolWindow);
|
||||
|
||||
var contentManagerService = ContentManagerService.getInstance(project);
|
||||
contentManagerService.addContent(chatToolWindow.getContent(), "Chat");
|
||||
contentManagerService.addContent(conversationsToolWindow.getContent(), "Conversation History");
|
||||
toolWindow.addContentManagerListener(new ContentManagerListener() {
|
||||
public void selectionChanged(@NotNull ContentManagerEvent event) {
|
||||
var content = event.getContent();
|
||||
if ("Conversation History".equals(content.getTabName()) && content.isSelected()) {
|
||||
conversationsToolWindow.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
displayRecentConversationIfPresent(toolWindowService, contentManagerService.isChatTabSelected());
|
||||
}
|
||||
|
||||
private void displayRecentConversationIfPresent(ToolWindowService toolWindowService, boolean isChatTabSelected) {
|
||||
var conversation = ConversationsState.getCurrentConversation();
|
||||
if (conversation != null) {
|
||||
if (isChatTabSelected) {
|
||||
toolWindowService.getChatToolWindow().displayConversation(conversation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow;
|
||||
|
||||
import com.intellij.ide.ui.LafManager;
|
||||
import com.intellij.ide.ui.LafManagerListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import ee.carlrobert.codegpt.client.ClientFactory;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.ide.settings.SettingsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.components.SyntaxTextArea;
|
||||
import icons.Icons;
|
||||
import java.util.List;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ToolWindowService implements LafManagerListener {
|
||||
|
||||
private ChatGptToolWindow chatToolWindow;
|
||||
|
||||
@Override
|
||||
public void lookAndFeelChanged(@NotNull LafManager source) {
|
||||
chatToolWindow.changeStyle();
|
||||
}
|
||||
|
||||
public void setChatToolWindow(ChatGptToolWindow chatToolWindow) {
|
||||
this.chatToolWindow = chatToolWindow;
|
||||
}
|
||||
|
||||
public ChatGptToolWindow getChatToolWindow() {
|
||||
return chatToolWindow;
|
||||
}
|
||||
|
||||
public void startRequest(String prompt, SyntaxTextArea textArea, Project project) {
|
||||
var client = new ClientFactory().getClient();
|
||||
chatToolWindow.displayGenerateButton(client::cancelRequest);
|
||||
|
||||
var conversationMessage = new Message(prompt);
|
||||
new SwingWorker<Void, String>() {
|
||||
protected Void doInBackground() {
|
||||
client.getCompletionsAsync(
|
||||
prompt,
|
||||
this::publish,
|
||||
(completedConversation) -> {
|
||||
ConversationsState.getInstance().saveConversation(completedConversation);
|
||||
stopGenerating(prompt, textArea, project);
|
||||
},
|
||||
(errorMessage) -> {
|
||||
var currentConversation = ConversationsState.getCurrentConversation();
|
||||
if (currentConversation != null) {
|
||||
conversationMessage.setResponse(errorMessage);
|
||||
currentConversation.addMessage(conversationMessage);
|
||||
ConversationsState.getInstance().saveConversation(currentConversation);
|
||||
}
|
||||
textArea.append(errorMessage);
|
||||
stopGenerating(prompt, textArea, project);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void process(List<String> chunks) {
|
||||
for (String text : chunks) {
|
||||
try {
|
||||
textArea.append(text);
|
||||
conversationMessage.setResponse(textArea.getText());
|
||||
chatToolWindow.scrollToBottom();
|
||||
} catch (Exception e) {
|
||||
textArea.append("Something went wrong. Please try again later.");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
public void sendMessage(String prompt, Project project) {
|
||||
chatToolWindow.addIconLabel(Icons.DefaultImageIcon, "ChatGPT:");
|
||||
|
||||
var settings = SettingsState.getInstance();
|
||||
if (settings.isGPTOptionSelected && settings.apiKey.isEmpty()) {
|
||||
chatToolWindow.notifyMissingCredential(project, "API key not provided.");
|
||||
} else if (settings.isChatGPTOptionSelected && settings.accessToken.isEmpty()) {
|
||||
chatToolWindow.notifyMissingCredential(project, "Access token not provided.");
|
||||
} else {
|
||||
var textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN);
|
||||
chatToolWindow.addTextArea(textArea);
|
||||
startRequest(prompt, textArea, project);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopGenerating(String prompt, SyntaxTextArea textArea, Project project) {
|
||||
chatToolWindow.stopGenerating(textArea, () -> {
|
||||
sendMessage(prompt, project);
|
||||
chatToolWindow.scrollToBottom();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.components;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.components;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import javax.swing.JButton;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import icons.Icons;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.util.List;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
public class LandingView {
|
||||
|
||||
private static final List<String> questions = List.of("How do I make an HTTP request in Javascript?",
|
||||
"What is the difference between px, dip, dp, and sp?",
|
||||
"How do I undo the most recent local commits in Git?",
|
||||
"What is the difference between stack and heap?");
|
||||
|
||||
public List<JPanel> getQuestionPanels() {
|
||||
return questions.stream()
|
||||
.map(this::createQuestionPanel)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public JPanel createImageIconPanel() {
|
||||
var imageIconPanel = new JPanel();
|
||||
imageIconPanel.setLayout(new GridBagLayout());
|
||||
var imageIconLabel = new JLabel(Icons.SunImageIcon);
|
||||
imageIconLabel.setHorizontalAlignment(JLabel.CENTER);
|
||||
imageIconPanel.add(imageIconLabel);
|
||||
return imageIconPanel;
|
||||
}
|
||||
|
||||
private JPanel createQuestionPanel(String question) {
|
||||
var panel = new JPanel();
|
||||
panel.setLayout(new GridBagLayout());
|
||||
var label = new JLabel(question, SwingConstants.CENTER);
|
||||
label.setHorizontalAlignment(JLabel.CENTER);
|
||||
panel.add(label);
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import java.awt.Adjustable;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
|
||||
public class ScrollPane extends JBScrollPane {
|
||||
|
||||
public ScrollPane(ScrollablePanel scrollablePanel) {
|
||||
super(scrollablePanel);
|
||||
setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
setBorder(JBUI.Borders.empty(0, 8));
|
||||
setViewportBorder(null);
|
||||
}
|
||||
|
||||
public void scrollToBottom() {
|
||||
JScrollBar verticalBar = getVerticalScrollBar();
|
||||
verticalBar.addAdjustmentListener(new AdjustmentListener() {
|
||||
public void adjustmentValueChanged(AdjustmentEvent e) {
|
||||
Adjustable adjustable = e.getAdjustable();
|
||||
adjustable.setValue(adjustable.getMaximum());
|
||||
verticalBar.removeAdjustmentListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import com.intellij.ui.JBColor;
|
||||
import java.awt.Component;
|
||||
|
|
@ -14,7 +14,7 @@ import javax.swing.JLabel;
|
|||
import javax.swing.JTextArea;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
public class ToolWindowUtil {
|
||||
public class SwingUtils {
|
||||
|
||||
public static JTextArea createTextArea(String selectedText) {
|
||||
var textArea = new JTextArea();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.components;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.createIconButton;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.createIconButton;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.components;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.components;
|
||||
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.addShiftEnterInputMap;
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.createIconButton;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.addShiftEnterInputMap;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.createIconButton;
|
||||
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBTextArea;
|
||||
|
|
@ -39,7 +39,6 @@ public class TextArea extends JBTextArea {
|
|||
|
||||
private FocusListener getFocusListener() {
|
||||
return new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (getText().equals("Ask me anything...")) {
|
||||
setText("");
|
||||
|
|
@ -47,7 +46,6 @@ public class TextArea extends JBTextArea {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (getText().isEmpty()) {
|
||||
setForeground(JBColor.GRAY);
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.conversations;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.conversations;
|
||||
|
||||
import static ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowUtil.justifyLeft;
|
||||
import static ee.carlrobert.codegpt.ide.toolwindow.components.SwingUtils.justifyLeft;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="ee.carlrobert.chatgpt.ide.toolwindow.conversations.ConversationsToolWindow">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="ee.carlrobert.codegpt.ide.toolwindow.conversations.ConversationsToolWindow">
|
||||
<grid id="27dc6" binding="conversationsToolWindowContent" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.conversations;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.conversations;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.chatgpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowService;
|
||||
import java.util.Arrays;
|
||||
import ee.carlrobert.codegpt.ide.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.ide.conversations.ConversationsState;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ContentManagerService;
|
||||
import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
|
@ -19,14 +17,12 @@ import org.jetbrains.annotations.NotNull;
|
|||
public class ConversationsToolWindow {
|
||||
|
||||
private final Project project;
|
||||
private final ToolWindow toolWindow;
|
||||
private JPanel conversationsToolWindowContent;
|
||||
private JScrollPane scrollPane;
|
||||
private ScrollablePanel scrollablePanel;
|
||||
|
||||
public ConversationsToolWindow(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
public ConversationsToolWindow(@NotNull Project project) {
|
||||
this.project = project;
|
||||
this.toolWindow = toolWindow;
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
|
@ -47,17 +43,10 @@ public class ConversationsToolWindow {
|
|||
private void addContent(Conversation conversation) {
|
||||
var mainPanel = new RootConversationPanel(() -> {
|
||||
ConversationsState.getInstance().setCurrentConversation(conversation);
|
||||
|
||||
var toolWindowService = project.getService(ToolWindowService.class);
|
||||
var contentManager = toolWindow.getContentManager();
|
||||
Arrays.stream(contentManager.getContents())
|
||||
.filter(content -> "Chat".equals(content.getTabName()))
|
||||
.findFirst()
|
||||
.ifPresentOrElse(
|
||||
contentManager::setSelectedContent,
|
||||
() -> contentManager.setSelectedContent(Objects.requireNonNull(contentManager.getContent(0)))
|
||||
);
|
||||
toolWindowService.displayConversation(conversation);
|
||||
ContentManagerService.getInstance(project).displayChatTab();
|
||||
project.getService(ToolWindowService.class)
|
||||
.getChatToolWindow()
|
||||
.displayConversation(conversation);
|
||||
});
|
||||
|
||||
var currentConversation = ConversationsState.getCurrentConversation();
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ee.carlrobert.chatgpt.ide.toolwindow.conversations;
|
||||
package ee.carlrobert.codegpt.ide.toolwindow.conversations;
|
||||
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<idea-plugin>
|
||||
<id>ee.carlrobert.chatgpt</id>
|
||||
<id>ee.carlrobert.codegpt</id>
|
||||
<name>CodeGPT</name>
|
||||
<vendor email="carlrobertoh@gmail.com" url="https://carlrobert.ee">Carl-Robert Linnupuu</vendor>
|
||||
<description><![CDATA[
|
||||
|
|
@ -102,34 +102,34 @@
|
|||
|
||||
<projectListeners>
|
||||
<listener
|
||||
class="ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowService"
|
||||
class="ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService"
|
||||
topic="com.intellij.ide.ui.LafManagerListener"/>
|
||||
</projectListeners>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationConfigurable id="settings.codegpt" parentId="tools" displayName="CodeGPT"
|
||||
instance="ee.carlrobert.chatgpt.ide.settings.SettingsConfigurable"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.chatgpt.ide.settings.SettingsState"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.chatgpt.ide.conversations.ConversationsState"/>
|
||||
<projectService serviceImplementation="ee.carlrobert.chatgpt.ide.toolwindow.ToolWindowService"/>
|
||||
instance="ee.carlrobert.codegpt.ide.settings.SettingsConfigurable"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.ide.settings.SettingsState"/>
|
||||
<applicationService serviceImplementation="ee.carlrobert.codegpt.ide.conversations.ConversationsState"/>
|
||||
<projectService serviceImplementation="ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService"/>
|
||||
<toolWindow id="CodeGPT" icon="Icons.ToolWindowIcon" anchor="right"
|
||||
factoryClass="ee.carlrobert.chatgpt.ide.toolwindow.ChatGptToolWindowFactory"/>
|
||||
factoryClass="ee.carlrobert.codegpt.ide.toolwindow.ProjectToolWindowFactory"/>
|
||||
</extensions>
|
||||
|
||||
<resource-bundle>messages.BasicActionsBundle</resource-bundle>
|
||||
|
||||
<actions>
|
||||
<group id="CodeGPTEditorPopup">
|
||||
<group id="ActionGroup" class="ee.carlrobert.chatgpt.ide.action.ActionGroup" popup="true" icon="Icons.DefaultIcon">
|
||||
<action id="AskAction" class="ee.carlrobert.chatgpt.ide.action.AskAction" icon="AllIcons.Actions.Find"/>
|
||||
<group id="ActionGroup" class="com.intellij.openapi.actionSystem.DefaultActionGroup" popup="true" icon="Icons.DefaultIcon">
|
||||
<action id="AskAction" class="ee.carlrobert.codegpt.ide.action.AskAction" icon="AllIcons.Actions.Find"/>
|
||||
<separator/>
|
||||
<action id="CustomPromptAction" class="ee.carlrobert.chatgpt.ide.action.CustomPromptAction" icon="AllIcons.Actions.Run_anything"/>
|
||||
<action id="CustomPromptAction" class="ee.carlrobert.codegpt.ide.action.CustomPromptAction" icon="AllIcons.Actions.Run_anything"/>
|
||||
<separator/>
|
||||
<action id="WriteTestsAction" class="ee.carlrobert.chatgpt.ide.action.WriteTestsAction"/>
|
||||
<action id="FindBugsAction" class="ee.carlrobert.chatgpt.ide.action.FindBugsAction"/>
|
||||
<action id="RefactorAction" class="ee.carlrobert.chatgpt.ide.action.RefactorAction"/>
|
||||
<action id="OptimizeAction" class="ee.carlrobert.chatgpt.ide.action.OptimizeAction"/>
|
||||
<action id="ExplainAction" class="ee.carlrobert.chatgpt.ide.action.ExplainAction"/>
|
||||
<action id="WriteTestsAction" class="ee.carlrobert.codegpt.ide.action.WriteTestsAction"/>
|
||||
<action id="FindBugsAction" class="ee.carlrobert.codegpt.ide.action.FindBugsAction"/>
|
||||
<action id="RefactorAction" class="ee.carlrobert.codegpt.ide.action.RefactorAction"/>
|
||||
<action id="OptimizeAction" class="ee.carlrobert.codegpt.ide.action.OptimizeAction"/>
|
||||
<action id="ExplainAction" class="ee.carlrobert.codegpt.ide.action.ExplainAction"/>
|
||||
</group>
|
||||
<add-to-group group-id="EditorPopupMenu1" anchor="first"/>
|
||||
<separator/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue