feat: add support for configuring code completions via settings

This commit is contained in:
Carl-Robert Linnupuu 2024-04-03 01:04:22 +03:00
parent 2b98b65210
commit f0172722c7
17 changed files with 198 additions and 139 deletions

View file

@ -1,26 +0,0 @@
package ee.carlrobert.codegpt.actions;
import com.intellij.util.messages.Topic;
import com.intellij.util.messages.Topic.BroadcastDirection;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationState;
import java.util.EventListener;
/**
* {@link EventListener} for changes of {@link ConfigurationState#isCodeCompletionsEnabled()}.
*
* @see EnableCompletionsAction
* @see DisableCompletionsAction
*/
public interface CodeCompletionEnabledListener extends EventListener {
/**
* Topic for subscribing to {@link ConfigurationState#isCodeCompletionsEnabled()} changes.<br/>
* Broadcasts from Application-Level to all projects.
*/
@Topic.AppLevel
Topic<CodeCompletionEnabledListener> TOPIC = new Topic<>(CodeCompletionEnabledListener.class,
BroadcastDirection.TO_DIRECT_CHILDREN);
void onCodeCompletionsEnabledChange(boolean codeCompletionsEnabled);
}

View file

@ -1,41 +0,0 @@
package ee.carlrobert.codegpt.actions;
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import java.util.List;
import org.jetbrains.annotations.NotNull;
/**
* Disables code-completion.<br/> Publishes message to {@link CodeCompletionEnabledListener#TOPIC}
*/
public class DisableCompletionsAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
ConfigurationSettings.getCurrentState().setCodeCompletionsEnabled(false);
ApplicationManager.getApplication()
.getMessageBus().syncPublisher(CodeCompletionEnabledListener.TOPIC)
.onCodeCompletionsEnabledChange(false);
}
@Override
public void update(@NotNull AnActionEvent e) {
var selectedService = GeneralSettings.getCurrentState().getSelectedService();
var codeCompletionEnabled = ConfigurationSettings.getCurrentState().isCodeCompletionsEnabled();
e.getPresentation().setEnabled(codeCompletionEnabled);
e.getPresentation()
.setVisible(codeCompletionEnabled && List.of(OPENAI, LLAMA_CPP).contains(selectedService));
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}
}

View file

@ -1,41 +0,0 @@
package ee.carlrobert.codegpt.actions;
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import java.util.List;
import org.jetbrains.annotations.NotNull;
/**
* Enables code-completion.<br/> Publishes message to {@link CodeCompletionEnabledListener#TOPIC}
*/
public class EnableCompletionsAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
ConfigurationSettings.getCurrentState().setCodeCompletionsEnabled(true);
ApplicationManager.getApplication()
.getMessageBus().syncPublisher(CodeCompletionEnabledListener.TOPIC)
.onCodeCompletionsEnabledChange(true);
}
@Override
public void update(@NotNull AnActionEvent e) {
var selectedService = GeneralSettings.getCurrentState().getSelectedService();
var codeCompletionEnabled = ConfigurationSettings.getCurrentState().isCodeCompletionsEnabled();
e.getPresentation().setEnabled(!codeCompletionEnabled);
e.getPresentation()
.setVisible(!codeCompletionEnabled && List.of(OPENAI, LLAMA_CPP).contains(selectedService));
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}
}

View file

@ -161,8 +161,6 @@ public class ConfigurationComponent {
state.setCreateNewChatOnEachAction(openNewTabCheckBox.isSelected());
state.setMethodNameGenerationEnabled(methodNameGenerationCheckBox.isSelected());
state.setAutoFormattingEnabled(autoFormattingCheckBox.isSelected());
state.setCodeCompletionsEnabled(
ConfigurationSettings.getCurrentState().isCodeCompletionsEnabled());
return state;
}

View file

