From f0172722c75ae50d2ea895f68cbef0c90bbbcc7f Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Wed, 3 Apr 2024 01:04:22 +0300 Subject: [PATCH] feat: add support for configuring code completions via settings --- CHANGELOG.md | 1 + .../CodeCompletionEnabledListener.java | 26 --------- .../actions/DisableCompletionsAction.java | 41 -------------- .../actions/EnableCompletionsAction.java | 41 -------------- .../configuration/ConfigurationComponent.java | 2 - .../configuration/ConfigurationState.java | 13 +---- .../service/llama/LlamaSettingsState.java | 25 ++++++++- .../service/llama/form/LlamaSettingsForm.java | 11 ++++ .../service/openai/OpenAISettings.java | 1 + .../service/openai/OpenAISettingsForm.java | 11 ++++ .../service/openai/OpenAISettingsState.java | 25 ++++++++- .../CodeCompletionFeatureToggleActions.kt | 54 +++++++++++++++++++ .../CodeCompletionRequestFactory.kt | 14 ++--- .../CodeGPTInlineCompletionProvider.kt | 14 +++-- .../CodeCompletionConfigurationForm.kt | 49 +++++++++++++++++ .../resources/messages/codegpt.properties | 4 ++ .../CodeCompletionServiceTest.java | 5 +- 17 files changed, 198 insertions(+), 139 deletions(-) delete mode 100644 src/main/java/ee/carlrobert/codegpt/actions/CodeCompletionEnabledListener.java delete mode 100644 src/main/java/ee/carlrobert/codegpt/actions/DisableCompletionsAction.java delete mode 100644 src/main/java/ee/carlrobert/codegpt/actions/EnableCompletionsAction.java create mode 100644 src/main/kotlin/ee/carlrobert/codegpt/actions/CodeCompletionFeatureToggleActions.kt create mode 100644 src/main/kotlin/ee/carlrobert/codegpt/settings/service/CodeCompletionConfigurationForm.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bf1dc91..00c930b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Vision support (image understanding) for OpenAI GPT-4 and Anthropic Claude models - Total token panel for all providers +- Support for configuring code completions via settings ### Fixed diff --git a/src/main/java/ee/carlrobert/codegpt/actions/CodeCompletionEnabledListener.java b/src/main/java/ee/carlrobert/codegpt/actions/CodeCompletionEnabledListener.java deleted file mode 100644 index 1e8a855c..00000000 --- a/src/main/java/ee/carlrobert/codegpt/actions/CodeCompletionEnabledListener.java +++ /dev/null @@ -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.
- * Broadcasts from Application-Level to all projects. - */ - @Topic.AppLevel - Topic TOPIC = new Topic<>(CodeCompletionEnabledListener.class, - BroadcastDirection.TO_DIRECT_CHILDREN); - - void onCodeCompletionsEnabledChange(boolean codeCompletionsEnabled); -} - diff --git a/src/main/java/ee/carlrobert/codegpt/actions/DisableCompletionsAction.java b/src/main/java/ee/carlrobert/codegpt/actions/DisableCompletionsAction.java deleted file mode 100644 index 1b08fa0a..00000000 --- a/src/main/java/ee/carlrobert/codegpt/actions/DisableCompletionsAction.java +++ /dev/null @@ -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.
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; - } -} diff --git a/src/main/java/ee/carlrobert/codegpt/actions/EnableCompletionsAction.java b/src/main/java/ee/carlrobert/codegpt/actions/EnableCompletionsAction.java deleted file mode 100644 index e646e997..00000000 --- a/src/main/java/ee/carlrobert/codegpt/actions/EnableCompletionsAction.java +++ /dev/null @@ -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.
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; - } -} diff --git a/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationComponent.java b/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationComponent.java index cbcf7fa9..bfe6c0c7 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationComponent.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationComponent.java @@ -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; } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationState.java b/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationState.java index f11663d3..dbf9bb6e 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationState.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/configuration/ConfigurationState.java @@ -20,7 +20,6 @@ public class ConfigurationState { private boolean methodNameGenerationEnabled = true; private boolean captureCompileErrors = true; private boolean autoFormattingEnabled = true; - private boolean codeCompletionsEnabled; private Map 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); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/llama/LlamaSettingsState.java b/src/main/java/ee/carlrobert/codegpt/settings/service/llama/LlamaSettingsState.java index c0c6de0b..cb81c722 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/llama/LlamaSettingsState.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/llama/LlamaSettingsState.java @@ -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); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/llama/form/LlamaSettingsForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/llama/form/LlamaSettingsForm.java index caa9de03..7147eceb 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/llama/form/LlamaSettingsForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/llama/form/LlamaSettingsForm.java @@ -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()) diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettings.java b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettings.java index d65a1576..4ba05dcd 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettings.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettings.java @@ -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; diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsForm.java b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsForm.java index fe3d22b6..f0bdc78b 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsForm.java @@ -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 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()); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsState.java b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsState.java index 75134d65..b13df7d1 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsState.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/service/openai/OpenAISettingsState.java @@ -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); } } diff --git a/src/main/kotlin/ee/carlrobert/codegpt/actions/CodeCompletionFeatureToggleActions.kt b/src/main/kotlin/ee/carlrobert/codegpt/actions/CodeCompletionFeatureToggleActions.kt new file mode 100644 index 00000000..c9dc223e --- /dev/null +++ b/src/main/kotlin/ee/carlrobert/codegpt/actions/CodeCompletionFeatureToggleActions.kt @@ -0,0 +1,54 @@ +package ee.carlrobert.codegpt.actions + +import com.intellij.openapi.actionSystem.ActionUpdateThread +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.DumbAwareAction +import ee.carlrobert.codegpt.settings.GeneralSettings +import ee.carlrobert.codegpt.settings.service.ServiceType +import ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP +import ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI +import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings +import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings + +abstract class CodeCompletionFeatureToggleActions( + private val enableFeatureAction: Boolean +) : DumbAwareAction() { + + override fun actionPerformed(e: AnActionEvent) { + GeneralSettings.getCurrentState().selectedService + .takeIf { it in listOf(OPENAI, LLAMA_CPP) } + ?.also { selectedService -> + if (OPENAI == selectedService) { + OpenAISettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction + } else { + LlamaSettings.getCurrentState().isCodeCompletionsEnabled = enableFeatureAction + } + } + } + + override fun update(e: AnActionEvent) { + val selectedService = GeneralSettings.getCurrentState().selectedService + val codeCompletionEnabled = isCodeCompletionsEnabled(selectedService) + e.presentation.isEnabled = codeCompletionEnabled != enableFeatureAction + e.presentation.isVisible = + e.presentation.isEnabled && listOf(OPENAI, LLAMA_CPP).contains( + selectedService + ) + } + + override fun getActionUpdateThread(): ActionUpdateThread { + return ActionUpdateThread.BGT + } + + private fun isCodeCompletionsEnabled(serviceType: ServiceType): Boolean { + return when (serviceType) { + OPENAI -> OpenAISettings.getCurrentState().isCodeCompletionsEnabled + LLAMA_CPP -> LlamaSettings.getCurrentState().isCodeCompletionsEnabled + else -> false + } + } +} + +class EnableCompletionsAction : CodeCompletionFeatureToggleActions(true) + +class DisableCompletionsAction : CodeCompletionFeatureToggleActions(false) \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt index 0738062c..26c35063 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt @@ -2,34 +2,34 @@ package ee.carlrobert.codegpt.codecompletions import ee.carlrobert.codegpt.completions.llama.LlamaModel import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings +import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState +import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings import ee.carlrobert.llm.client.llama.completion.LlamaCompletionRequest import ee.carlrobert.llm.client.openai.completion.request.OpenAITextCompletionRequest object CodeCompletionRequestFactory { - private const val MAX_TOKENS = 128 - fun buildOpenAIRequest(details: InfillRequestDetails): OpenAITextCompletionRequest { return OpenAITextCompletionRequest.Builder(details.prefix) .setSuffix(details.suffix) .setStream(true) - .setMaxTokens(MAX_TOKENS) + .setMaxTokens(OpenAISettings.getCurrentState().codeCompletionMaxTokens) .setTemperature(0.4) .build() } fun buildLlamaRequest(details: InfillRequestDetails): LlamaCompletionRequest { - val promptTemplate = getLlamaInfillPromptTemplate() + val settings = LlamaSettings.getCurrentState() + val promptTemplate = getLlamaInfillPromptTemplate(settings) val prompt = promptTemplate.buildPrompt(details.prefix, details.suffix) return LlamaCompletionRequest.Builder(prompt) - .setN_predict(MAX_TOKENS) + .setN_predict(settings.codeCompletionMaxTokens) .setStream(true) .setTemperature(0.4) .setStop(promptTemplate.stopTokens) .build() } - private fun getLlamaInfillPromptTemplate(): InfillPromptTemplate { - val settings = LlamaSettings.getCurrentState() + private fun getLlamaInfillPromptTemplate(settings: LlamaSettingsState): InfillPromptTemplate { if (!settings.isRunLocalServer) { return settings.remoteModelInfillPromptTemplate } diff --git a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionProvider.kt b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionProvider.kt index 6d111e23..e0fecdce 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionProvider.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionProvider.kt @@ -8,7 +8,10 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.editor.Editor import ee.carlrobert.codegpt.CodeGPTKeys import ee.carlrobert.codegpt.completions.CompletionRequestService -import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings +import ee.carlrobert.codegpt.settings.GeneralSettings +import ee.carlrobert.codegpt.settings.service.ServiceType +import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings +import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings import ee.carlrobert.codegpt.treesitter.CodeCompletionParserFactory import ee.carlrobert.llm.completion.CompletionEventListener import kotlinx.coroutines.* @@ -52,8 +55,13 @@ class CodeGPTInlineCompletionProvider : InlineCompletionProvider { } override fun isEnabled(event: InlineCompletionEvent): Boolean { - return event is InlineCompletionEvent.DocumentChange - && ConfigurationSettings.getCurrentState().isCodeCompletionsEnabled + val selectedService = GeneralSettings.getCurrentState().selectedService + val codeCompletionsEnabled = when (selectedService) { + ServiceType.OPENAI -> OpenAISettings.getCurrentState().isCodeCompletionsEnabled + ServiceType.LLAMA_CPP -> LlamaSettings.getCurrentState().isCodeCompletionsEnabled + else -> false + } + return event is InlineCompletionEvent.DocumentChange && codeCompletionsEnabled } private fun ProducerScope.getCodeCompletionEventListener( diff --git a/src/main/kotlin/ee/carlrobert/codegpt/settings/service/CodeCompletionConfigurationForm.kt b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/CodeCompletionConfigurationForm.kt new file mode 100644 index 00000000..1fddb3fa --- /dev/null +++ b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/CodeCompletionConfigurationForm.kt @@ -0,0 +1,49 @@ +package ee.carlrobert.codegpt.settings.service + +import com.intellij.openapi.ui.panel.ComponentPanelBuilder +import com.intellij.ui.components.JBCheckBox +import com.intellij.ui.components.fields.IntegerField +import com.intellij.util.ui.FormBuilder +import ee.carlrobert.codegpt.CodeGPTBundle +import javax.swing.JPanel + +class CodeCompletionConfigurationForm(codeCompletionsEnabled: Boolean, maxTokens: Int) { + + private val codeCompletionsEnabledCheckBox = JBCheckBox( + CodeGPTBundle.get("codeCompletionsForm.enableFeatureText"), + codeCompletionsEnabled + ) + private val codeCompletionMaxTokensField = + IntegerField("completion_max_tokens", 8, 4096).apply { + columns = 12 + value = maxTokens + } + + fun getForm(): JPanel { + return FormBuilder.createFormBuilder() + .addComponent(codeCompletionsEnabledCheckBox) + .addVerticalGap(4) + .addLabeledComponent( + CodeGPTBundle.get("codeCompletionsForm.maxTokensLabel"), + codeCompletionMaxTokensField + ) + .addComponentToRightColumn( + ComponentPanelBuilder.createCommentComponent( + CodeGPTBundle.get("codeCompletionsForm.maxTokensComment"), true, 48, true + ) + ) + .panel + } + + var isCodeCompletionsEnabled: Boolean + get() = codeCompletionsEnabledCheckBox.isSelected + set(enabled) { + codeCompletionsEnabledCheckBox.isSelected = enabled + } + + var maxTokens: Int + get() = codeCompletionMaxTokensField.value + set(maxTokens) { + codeCompletionMaxTokensField.value = maxTokens + } +} diff --git a/src/main/resources/messages/codegpt.properties b/src/main/resources/messages/codegpt.properties index b5858202..c31b2b00 100644 --- a/src/main/resources/messages/codegpt.properties +++ b/src/main/resources/messages/codegpt.properties @@ -198,3 +198,7 @@ action.attachImage=Attach Image action.attachImageDescription=Attach an image imageFileChooser.title=Select Image imageAccordion.title=Attached image +shared.codeCompletions=Code Completions +codeCompletionsForm.enableFeatureText=Enable code completions +codeCompletionsForm.maxTokensLabel=Max tokens: +codeCompletionsForm.maxTokensComment=The maximum number of tokens that can be generated in the code completion. diff --git a/src/test/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.java b/src/test/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.java index 0b039e06..bdd390a4 100644 --- a/src/test/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.java +++ b/src/test/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.java @@ -8,8 +8,7 @@ import static ee.carlrobert.llm.client.util.JSONUtil.jsonMapResponse; import static org.assertj.core.api.Assertions.assertThat; import com.intellij.openapi.editor.VisualPosition; -import com.intellij.testFramework.PlatformTestUtil; -import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings; +import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings; import ee.carlrobert.llm.client.http.exchange.StreamHttpExchange; import java.util.List; import testsupport.IntegrationTest; @@ -20,7 +19,7 @@ public class CodeCompletionServiceTest extends IntegrationTest { public void testFetchCodeCompletionLlama() { useLlamaService(); - ConfigurationSettings.getCurrentState().setCodeCompletionsEnabled(true); + LlamaSettings.getCurrentState().setCodeCompletionsEnabled(true); myFixture.configureByText( "CompletionTest.java", getResourceContent("/codecompletions/code-completion-file.txt"));