@ -20,7 +20,6 @@ public class ConfigurationState {
private boolean methodNameGenerationEnabled = true;
private boolean captureCompileErrors = true;
private boolean autoFormattingEnabled = true;
private boolean codeCompletionsEnabled;
private Map<String, String> tableData = EditorActionsUtil.DEFAULT_ACTIONS;
public String getSystemPrompt() {
@ -119,14 +118,6 @@ public class ConfigurationState {
this.autoFormattingEnabled = autoFormattingEnabled;
}
public boolean isCodeCompletionsEnabled() {
return codeCompletionsEnabled;
}
public void setCodeCompletionsEnabled(boolean codeCompletionsEnabled) {
this.codeCompletionsEnabled = codeCompletionsEnabled;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -144,7 +135,6 @@ public class ConfigurationState {
&& methodNameGenerationEnabled == that.methodNameGenerationEnabled
&& captureCompileErrors == that.captureCompileErrors
&& autoFormattingEnabled == that.autoFormattingEnabled
&& codeCompletionsEnabled == that.codeCompletionsEnabled
&& Objects.equals(systemPrompt, that.systemPrompt)
&& Objects.equals(commitMessagePrompt, that.commitMessagePrompt)
&& Objects.equals(tableData, that.tableData);
@ -154,7 +144,6 @@ public class ConfigurationState {
public int hashCode() {
return Objects.hash(systemPrompt, commitMessagePrompt, maxTokens, temperature,
checkForPluginUpdates, createNewChatOnEachAction, ignoreGitCommitTokenLimit,
methodNameGenerationEnabled, captureCompileErrors, autoFormattingEnabled,
codeCompletionsEnabled, tableData);
methodNameGenerationEnabled, captureCompileErrors, autoFormattingEnabled, tableData);
}
}

View file

@ -27,6 +27,8 @@ public class LlamaSettingsState {
private double topP = 0.9;
private double minP = 0.05;
private double repeatPenalty = 1.1;
private boolean codeCompletionsEnabled = true;
private int codeCompletionMaxTokens = 128;
public boolean isUseCustomModel() {
return useCustomModel;
@ -168,6 +170,22 @@ public class LlamaSettingsState {
this.repeatPenalty = repeatPenalty;
}
public boolean isCodeCompletionsEnabled() {
return codeCompletionsEnabled;
}
public void setCodeCompletionsEnabled(boolean codeCompletionsEnabled) {
this.codeCompletionsEnabled = codeCompletionsEnabled;
}
public int getCodeCompletionMaxTokens() {
return codeCompletionMaxTokens;
}
public void setCodeCompletionMaxTokens(int codeCompletionMaxTokens) {
this.codeCompletionMaxTokens = codeCompletionMaxTokens;
}
private static Integer getRandomAvailablePortOrDefault() {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
@ -201,7 +219,9 @@ public class LlamaSettingsState {
&& remoteModelInfillPromptTemplate == that.remoteModelInfillPromptTemplate
&& Objects.equals(baseHost, that.baseHost)
&& Objects.equals(serverPort, that.serverPort)
&& Objects.equals(additionalParameters, that.additionalParameters);
&& Objects.equals(additionalParameters, that.additionalParameters)
&& codeCompletionsEnabled == that.codeCompletionsEnabled
&& codeCompletionMaxTokens == that.codeCompletionMaxTokens;
}
@Override
@ -209,6 +229,7 @@ public class LlamaSettingsState {
return Objects.hash(runLocalServer, useCustomModel, customLlamaModelPath, huggingFaceModel,
localModelPromptTemplate, remoteModelPromptTemplate, localModelInfillPromptTemplate,
remoteModelInfillPromptTemplate, baseHost, serverPort, contextSize, threads,
additionalParameters, topK, topP, minP, repeatPenalty);
additionalParameters, topK, topP, minP, repeatPenalty, codeCompletionsEnabled,
codeCompletionMaxTokens);
}
}

View file

@ -5,6 +5,7 @@ import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.ui.TitledSeparator;
import com.intellij.util.ui.FormBuilder;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
import java.awt.BorderLayout;
@ -14,10 +15,14 @@ public class LlamaSettingsForm extends JPanel {
private final LlamaServerPreferencesForm llamaServerPreferencesForm;
private final LlamaRequestPreferencesForm llamaRequestPreferencesForm;
private final CodeCompletionConfigurationForm codeCompletionConfigurationForm;
public LlamaSettingsForm(LlamaSettingsState settings) {
llamaServerPreferencesForm = new LlamaServerPreferencesForm(settings);
llamaRequestPreferencesForm = new LlamaRequestPreferencesForm(settings);
codeCompletionConfigurationForm = new CodeCompletionConfigurationForm(
settings.isCodeCompletionsEnabled(),
settings.getCodeCompletionMaxTokens());
init();
}
@ -44,6 +49,8 @@ public class LlamaSettingsForm extends JPanel {
state.setLocalModelPromptTemplate(modelPreferencesForm.getPromptTemplate());
state.setLocalModelInfillPromptTemplate(modelPreferencesForm.getInfillPromptTemplate());
state.setCodeCompletionsEnabled(codeCompletionConfigurationForm.isCodeCompletionsEnabled());
state.setCodeCompletionMaxTokens(codeCompletionConfigurationForm.getMaxTokens());
return state;
}
@ -51,6 +58,8 @@ public class LlamaSettingsForm extends JPanel {
var state = LlamaSettings.getCurrentState();
llamaServerPreferencesForm.resetForm(state);
llamaRequestPreferencesForm.resetForm(state);
codeCompletionConfigurationForm.setCodeCompletionsEnabled(state.isCodeCompletionsEnabled());
codeCompletionConfigurationForm.setMaxTokens(state.getCodeCompletionMaxTokens());
}
public LlamaServerPreferencesForm getLlamaServerPreferencesForm() {
@ -60,6 +69,8 @@ public class LlamaSettingsForm extends JPanel {
private void init() {
setLayout(new BorderLayout());
add(FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator("Code Completions"))
.addComponent(withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
.addComponent(new TitledSeparator(
CodeGPTBundle.get("settingsConfigurable.service.llama.serverPreferences.title")))
.addComponent(llamaServerPreferencesForm.getForm())

View file

@ -7,6 +7,7 @@ import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

View file

@ -12,6 +12,7 @@ import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import javax.swing.JPanel;
@ -22,6 +23,7 @@ public class OpenAISettingsForm {
private final JBPasswordField apiKeyField;
private final JBTextField organizationField;
private final ComboBox<OpenAIChatCompletionModel> completionModelComboBox;
private final CodeCompletionConfigurationForm codeCompletionConfigurationForm;
public OpenAISettingsForm(OpenAISettingsState settings) {
apiKeyField = new JBPasswordField();
@ -32,6 +34,9 @@ public class OpenAISettingsForm {
new EnumComboBoxModel<>(OpenAIChatCompletionModel.class));
completionModelComboBox.setSelectedItem(
OpenAIChatCompletionModel.findByCode(settings.getModel()));
codeCompletionConfigurationForm = new CodeCompletionConfigurationForm(
settings.isCodeCompletionsEnabled(),
settings.getCodeCompletionMaxTokens());
}
public JPanel getForm() {
@ -52,6 +57,8 @@ public class OpenAISettingsForm {
.createPanel();
return FormBuilder.createFormBuilder()
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.codeCompletions")))
.addComponent(withEmptyLeftBorder(codeCompletionConfigurationForm.getForm()))
.addComponent(new TitledSeparator(CodeGPTBundle.get("shared.configuration")))
.addComponent(withEmptyLeftBorder(configurationGrid))
.addComponentFillVertically(new JPanel(), 0)
@ -73,6 +80,8 @@ public class OpenAISettingsForm {
var state = new OpenAISettingsState();
state.setModel(getModel());
state.setOrganization(organizationField.getText());
state.setCodeCompletionsEnabled(codeCompletionConfigurationForm.isCodeCompletionsEnabled());
state.setCodeCompletionMaxTokens(codeCompletionConfigurationForm.getMaxTokens());
return state;
}
@ -82,5 +91,7 @@ public class OpenAISettingsForm {
completionModelComboBox.setSelectedItem(
OpenAIChatCompletionModel.findByCode(state.getModel()));
organizationField.setText(state.getOrganization());
codeCompletionConfigurationForm.setCodeCompletionsEnabled(state.isCodeCompletionsEnabled());
codeCompletionConfigurationForm.setMaxTokens(state.getCodeCompletionMaxTokens());
}
}

View file

@ -7,6 +7,8 @@ public class OpenAISettingsState {
private String organization = "";
private String model = OpenAIChatCompletionModel.GPT_3_5_0125_16k.getCode();
private boolean codeCompletionsEnabled = true;
private int codeCompletionMaxTokens = 128;
public String getOrganization() {
return organization;
@ -24,6 +26,22 @@ public class OpenAISettingsState {
this.model = model;
}
public boolean isCodeCompletionsEnabled() {
return codeCompletionsEnabled;
}
public void setCodeCompletionsEnabled(boolean codeCompletionsEnabled) {
this.codeCompletionsEnabled = codeCompletionsEnabled;
}
public int getCodeCompletionMaxTokens() {
return codeCompletionMaxTokens;
}
public void setCodeCompletionMaxTokens(int codeCompletionMaxTokens) {
this.codeCompletionMaxTokens = codeCompletionMaxTokens;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -33,11 +51,14 @@ public class OpenAISettingsState {
return false;
}
OpenAISettingsState that = (OpenAISettingsState) o;
return Objects.equals(organization, that.organization) && Objects.equals(model, that.model);
return Objects.equals(organization, that.organization)
&& Objects.equals(model, that.model)
&& codeCompletionsEnabled == that.codeCompletionsEnabled
&& codeCompletionMaxTokens == that.codeCompletionMaxTokens;
}
@Override
public int hashCode() {
return Objects.hash(organization, model);
return Objects.hash(organization, model, codeCompletionsEnabled, codeCompletionMaxTokens);
}
}