diff --git a/src/main/java/com/devoxx/genie/chatmodel/ChatModelProvider.java b/src/main/java/com/devoxx/genie/chatmodel/ChatModelProvider.java index 2f79f5a2..a89532de 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/ChatModelProvider.java +++ b/src/main/java/com/devoxx/genie/chatmodel/ChatModelProvider.java @@ -13,7 +13,7 @@ import com.devoxx.genie.model.Constant; import com.devoxx.genie.model.enumarations.ModelProvider; import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llmconfig.LLMConfigStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import lombok.Setter; @@ -83,7 +83,7 @@ public StreamingChatLanguageModel getStreamingChatLanguageModel(@NotNull ChatMes */ public @NotNull ChatModel initChatModel(@NotNull ChatMessageContext chatMessageContext) { ChatModel chatModel = new ChatModel(); - SettingsStateService settingsState = SettingsStateService.getInstance(); + LLMConfigStateService settingsState = LLMConfigStateService.getInstance(); setMaxOutputTokens(settingsState, chatModel); chatModel.setTemperature(settingsState.getTemperature()); @@ -101,15 +101,13 @@ public StreamingChatLanguageModel getStreamingChatLanguageModel(@NotNull ChatMes * @param settingsState the settings state * @param chatModel the chat model */ - private static void setMaxOutputTokens(@NotNull SettingsStateService settingsState, ChatModel chatModel) { - String maxOutputTokens = settingsState.getMaxOutputTokens(); - if (maxOutputTokens.isBlank()) { + private static void setMaxOutputTokens(@NotNull LLMConfigStateService settingsState, ChatModel chatModel) { + Integer maxOutputTokens = settingsState.getMaxOutputTokens(); + if (maxOutputTokens == null) { chatModel.setMaxTokens(Constant.MAX_OUTPUT_TOKENS); } else { - int value; try { - value = Integer.parseInt(maxOutputTokens); - chatModel.setMaxTokens(value); + chatModel.setMaxTokens(maxOutputTokens); } catch (NumberFormatException e) { chatModel.setMaxTokens(Constant.MAX_OUTPUT_TOKENS); } diff --git a/src/main/java/com/devoxx/genie/chatmodel/LLMProviderConstant.java b/src/main/java/com/devoxx/genie/chatmodel/LLMProviderConstant.java index 9e421c38..b7ed61bf 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/LLMProviderConstant.java +++ b/src/main/java/com/devoxx/genie/chatmodel/LLMProviderConstant.java @@ -1,6 +1,6 @@ package com.devoxx.genie.chatmodel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -32,7 +32,7 @@ private LLMProviderConstant() { }; public static @NotNull List getLLMProviders() { - SettingsStateService settingState = SettingsStateService.getInstance(); + LLMStateService settingState = LLMStateService.getInstance(); Map> providerKeyMap = new HashMap<>(); providerKeyMap.put(OpenAI.getName(), settingState::getOpenAIKey); providerKeyMap.put(Anthropic.getName(), settingState::getAnthropicKey); diff --git a/src/main/java/com/devoxx/genie/chatmodel/anthropic/AnthropicChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/anthropic/AnthropicChatModelFactory.java index 860066ff..badc1184 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/anthropic/AnthropicChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/anthropic/AnthropicChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.anthropic.AnthropicChatModel; import dev.langchain4j.model.anthropic.AnthropicStreamingChatModel; import dev.langchain4j.model.chat.ChatLanguageModel; @@ -40,7 +40,7 @@ public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel ch @Override public String getApiKey() { - return SettingsStateService.getInstance().getAnthropicKey().trim(); + return LLMStateService.getInstance().getAnthropicKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/chatmodel/deepinfra/DeepInfraChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/deepinfra/DeepInfraChatModelFactory.java index c8602283..dc7b7e36 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/deepinfra/DeepInfraChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/deepinfra/DeepInfraChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; @@ -42,7 +42,7 @@ public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel ch @Override public String getApiKey() { - return SettingsStateService.getInstance().getDeepInfraKey().trim(); + return LLMStateService.getInstance().getDeepInfraKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/chatmodel/gemini/GeminiChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/gemini/GeminiChatModelFactory.java index 65fc4c1c..c543bb86 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/gemini/GeminiChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/gemini/GeminiChatModelFactory.java @@ -3,7 +3,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; import com.devoxx.genie.model.gemini.GeminiChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import org.jetbrains.annotations.NotNull; @@ -26,7 +26,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { @Override public String getApiKey() { - return SettingsStateService.getInstance().getGeminiKey().trim(); + return LLMStateService.getInstance().getGeminiKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/chatmodel/gpt4all/GPT4AllChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/gpt4all/GPT4AllChatModelFactory.java index 73feaf5a..d5dcaead 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/gpt4all/GPT4AllChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/gpt4all/GPT4AllChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.localai.LocalAiChatModel; @@ -16,7 +16,7 @@ public class GPT4AllChatModelFactory implements ChatModelFactory { @Override public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { return LocalAiChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getGpt4allModelUrl()) + .baseUrl(LLMStateService.getInstance().getGpt4allModelUrl()) .modelName("test-model") .maxRetries(chatModel.getMaxRetries()) .maxTokens(chatModel.getMaxTokens()) @@ -28,7 +28,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel chatModel) { return LocalAiStreamingChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getGpt4allModelUrl()) + .baseUrl(LLMStateService.getInstance().getGpt4allModelUrl()) .modelName("test-model") .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) diff --git a/src/main/java/com/devoxx/genie/chatmodel/groq/GroqChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/groq/GroqChatModelFactory.java index 64f78918..71c82401 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/groq/GroqChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/groq/GroqChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import org.jetbrains.annotations.NotNull; @@ -40,7 +40,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { @Override public String getApiKey() { - return SettingsStateService.getInstance().getGroqKey().trim(); + return LLMStateService.getInstance().getGroqKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/chatmodel/jan/JanChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/jan/JanChatModelFactory.java index c2d9b653..4bccc65e 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/jan/JanChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/jan/JanChatModelFactory.java @@ -4,7 +4,7 @@ import com.devoxx.genie.model.ChatModel; import com.devoxx.genie.model.jan.Data; import com.devoxx.genie.service.JanService; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.openapi.project.ProjectManager; import dev.langchain4j.model.chat.ChatLanguageModel; @@ -27,7 +27,7 @@ public class JanChatModelFactory implements ChatModelFactory { @Override public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { return LocalAiChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getJanModelUrl()) + .baseUrl(LLMStateService.getInstance().getJanModelUrl()) .modelName(chatModel.getModelName()) .maxRetries(chatModel.getMaxRetries()) .temperature(chatModel.getTemperature()) @@ -41,7 +41,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { @Override public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel chatModel) { return LocalAiStreamingChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getJanModelUrl()) + .baseUrl(LLMStateService.getInstance().getJanModelUrl()) .modelName(chatModel.getModelName()) .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) diff --git a/src/main/java/com/devoxx/genie/chatmodel/lmstudio/LMStudioChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/lmstudio/LMStudioChatModelFactory.java index 0044a256..0dfce58e 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/lmstudio/LMStudioChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/lmstudio/LMStudioChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.localai.LocalAiChatModel; @@ -16,7 +16,7 @@ public class LMStudioChatModelFactory implements ChatModelFactory { @Override public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { return LocalAiChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getLmstudioModelUrl()) + .baseUrl(LLMStateService.getInstance().getLmstudioModelUrl()) .modelName("LMStudio") .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) @@ -29,7 +29,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { @Override public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel chatModel) { return LocalAiStreamingChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getLmstudioModelUrl()) + .baseUrl(LLMStateService.getInstance().getLmstudioModelUrl()) .modelName("LMStudio") .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) diff --git a/src/main/java/com/devoxx/genie/chatmodel/mistral/MistralChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/mistral/MistralChatModelFactory.java index 96cc7014..db423f9b 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/mistral/MistralChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/mistral/MistralChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; @@ -42,7 +42,7 @@ public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel ch @Override public String getApiKey() { - return SettingsStateService.getInstance().getMistralKey().trim(); + return LLMStateService.getInstance().getMistralKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/chatmodel/ollama/OllamaChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/ollama/OllamaChatModelFactory.java index b71b08db..e0c9b0d4 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/ollama/OllamaChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/ollama/OllamaChatModelFactory.java @@ -4,7 +4,7 @@ import com.devoxx.genie.model.ChatModel; import com.devoxx.genie.model.ollama.OllamaModelEntryDTO; import com.devoxx.genie.service.OllamaService; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.openapi.project.ProjectManager; import dev.langchain4j.model.chat.ChatLanguageModel; @@ -23,7 +23,7 @@ public class OllamaChatModelFactory implements ChatModelFactory { @Override public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { return OllamaChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getOllamaModelUrl()) + .baseUrl(LLMStateService.getInstance().getOllamaModelUrl()) .modelName(chatModel.getModelName()) .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) @@ -35,7 +35,7 @@ public ChatLanguageModel createChatModel(@NotNull ChatModel chatModel) { @Override public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel chatModel) { return OllamaStreamingChatModel.builder() - .baseUrl(SettingsStateService.getInstance().getOllamaModelUrl()) + .baseUrl(LLMStateService.getInstance().getOllamaModelUrl()) .modelName(chatModel.getModelName()) .temperature(chatModel.getTemperature()) .topP(chatModel.getTopP()) diff --git a/src/main/java/com/devoxx/genie/chatmodel/openai/OpenAIChatModelFactory.java b/src/main/java/com/devoxx/genie/chatmodel/openai/OpenAIChatModelFactory.java index 49bcc7a4..c48a596e 100644 --- a/src/main/java/com/devoxx/genie/chatmodel/openai/OpenAIChatModelFactory.java +++ b/src/main/java/com/devoxx/genie/chatmodel/openai/OpenAIChatModelFactory.java @@ -2,7 +2,7 @@ import com.devoxx.genie.chatmodel.ChatModelFactory; import com.devoxx.genie.model.ChatModel; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; @@ -41,7 +41,7 @@ public StreamingChatLanguageModel createStreamingChatModel(@NotNull ChatModel ch @Override public String getApiKey() { - return SettingsStateService.getInstance().getOpenAIKey().trim(); + return LLMStateService.getInstance().getOpenAIKey().trim(); } @Override diff --git a/src/main/java/com/devoxx/genie/model/ChatModel.java b/src/main/java/com/devoxx/genie/model/ChatModel.java index d2213654..2a28f168 100644 --- a/src/main/java/com/devoxx/genie/model/ChatModel.java +++ b/src/main/java/com/devoxx/genie/model/ChatModel.java @@ -9,8 +9,8 @@ public class ChatModel { private String baseUrl; private String modelName; - private Double temperature = Constant.TEMPERATURE; - private Double topP = Constant.TOP_P; + private double temperature = Constant.TEMPERATURE; + private double topP = Constant.TOP_P; private int maxTokens = Constant.MAX_OUTPUT_TOKENS; private int maxRetries = Constant.MAX_RETRIES; private int timeout = Constant.TIMEOUT; diff --git a/src/main/java/com/devoxx/genie/service/ChatMemoryService.java b/src/main/java/com/devoxx/genie/service/ChatMemoryService.java index beab4f03..aad708bc 100644 --- a/src/main/java/com/devoxx/genie/service/ChatMemoryService.java +++ b/src/main/java/com/devoxx/genie/service/ChatMemoryService.java @@ -1,7 +1,7 @@ package com.devoxx.genie.service; -import com.devoxx.genie.service.settings.SettingsStateService; import com.devoxx.genie.ui.listener.ChatMemorySizeListener; +import com.devoxx.genie.ui.settings.llmconfig.LLMConfigStateService; import com.devoxx.genie.ui.topic.AppTopics; import com.intellij.openapi.application.ApplicationManager; import dev.langchain4j.data.message.ChatMessage; @@ -22,7 +22,7 @@ public class ChatMemoryService implements ChatMemorySizeListener { * @link PostStartupActivity */ public void init() { - createChatMemory(SettingsStateService.getInstance().getChatMemorySize()); + createChatMemory(LLMConfigStateService.getInstance().getChatMemorySize()); createChangeListener(); } diff --git a/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java b/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java index 3258c713..0601f848 100644 --- a/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java +++ b/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java @@ -1,8 +1,9 @@ package com.devoxx.genie.service; import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; import com.devoxx.genie.ui.panel.PromptOutputPanel; +import com.devoxx.genie.ui.settings.llm.LLMStateService; +import com.devoxx.genie.ui.settings.prompt.PromptSettingsStateService; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; @@ -18,7 +19,6 @@ public class ChatPromptExecutor { private final PromptExecutionService promptExecutionService = PromptExecutionService.getInstance(); - private final SettingsStateService settingsState = SettingsStateService.getInstance(); public ChatPromptExecutor() { } @@ -39,7 +39,7 @@ public void run(@NotNull ProgressIndicator progressIndicator) { if (chatMessageContext.getContext() != null && chatMessageContext.getContext().toLowerCase().contains("search")) { webSearchPrompt(chatMessageContext, promptOutputPanel, enableButtons); } else { - if (SettingsStateService.getInstance().getStreamMode()) { + if (LLMStateService.getInstance().getStreamMode()) { setupStreaming(chatMessageContext, promptOutputPanel, enableButtons); } else { runPrompt(chatMessageContext, promptOutputPanel, enableButtons); @@ -99,7 +99,7 @@ private void setupStreaming(@NotNull ChatMessageContext chatMessageContext, MessageCreationService messageCreationService = MessageCreationService.getInstance(); if (chatMemoryService.isEmpty()) { - chatMemoryService.add(new SystemMessage(SettingsStateService.getInstance().getSystemPrompt())); + chatMemoryService.add(new SystemMessage(PromptSettingsStateService.getInstance().getSystemPrompt())); } UserMessage userMessage = messageCreationService.createUserMessage(chatMessageContext); @@ -124,13 +124,13 @@ private Optional getCommandFromPrompt(@NotNull String prompt, if (prompt.startsWith("/")) { if (prompt.equalsIgnoreCase("/test")) { - prompt = settingsState.getTestPrompt(); + prompt = PromptSettingsStateService.getInstance().getTestPrompt(); } else if (prompt.equalsIgnoreCase("/review")) { - prompt = settingsState.getReviewPrompt(); + prompt = PromptSettingsStateService.getInstance().getReviewPrompt(); } else if (prompt.equalsIgnoreCase("/explain")) { - prompt = settingsState.getExplainPrompt(); + prompt = PromptSettingsStateService.getInstance().getExplainPrompt(); } else if (prompt.equalsIgnoreCase("/custom")) { - prompt = settingsState.getCustomPrompt(); + prompt = PromptSettingsStateService.getInstance().getCustomPrompt(); } else { promptOutputPanel.showHelpText(); return Optional.empty(); diff --git a/src/main/java/com/devoxx/genie/service/JanService.java b/src/main/java/com/devoxx/genie/service/JanService.java index c2aca7f1..f432a3dc 100644 --- a/src/main/java/com/devoxx/genie/service/JanService.java +++ b/src/main/java/com/devoxx/genie/service/JanService.java @@ -2,7 +2,7 @@ import com.devoxx.genie.model.jan.Data; import com.devoxx.genie.model.jan.ResponseDTO; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.google.gson.Gson; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -21,7 +21,7 @@ public JanService(OkHttpClient client) { } public List getModels() throws IOException { - String baseUrl = ensureEndsWithSlash(SettingsStateService.getInstance().getJanModelUrl()); + String baseUrl = ensureEndsWithSlash(LLMStateService.getInstance().getJanModelUrl()); Request request = new Request.Builder() .url(baseUrl + "models") diff --git a/src/main/java/com/devoxx/genie/service/MessageCreationService.java b/src/main/java/com/devoxx/genie/service/MessageCreationService.java index 73448400..c273fcbf 100644 --- a/src/main/java/com/devoxx/genie/service/MessageCreationService.java +++ b/src/main/java/com/devoxx/genie/service/MessageCreationService.java @@ -1,7 +1,8 @@ package com.devoxx.genie.service; import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; +import com.devoxx.genie.ui.settings.llmconfig.LLMConfigStateService; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; @@ -100,7 +101,7 @@ public static MessageCreationService getInstance() { appendIfNotEmpty(sb, chatMessageContext.getEditorInfo().getSelectedText()); - if (SettingsStateService.getInstance().getAstMode()) { + if (LLMConfigStateService.getInstance().getAstMode()) { addASTContext(chatMessageContext, sb); } diff --git a/src/main/java/com/devoxx/genie/service/OllamaService.java b/src/main/java/com/devoxx/genie/service/OllamaService.java index dbb5d5fe..4db4ec1e 100644 --- a/src/main/java/com/devoxx/genie/service/OllamaService.java +++ b/src/main/java/com/devoxx/genie/service/OllamaService.java @@ -2,7 +2,7 @@ import com.devoxx.genie.model.ollama.OllamaModelDTO; import com.devoxx.genie.model.ollama.OllamaModelEntryDTO; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.google.gson.Gson; import com.intellij.openapi.application.ApplicationManager; import okhttp3.OkHttpClient; @@ -29,7 +29,7 @@ public static OllamaService getInstance() { * @throws IOException if there is an error */ public OllamaModelEntryDTO[] getModels() throws IOException { - String baseUrl = ensureEndsWithSlash(SettingsStateService.getInstance().getOllamaModelUrl()); + String baseUrl = ensureEndsWithSlash(LLMStateService.getInstance().getOllamaModelUrl()); Request request = new Request.Builder() .url(baseUrl + "api/tags") diff --git a/src/main/java/com/devoxx/genie/service/PSIAnalyzerService.java b/src/main/java/com/devoxx/genie/service/PSIAnalyzerService.java index 0f78436e..3800f8de 100644 --- a/src/main/java/com/devoxx/genie/service/PSIAnalyzerService.java +++ b/src/main/java/com/devoxx/genie/service/PSIAnalyzerService.java @@ -1,6 +1,6 @@ package com.devoxx.genie.service; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llmconfig.LLMConfigStateService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -36,13 +36,13 @@ public Optional> analyze(Project project, VirtualFile file) { } for (PsiClass psiClass : runReadAction(javaFile::getClasses)) { - if (SettingsStateService.getInstance().getAstParentClass()) { + if (LLMConfigStateService.getInstance().getAstParentClass()) { extractBaseClass(psiClass, relatedClasses); } - if (SettingsStateService.getInstance().getAstClassReference()) { + if (LLMConfigStateService.getInstance().getAstClassReference()) { extractReferenceClasses(psiClass, relatedClasses); } - if (SettingsStateService.getInstance().getAstFieldReference()) { + if (LLMConfigStateService.getInstance().getAstFieldReference()) { PsiField[] fields = runReadAction(psiClass::getFields); extractPSIFields(fields, relatedClasses); } diff --git a/src/main/java/com/devoxx/genie/service/PromptExecutionService.java b/src/main/java/com/devoxx/genie/service/PromptExecutionService.java index 2ad2d3df..37011263 100644 --- a/src/main/java/com/devoxx/genie/service/PromptExecutionService.java +++ b/src/main/java/com/devoxx/genie/service/PromptExecutionService.java @@ -2,7 +2,7 @@ import com.devoxx.genie.model.Constant; import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.prompt.PromptSettingsStateService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import dev.langchain4j.data.message.AiMessage; @@ -52,7 +52,7 @@ static PromptExecutionService getInstance() { if (ChatMemoryService.getInstance().isEmpty()) { ChatMemoryService.getInstance().add( - new SystemMessage(SettingsStateService.getInstance().getSystemPrompt() + Constant.MARKDOWN) + new SystemMessage(PromptSettingsStateService.getInstance().getSystemPrompt() + Constant.MARKDOWN) ); } diff --git a/src/main/java/com/devoxx/genie/service/WebSearchService.java b/src/main/java/com/devoxx/genie/service/WebSearchService.java index 8d02e017..dce3cb9a 100644 --- a/src/main/java/com/devoxx/genie/service/WebSearchService.java +++ b/src/main/java/com/devoxx/genie/service/WebSearchService.java @@ -2,7 +2,7 @@ import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.intellij.openapi.application.ApplicationManager; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.rag.content.retriever.ContentRetriever; @@ -71,15 +71,15 @@ interface SearchWebsite { */ private static Optional getWebSearchEngine(@NotNull ChatMessageContext chatMessageContext) { if (chatMessageContext.getContext().equals(TAVILY_SEARCH_ACTION) && - SettingsStateService.getInstance().getTavilySearchKey() != null) { + LLMStateService.getInstance().getTavilySearchKey() != null) { return Optional.of(TavilyWebSearchEngine.builder() - .apiKey(SettingsStateService.getInstance().getTavilySearchKey()) + .apiKey(LLMStateService.getInstance().getTavilySearchKey()) .build()); - } else if (SettingsStateService.getInstance().getGoogleSearchKey() != null && + } else if (LLMStateService.getInstance().getGoogleSearchKey() != null && chatMessageContext.getContext().equals(GOOGLE_SEARCH_ACTION)) { return Optional.of(GoogleCustomWebSearchEngine.builder() - .apiKey(SettingsStateService.getInstance().getGoogleSearchKey()) - .csi(SettingsStateService.getInstance().getGoogleCSIKey()) + .apiKey(LLMStateService.getInstance().getGoogleSearchKey()) + .csi(LLMStateService.getInstance().getGoogleCSIKey()) .build()); } else { return Optional.empty(); diff --git a/src/main/java/com/devoxx/genie/service/settings/SettingsStateService.java b/src/main/java/com/devoxx/genie/service/settings/SettingsStateService.java deleted file mode 100644 index 204f7bbc..00000000 --- a/src/main/java/com/devoxx/genie/service/settings/SettingsStateService.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.devoxx.genie.service.settings; - -import com.devoxx.genie.ui.util.DoubleConverter; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.Service; -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 lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; - -import static com.devoxx.genie.model.Constant.*; - -@Getter -@Setter -@Service -@State( - name = "com.devoxx.genie.ui.SettingsState", - storages = @Storage("DevoxxGenieSettingsPlugin.xml") -) -public final class SettingsStateService implements PersistentStateComponent { - - public static SettingsStateService getInstance() { - return ApplicationManager.getApplication().getService(SettingsStateService.class); - } - - // Local LLM URL fields - private String ollamaModelUrl = OLLAMA_MODEL_URL; - private String lmstudioModelUrl = LMSTUDIO_MODEL_URL; - private String gpt4allModelUrl = GPT4ALL_MODEL_URL; - private String janModelUrl = JAN_MODEL_URL; - - // LLM API Keys - private String openAIKey = ""; - private String mistralKey = ""; - private String anthropicKey = ""; - private String groqKey = ""; - private String fireworksKey = ""; - private String deepInfraKey = ""; - private String geminiKey = ""; - - // Search API Keys - private Boolean hideSearchButtonsFlag = HIDE_SEARCH_BUTTONS; - private String googleSearchKey = ""; - private String googleCSIKey = ""; - private String tavilySearchKey = ""; - - // Prompt fields - private String systemPrompt = SYSTEM_PROMPT; - private String testPrompt = TEST_PROMPT; - private String reviewPrompt = REVIEW_PROMPT; - private String explainPrompt = EXPLAIN_PROMPT; - private String customPrompt = CUSTOM_PROMPT; - - // LLM settings - @OptionTag(converter = DoubleConverter.class) - private Double temperature = TEMPERATURE; - - @OptionTag(converter = DoubleConverter.class) - private Double topP = TOP_P; - - private Integer timeout = TIMEOUT; - private Integer maxRetries = MAX_RETRIES; - private Integer chatMemorySize = MAX_MEMORY; - - // Was unable to make it work with Integer for some unknown reason - private String maxOutputTokens = MAX_OUTPUT_TOKENS.toString(); - - // Last selected LLM provider and model name - private String lastSelectedProvider; - private String lastSelectedModel; - - // Enable stream mode - private Boolean streamMode = STREAM_MODE; - - // Enable AST mode - private Boolean astMode = AST_MODE; - private Boolean astParentClass = AST_PARENT_CLASS; - private Boolean astClassReference = AST_CLASS_REFERENCE; - private Boolean astFieldReference = AST_FIELD_REFERENCE; - - @Override - public SettingsStateService getState() { - return this; - } - - @Override - public void loadState(@NotNull SettingsStateService state) { - XmlSerializerUtil.copyBean(state, this); - } -} diff --git a/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java b/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java index 80c18f38..1facbb73 100644 --- a/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java +++ b/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java @@ -6,13 +6,13 @@ import com.devoxx.genie.model.enumarations.ModelProvider; import com.devoxx.genie.service.ChatMemoryService; import com.devoxx.genie.service.FileListManager; -import com.devoxx.genie.service.settings.SettingsStateService; import com.devoxx.genie.ui.component.PromptInputArea; import com.devoxx.genie.ui.listener.SettingsChangeListener; import com.devoxx.genie.ui.panel.ActionButtonsPanel; import com.devoxx.genie.ui.panel.ConversationPanel; import com.devoxx.genie.ui.panel.PromptContextFileListPanel; import com.devoxx.genie.ui.panel.PromptOutputPanel; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.Splitter; @@ -71,8 +71,8 @@ public DevoxxGenieToolWindowContent(@NotNull ToolWindow toolWindow) { * Set the last selected LLM provider or show default. */ private void setLastSelectedProvider() { - String lastSelectedProvider = SettingsStateService.getInstance().getLastSelectedProvider(); - if (lastSelectedProvider != null) { + String lastSelectedProvider = LLMStateService.getInstance().getLastSelectedProvider(); + if (lastSelectedProvider != null && !lastSelectedProvider.isEmpty()) { llmProvidersComboBox.setSelectedItem(lastSelectedProvider); updateModelNamesComboBox(ModelProvider.valueOf(lastSelectedProvider)); } else { @@ -229,7 +229,7 @@ private void processModelNameSelection(@NotNull ActionEvent e) { JComboBox comboBox = (JComboBox) e.getSource(); String selectedModel = (String) comboBox.getSelectedItem(); if (selectedModel != null) { - SettingsStateService.getInstance().setLastSelectedModel(selectedModel); + LLMStateService.getInstance().setLastSelectedModel(selectedModel); } } } @@ -246,7 +246,7 @@ private void handleModelProviderSelectionChange(@NotNull ActionEvent e) { String selectedLLMProvider = (String) comboBox.getSelectedItem(); if (selectedLLMProvider == null) return; - SettingsStateService.getInstance().setLastSelectedProvider(selectedLLMProvider); + LLMStateService.getInstance().setLastSelectedProvider(selectedLLMProvider); ModelProvider provider = ModelProvider.fromString(selectedLLMProvider); updateModelNamesComboBox(provider); @@ -269,7 +269,7 @@ private void updateModelNamesComboBox(ModelProvider provider) { .getFactoryByProvider(provider) .ifPresentOrElse(this::populateModelNames, this::hideModelNameComboBox); - String lastSelectedModel = SettingsStateService.getInstance().getLastSelectedModel(); + String lastSelectedModel = LLMStateService.getInstance().getLastSelectedModel(); if (lastSelectedModel != null) { modelNameComboBox.setSelectedItem(lastSelectedModel); } diff --git a/src/main/java/com/devoxx/genie/ui/panel/ActionButtonsPanel.java b/src/main/java/com/devoxx/genie/ui/panel/ActionButtonsPanel.java index ae629313..c85fc556 100644 --- a/src/main/java/com/devoxx/genie/ui/panel/ActionButtonsPanel.java +++ b/src/main/java/com/devoxx/genie/ui/panel/ActionButtonsPanel.java @@ -7,12 +7,13 @@ import com.devoxx.genie.service.ChatPromptExecutor; import com.devoxx.genie.service.FileListManager; import com.devoxx.genie.service.MessageCreationService; -import com.devoxx.genie.service.settings.SettingsStateService; import com.devoxx.genie.ui.DevoxxGenieToolWindowContent; import com.devoxx.genie.ui.EditorFileButtonManager; import com.devoxx.genie.ui.component.ContextPopupMenu; import com.devoxx.genie.ui.component.JHoverButton; import com.devoxx.genie.ui.component.PromptInputArea; +import com.devoxx.genie.ui.settings.llm.LLMStateService; +import com.devoxx.genie.ui.settings.llmconfig.LLMConfigStateService; import com.devoxx.genie.ui.util.EditorUtil; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.openapi.editor.Editor; @@ -169,7 +170,7 @@ public void enableButtons() { */ private void disableSubmitBtn() { invokeLater(() -> { - if (SettingsStateService.getInstance().getStreamMode()) { + if (LLMStateService.getInstance().getStreamMode()) { submitBtn.setEnabled(false); } submitBtn.setIcon(StopIcon); @@ -224,7 +225,7 @@ private boolean isWebSearchTriggeredAndConfigured(@NotNull ActionEvent actionEve chatMessageContext.setLlmProvider((String) llmProvidersComboBox.getSelectedItem()); chatMessageContext.setModelName((String) modelNameComboBox.getSelectedItem()); - if (SettingsStateService.getInstance().getStreamMode() && actionEvent.getActionCommand().equals(Constant.SUBMIT_ACTION)) { + if (LLMStateService.getInstance().getStreamMode() && actionEvent.getActionCommand().equals(Constant.SUBMIT_ACTION)) { chatMessageContext.setStreamingChatLanguageModel(chatModelProvider.getStreamingChatLanguageModel(chatMessageContext)); } else { chatMessageContext.setChatLanguageModel(chatModelProvider.getChatLanguageModel(chatMessageContext)); @@ -281,7 +282,7 @@ private void addSelectedCodeSnippet(String userPrompt, * @param chatMessageContext the chat message context */ private void setChatTimeout(ChatMessageContext chatMessageContext) { - Integer timeout = SettingsStateService.getInstance().getTimeout(); + Integer timeout = LLMConfigStateService.getInstance().getTimeout(); if (timeout == 0) { chatMessageContext.setTimeout(60); } else { @@ -294,8 +295,8 @@ private void setChatTimeout(ChatMessageContext chatMessageContext) { * @return true if web search is enabled */ private boolean isWebSearchEnabled() { - return !SettingsStateService.getInstance().getTavilySearchKey().isEmpty() || - !SettingsStateService.getInstance().getGoogleSearchKey().isEmpty(); + return !LLMStateService.getInstance().getTavilySearchKey().isEmpty() || + !LLMStateService.getInstance().getGoogleSearchKey().isEmpty(); } /** @@ -327,13 +328,13 @@ private void disableButtons() { * Set the search buttons visibility based on settings. */ public void configureSearchButtonsVisibility() { - if (SettingsStateService.getInstance().getHideSearchButtonsFlag()) { + if (LLMStateService.getInstance().getHideSearchButtonsFlag()) { tavilySearchBtn.setVisible(false); googleSearchBtn.setVisible(false); } else { - tavilySearchBtn.setVisible(!SettingsStateService.getInstance().getTavilySearchKey().isEmpty()); - googleSearchBtn.setVisible(!SettingsStateService.getInstance().getGoogleSearchKey().isEmpty() && - !SettingsStateService.getInstance().getGoogleCSIKey().isEmpty()); + tavilySearchBtn.setVisible(!LLMStateService.getInstance().getTavilySearchKey().isEmpty()); + googleSearchBtn.setVisible(!LLMStateService.getInstance().getGoogleSearchKey().isEmpty() && + !LLMStateService.getInstance().getGoogleCSIKey().isEmpty()); } } } diff --git a/src/main/java/com/devoxx/genie/ui/panel/PromptOutputPanel.java b/src/main/java/com/devoxx/genie/ui/panel/PromptOutputPanel.java index e4b3f5b5..d4300eca 100644 --- a/src/main/java/com/devoxx/genie/ui/panel/PromptOutputPanel.java +++ b/src/main/java/com/devoxx/genie/ui/panel/PromptOutputPanel.java @@ -1,8 +1,8 @@ package com.devoxx.genie.ui.panel; import com.devoxx.genie.model.request.ChatMessageContext; -import com.devoxx.genie.service.settings.SettingsStateService; import com.devoxx.genie.ui.component.ExpandablePanel; +import com.devoxx.genie.ui.settings.llm.LLMStateService; import com.devoxx.genie.ui.util.HelpUtil; import com.intellij.ui.components.JBPanel; import com.intellij.ui.components.JBScrollPane; @@ -88,7 +88,7 @@ public void addUserPrompt(ChatMessageContext chatMessageContext) { UserPromptPanel userPromptPanel = new UserPromptPanel(container, chatMessageContext); - if (!SettingsStateService.getInstance().getStreamMode()) { + if (!LLMStateService.getInstance().getStreamMode()) { waitingPanel.showMsg(); userPromptPanel.add(waitingPanel, BorderLayout.SOUTH); } diff --git a/src/main/java/com/devoxx/genie/ui/settings/LLMConfigManager.java b/src/main/java/com/devoxx/genie/ui/settings/LLMConfigManager.java deleted file mode 100644 index b2cc78b1..00000000 --- a/src/main/java/com/devoxx/genie/ui/settings/LLMConfigManager.java +++ /dev/null @@ -1,372 +0,0 @@ -package com.devoxx.genie.ui.settings; - -import com.devoxx.genie.service.settings.SettingsStateService; -import com.devoxx.genie.ui.topic.AppTopics; -import com.devoxx.genie.ui.util.DoubleConverter; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.options.Configurable; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.ui.JBUI; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.text.DefaultFormatterFactory; -import javax.swing.text.NumberFormatter; -import java.awt.*; -import java.awt.event.ItemEvent; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.Locale; -import java.util.Objects; -import java.util.function.Consumer; - -import static com.intellij.openapi.options.Configurable.isFieldModified; - -public class LLMConfigManager implements Configurable { - - private final DoubleConverter doubleConverter; - - private JFormattedTextField temperatureField; - private JFormattedTextField topPField; - - private JFormattedTextField timeoutField; - private JFormattedTextField retryField; - private JFormattedTextField chatMemorySizeField; - - private JTextField maxOutputTokensField; - - private JCheckBox astModeCheckBox; - private JCheckBox astParentClassCheckBox; - private JCheckBox astReferenceFieldCheckBox; - private JCheckBox astReferenceClassesCheckBox; - - private JCheckBox streamModeCheckBox; - - public LLMConfigManager() { - doubleConverter = new DoubleConverter(); - } - - @Nls - @Override - public String getDisplayName() { - return "Devoxx Genie Settings"; - } - - @Nullable - @Override - public JComponent createComponent() { - SettingsStateService settings = SettingsStateService.getInstance(); - - JPanel settingsPanel = new JPanel(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.anchor = GridBagConstraints.WEST; - - setTitle("LLM Settings", settingsPanel, gbc); - - streamModeCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Enable Stream Mode (Beta)", settings.getStreamMode(), - "Streaming response does not support (yet) copy code buttons to clipboard", false); - - setTitle("LLM Parameters", settingsPanel, gbc); - - chatMemorySizeField = addFormattedFieldWithLabel(settingsPanel, gbc, "Chat memory size:", settings.getTemperature()); - temperatureField = addFormattedFieldWithLabel(settingsPanel, gbc, "Temperature:", settings.getTemperature()); - topPField = addFormattedFieldWithLabel(settingsPanel, gbc, "Top-P:", settings.getTopP()); - maxOutputTokensField = addTextFieldWithLabel(settingsPanel, gbc, "Maximum output tokens :", settings.getMaxOutputTokens()); - timeoutField = addFormattedFieldWithLabel(settingsPanel, gbc, "Timeout (in secs):", settings.getTimeout()); - retryField = addFormattedFieldWithLabel(settingsPanel, gbc, "Maximum retries :", settings.getMaxRetries()); - - setTitle("Abstract Syntax Tree Config", settingsPanel, gbc); - astModeCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Enable AST Mode (Beta)", settings.getAstMode(), - "Enable Abstract Syntax Tree mode for code generation, results in including related classes in the prompt.", false); - astParentClassCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Include project parent class(es)", settings.getAstParentClass(), "", true); - astReferenceClassesCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Include class references", settings.getAstClassReference(), "", true); - astReferenceFieldCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Include field references", settings.getAstFieldReference(), "", true); - - astModeCheckBox.addItemListener(e -> { - boolean selected = e.getStateChange() == ItemEvent.SELECTED; - astParentClassCheckBox.setEnabled(selected); - astReferenceClassesCheckBox.setEnabled(selected); - astReferenceFieldCheckBox.setEnabled(selected); - }); - - return settingsPanel; - } - - /** - * Set the title of the settings panel - * - * @param title the title - * @param settingsPanel the settings panel - * @param gbc the grid bag constraints - */ - private void setTitle(String title, - @NotNull JPanel settingsPanel, - @NotNull GridBagConstraints gbc) { - JLabel titleLabel = new JLabel(title); - - gbc.insets = JBUI.insets(10, 0); - settingsPanel.add(titleLabel, gbc); - - // Reset the insets for the next component - gbc.insets = JBUI.emptyInsets(); - - // Add vertical spacing below the title - gbc.weighty = 1.0; // Allow the empty space to expand vertically - settingsPanel.add(new JLabel(), gbc); - - // Reset the constraints for the next component - gbc.weighty = 0.0; - resetGbc(gbc); - } - - /** - * Add a text field with label - * @param panel the panel - * @param gbc the gridbag constraints - * @param label the label - * @param value the value - * @return the text field - */ - private @NotNull JTextField addTextFieldWithLabel(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - String value) { - panel.add(new JLabel(label), gbc); - gbc.gridx++; - JTextField textField = new JTextField(value); - panel.add(textField, gbc); - resetGbc(gbc); - return textField; - } - - /** - * Add a formatted field with label - * - * @param panel the panel - * @param gbc the gridbag constraints - * @param label the label - * @param value the value - * @return the formatted field - */ - private @NotNull JFormattedTextField addFormattedFieldWithLabel(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - Number value) { - panel.add(new JLabel(label), gbc); - gbc.gridx++; - JFormattedTextField formattedField = new JFormattedTextField(); - setValue(formattedField, value); - panel.add(formattedField, gbc); - resetGbc(gbc); - return formattedField; - } - - /** - * Add a formatted field with label - * - * @param panel the panel - * @param gbc the grid bag constraints - * @param label the label - * @param value the value - * @param tooltip the tooltip - * @return the formatted field - */ - private @NotNull JCheckBox addCheckBoxWithLabel(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - Boolean value, - @NotNull String tooltip, - boolean labelInNextColumn) { - JCheckBox checkBox = new JCheckBox(); - if (!tooltip.isEmpty()) { - checkBox.setToolTipText(tooltip); - } - if (value != null) { - checkBox.setSelected(value); - } - - if (labelInNextColumn) { - JPanel jPanel = new JPanel(); - jPanel.setLayout(new BorderLayout()); - jPanel.add(new JLabel(label), BorderLayout.CENTER); - jPanel.add(checkBox, BorderLayout.WEST); - gbc.gridx++; - panel.add(jPanel, gbc); - } else { - panel.add(new JLabel(label), gbc); - gbc.gridx++; - panel.add(checkBox, gbc); - } - - resetGbc(gbc); - return checkBox; - } - - private void resetGbc(@NotNull GridBagConstraints gbc) { - gbc.gridx = 0; - gbc.gridy++; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1.0; - } - - @Override - public boolean isModified() { - SettingsStateService settings = SettingsStateService.getInstance(); - - boolean isModified = false; - isModified |= !settings.getStreamMode().equals(streamModeCheckBox.isSelected()); - - isModified |= isFieldModified(temperatureField, Objects.requireNonNull(doubleConverter.toString(settings.getTemperature()))); - isModified |= isFieldModified(topPField, Objects.requireNonNull(doubleConverter.toString(settings.getTopP()))); - isModified |= isFieldModified(timeoutField, settings.getTimeout()); - isModified |= isFieldModified(maxOutputTokensField, settings.getMaxOutputTokens()); - isModified |= isFieldModified(retryField, settings.getMaxRetries()); - isModified |= isFieldModified(chatMemorySizeField, settings.getChatMemorySize()); - - isModified |= !settings.getAstMode().equals(astModeCheckBox.isSelected()); - isModified |= !settings.getAstParentClass().equals(astParentClassCheckBox.isSelected()); - isModified |= !settings.getAstClassReference().equals(astReferenceClassesCheckBox.isSelected()); - isModified |= !settings.getAstFieldReference().equals(astReferenceFieldCheckBox.isSelected()); - - return isModified; - } - - @Override - public void apply() { - SettingsStateService settings = SettingsStateService.getInstance(); - - boolean apiKeyModified = false; - - if (apiKeyModified) { - // Only notify the listener if an API key has changed, so we can refresh the LLM providers list in the UI - notifySettingsChanged(); - } - - updateSettingIfModified(temperatureField, doubleConverter.toString(settings.getTemperature()), value -> settings.setTemperature(doubleConverter.fromString(value))); - updateSettingIfModified(topPField, doubleConverter.toString(settings.getTopP()), value -> settings.setTopP(doubleConverter.fromString(value))); - updateSettingIfModified(timeoutField, settings.getTimeout(), value -> settings.setTimeout(safeCastToInteger(value))); - updateSettingIfModified(retryField, settings.getMaxRetries(), value -> settings.setMaxRetries(safeCastToInteger(value))); - updateSettingIfModified(maxOutputTokensField, settings.getMaxOutputTokens(), settings::setMaxOutputTokens); - - updateSettingIfModified(astModeCheckBox, settings.getAstMode(), value -> settings.setAstMode(Boolean.parseBoolean(value))); - updateSettingIfModified(astParentClassCheckBox, settings.getAstParentClass(), value -> settings.setAstParentClass(Boolean.parseBoolean(value))); - updateSettingIfModified(astReferenceClassesCheckBox, settings.getAstClassReference(), value -> settings.setAstClassReference(Boolean.parseBoolean(value))); - updateSettingIfModified(astReferenceFieldCheckBox, settings.getAstFieldReference(), value -> settings.setAstFieldReference(Boolean.parseBoolean(value))); - - // Notify the listeners if the chat memory size has changed - if (updateSettingIfModified(chatMemorySizeField, settings.getChatMemorySize(), value -> settings.setChatMemorySize(safeCastToInteger(value)))) { - notifyChatMemorySizeChangeListeners(); - } - - updateSettingIfModified(streamModeCheckBox, settings.getStreamMode(), value -> settings.setStreamMode(Boolean.parseBoolean(value))); - } - - /** - * Update the setting if the field value has changed - * @param field the field - * @param currentValue the current value - * @param updateAction the update action - */ - public boolean updateSettingIfModified(JComponent field, - Object currentValue, - Consumer updateAction) { - String newValue = extractStringValue(field); - if (newValue != null && !newValue.equals(currentValue)) { - updateAction.accept(newValue); - return true; - } - return false; - } - - /** - * Notify the chat memory size change listeners - */ - public void notifyChatMemorySizeChangeListeners() { - ApplicationManager.getApplication().getMessageBus() - .syncPublisher(AppTopics.CHAT_MEMORY_SIZE_TOPIC) - .onChatMemorySizeChanged(SettingsStateService.getInstance().getChatMemorySize()); - } - - /** - * Extract the string value from the field - * @param field the field - * @return the string value - */ - private @Nullable String extractStringValue(JComponent field) { - if (field instanceof JTextField jtextfield) { - return jtextfield.getText(); - } else if (field instanceof JCheckBox jcheckbox) { - return Boolean.toString(jcheckbox.isSelected()); - } - return null; - } - - /** - * Notify the listeners that the settings have changed - */ - private void notifySettingsChanged() { - MessageBus messageBus = ApplicationManager.getApplication().getMessageBus(); - messageBus.syncPublisher(AppTopics.SETTINGS_CHANGED_TOPIC).settingsChanged(); - } - - @Override - public void reset() { - SettingsStateService settingsState = SettingsStateService.getInstance(); - - chatMemorySizeField.setText(String.valueOf(settingsState.getChatMemorySize())); - maxOutputTokensField.setText(settingsState.getMaxOutputTokens()); - - astReferenceFieldCheckBox.setSelected(settingsState.getAstFieldReference()); - astParentClassCheckBox.setSelected(settingsState.getAstParentClass()); - astReferenceClassesCheckBox.setSelected(settingsState.getAstClassReference()); - streamModeCheckBox.setSelected(settingsState.getStreamMode()); - - setValue(temperatureField, settingsState.getTemperature()); - setValue(topPField, settingsState.getTopP()); - setValue(timeoutField, settingsState.getTimeout()); - setValue(retryField, settingsState.getMaxRetries()); - setValue(chatMemorySizeField, settingsState.getChatMemorySize()); - } - - /** - * Set the value of the field - * @param field the field - * @param value the value - */ - private static void setValue(JFormattedTextField field, Number value) { - try { - NumberFormat format = NumberFormat.getInstance(Locale.getDefault()); - - if (value instanceof Double) { - if (format instanceof DecimalFormat) { - ((DecimalFormat) format).applyPattern("#0.00"); // Ensures one decimal place in the display - } - } else { - format.setParseIntegerOnly(true); - } - field.setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(format))); - field.setValue(value); - } catch (IllegalArgumentException e) { - // Handle the case where the string cannot be parsed to a number - field.setValue(0); - } - } - - /** - * Safely cast a string to an integer - * - * @param value the string value - * @return the integer value - */ - private @NotNull Integer safeCastToInteger(String value) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return 0; - } - } -} diff --git a/src/main/java/com/devoxx/genie/ui/settings/LLMSettingsManager.java b/src/main/java/com/devoxx/genie/ui/settings/LLMSettingsManager.java deleted file mode 100644 index 9f6e697e..00000000 --- a/src/main/java/com/devoxx/genie/ui/settings/LLMSettingsManager.java +++ /dev/null @@ -1,359 +0,0 @@ -package com.devoxx.genie.ui.settings; - -import com.devoxx.genie.service.settings.SettingsStateService; -import com.devoxx.genie.ui.topic.AppTopics; -import com.devoxx.genie.ui.util.NotificationUtil; -import com.intellij.ide.BrowserUtil; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.ui.JBUI; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ItemEvent; -import java.util.function.Consumer; - -import static com.intellij.openapi.options.Configurable.isFieldModified; - -public class LLMSettingsManager implements Configurable { - - private JTextField ollamaUrlField; - private JTextField lmstudioUrlField; - private JTextField gpt4allUrlField; - private JTextField janUrlField; - - private JPasswordField openAiKeyField; - private JPasswordField mistralKeyField; - private JPasswordField anthropicKeyField; - private JPasswordField groqKeyField; - private JPasswordField deepInfraKeyField; - private JPasswordField geminiKeyField; - - private JPasswordField tavilySearchKeyField; - private JPasswordField googleSearchKeyField; - private JPasswordField googleCSIKeyField; - - private JCheckBox hideSearchCheckBox; - - @Nls - @Override - public String getDisplayName() { - return "Devoxx Genie Settings"; - } - - @Nullable - @Override - public JComponent createComponent() { - SettingsStateService settings = SettingsStateService.getInstance(); - - JPanel settingsPanel = new JPanel(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.anchor = GridBagConstraints.WEST; - - // Helper method to add a text field with label - setTitle("Local Large Language Models", settingsPanel, gbc); - - ollamaUrlField = addFieldWithLinkButton(settingsPanel, gbc, "Ollama URL:", settings.getOllamaModelUrl(), "https://ollama.com/"); - lmstudioUrlField = addFieldWithLinkButton(settingsPanel, gbc, "LMStudio URL:", settings.getLmstudioModelUrl(), "https://lmstudio.ai/"); - gpt4allUrlField = addFieldWithLinkButton(settingsPanel, gbc, "GPT4All URL:", settings.getGpt4allModelUrl(), "https://gpt4all.io/"); - janUrlField = addFieldWithLinkButton(settingsPanel, gbc, "Jan URL:", settings.getJanModelUrl(), "https://jan.ai/download"); - - setTitle("Cloud based Large Language Models", settingsPanel, gbc); - - openAiKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "OpenAI API Key :", settings.getOpenAIKey(), "https://platform.openai.com/api-keys"); - mistralKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Mistral API Key :", settings.getMistralKey(), "https://console.mistral.ai/api-keys"); - anthropicKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Anthropic API Key :", settings.getAnthropicKey(), "https://console.anthropic.com/settings/keys"); - groqKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Groq API Key :", settings.getGroqKey(), "https://console.groq.com/keys"); - deepInfraKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "DeepInfra API Key :", settings.getDeepInfraKey(), "https://deepinfra.com/dash/api_keys"); - geminiKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Gemini API Key :", settings.getGeminiKey(), "https://aistudio.google.com/app/apikey"); - - setTitle("Search Providers", settingsPanel, gbc); - hideSearchCheckBox = addCheckBoxWithLabel(settingsPanel, gbc, "Hide Search Providers", false, "", false); - tavilySearchKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Tavily Web Search API Key :", settings.getTavilySearchKey(), "https://app.tavily.com/home"); - googleSearchKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Google Web Search API Key :", settings.getGoogleSearchKey(), "https://developers.google.com/custom-search/docs/paid_element#api_key"); - googleCSIKeyField = addFieldWithLabelPasswordAndLinkButton(settingsPanel, gbc, "Google Custom Search Engine ID :", settings.getGoogleCSIKey(), "https://programmablesearchengine.google.com/controlpanel/create"); - - hideSearchCheckBox.addItemListener(e -> { - boolean selected = e.getStateChange() == ItemEvent.SELECTED; - tavilySearchKeyField.setEnabled(!selected); - googleSearchKeyField.setEnabled(!selected); - googleCSIKeyField.setEnabled(!selected); - }); - - return settingsPanel; - } - - /** - * Set the title of the settings panel - * - * @param title the title - * @param settingsPanel the settings panel - * @param gbc the grid bag constraints - */ - private void setTitle(String title, - @NotNull JPanel settingsPanel, - @NotNull GridBagConstraints gbc) { - JLabel titleLabel = new JLabel(title); - - gbc.insets = JBUI.insets(10, 0); - settingsPanel.add(titleLabel, gbc); - - // Reset the insets for the next component - gbc.insets = JBUI.emptyInsets(); - - // Add vertical spacing below the title - gbc.weighty = 1.0; // Allow the empty space to expand vertically - settingsPanel.add(new JLabel(), gbc); - - // Reset the constraints for the next component - gbc.weighty = 0.0; - resetGbc(gbc); - } - - /** - * Add a field with label and a link button - * - * @param panel the panel - * @param gbc the gridbag constraints - * @param label the label - * @param value the value - * @param url the url - * @return the text field - */ - private @NotNull JTextField addFieldWithLinkButton(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - String value, - String url) { - String wwwEmoji = "\uD83D\uDD17"; - JButton btnApiKey = createButton(wwwEmoji, "Download from", url); - panel.add(new JLabel(label), gbc); - gbc.gridx++; - JPanel jPanel = new JPanel(); - jPanel.setLayout(new BorderLayout()); - JTextField textField = new JTextField(value); - jPanel.add(textField, BorderLayout.CENTER); - jPanel.add(btnApiKey, BorderLayout.WEST); - panel.add(jPanel, gbc); - resetGbc(gbc); - return textField; - } - - /** - * Add field with label, password and link button - * - * @param panel the panel - * @param gbc the gridbag constraints - * @param label the label - * @param value the value - * @param url the url - * @return the password field - */ - private @NotNull JPasswordField addFieldWithLabelPasswordAndLinkButton(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - String value, - String url) { - String keyEmoji = "\uD83D\uDD11"; - JButton btnApiKey = createButton(keyEmoji, "Get your API Key from ", url); - panel.add(new JLabel(label), gbc); - gbc.gridx++; - JPanel jPanel = new JPanel(); - jPanel.setLayout(new BorderLayout()); - JPasswordField passwordField = new JPasswordField(value); - passwordField.setEchoChar('*'); - jPanel.add(passwordField, BorderLayout.CENTER); - jPanel.add(btnApiKey, BorderLayout.WEST); - panel.add(jPanel, gbc); - resetGbc(gbc); - return passwordField; - } - - /** - * Create a button with emoji and tooltip message and open the URL in the browser - * - * @param emoji the emoji to use in the button - * @param toolTipMsg the tooltip message - * @param url the url to open when clicked - * @return the created button - */ - private @NotNull JButton createButton(String emoji, - String toolTipMsg, - String url) { - JButton btnApiKey = new JButton(emoji); - btnApiKey.setToolTipText(toolTipMsg + " " + url); - btnApiKey.addActionListener(e -> { - try { - BrowserUtil.open(url); - } catch (Exception ex) { - Project project = ProjectManager.getInstance().getOpenProjects()[0]; - NotificationUtil.sendNotification(project, "Error: Unable to open the link"); - } - }); - return btnApiKey; - } - - /** - * Add a formatted field with label - * - * @param panel the panel - * @param gbc the grid bag constraints - * @param label the label - * @param value the value - * @param tooltip the tooltip - * @return the formatted field - */ - private @NotNull JCheckBox addCheckBoxWithLabel(@NotNull JPanel panel, - GridBagConstraints gbc, - String label, - Boolean value, - @NotNull String tooltip, - boolean labelInNextColumn) { - JCheckBox checkBox = new JCheckBox(); - if (!tooltip.isEmpty()) { - checkBox.setToolTipText(tooltip); - } - if (value != null) { - checkBox.setSelected(value); - } - - if (labelInNextColumn) { - JPanel jPanel = new JPanel(); - jPanel.setLayout(new BorderLayout()); - jPanel.add(new JLabel(label), BorderLayout.CENTER); - jPanel.add(checkBox, BorderLayout.WEST); - gbc.gridx++; - panel.add(jPanel, gbc); - } else { - panel.add(new JLabel(label), gbc); - gbc.gridx++; - panel.add(checkBox, gbc); - } - - resetGbc(gbc); - return checkBox; - } - - private void resetGbc(@NotNull GridBagConstraints gbc) { - gbc.gridx = 0; - gbc.gridy++; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1.0; - } - - @Override - public boolean isModified() { - SettingsStateService settings = SettingsStateService.getInstance(); - - boolean isModified = isFieldModified(ollamaUrlField, settings.getOllamaModelUrl()); - isModified |= isFieldModified(lmstudioUrlField, settings.getLmstudioModelUrl()); - isModified |= isFieldModified(gpt4allUrlField, settings.getGpt4allModelUrl()); - isModified |= isFieldModified(janUrlField, settings.getJanModelUrl()); - - isModified |= isFieldModified(openAiKeyField, settings.getOpenAIKey()); - isModified |= isFieldModified(mistralKeyField, settings.getMistralKey()); - isModified |= isFieldModified(anthropicKeyField, settings.getAnthropicKey()); - isModified |= isFieldModified(groqKeyField, settings.getGroqKey()); - isModified |= isFieldModified(deepInfraKeyField, settings.getDeepInfraKey()); - isModified |= isFieldModified(geminiKeyField, settings.getGeminiKey()); - - isModified |= !settings.getHideSearchButtonsFlag().equals(hideSearchCheckBox.isSelected()); - isModified |= isFieldModified(tavilySearchKeyField, settings.getTavilySearchKey()); - isModified |= isFieldModified(googleSearchKeyField, settings.getGoogleSearchKey()); - isModified |= isFieldModified(googleCSIKeyField, settings.getGoogleCSIKey()); - - return isModified; - } - - @Override - public void apply() { - SettingsStateService settings = SettingsStateService.getInstance(); - - boolean apiKeyModified = false; - apiKeyModified |= updateSettingIfModified(openAiKeyField, settings.getOpenAIKey(), settings::setOpenAIKey); - apiKeyModified |= updateSettingIfModified(mistralKeyField, settings.getMistralKey(), settings::setMistralKey); - apiKeyModified |= updateSettingIfModified(anthropicKeyField, settings.getAnthropicKey(), settings::setAnthropicKey); - apiKeyModified |= updateSettingIfModified(groqKeyField, settings.getGroqKey(), settings::setGroqKey); - apiKeyModified |= updateSettingIfModified(deepInfraKeyField, settings.getDeepInfraKey(), settings::setDeepInfraKey); - apiKeyModified |= updateSettingIfModified(geminiKeyField, settings.getGeminiKey(), settings::setGeminiKey); - - apiKeyModified |= updateSettingIfModified(hideSearchCheckBox, settings.getHideSearchButtonsFlag(), value -> - settings.setHideSearchButtonsFlag(Boolean.parseBoolean(value)) - ); - apiKeyModified |= updateSettingIfModified(tavilySearchKeyField, settings.getTavilySearchKey(), settings::setTavilySearchKey); - apiKeyModified |= updateSettingIfModified(googleSearchKeyField, settings.getGoogleSearchKey(), settings::setGoogleSearchKey); - apiKeyModified |= updateSettingIfModified(googleCSIKeyField, settings.getGoogleCSIKey(), settings::setGoogleCSIKey); - - if (apiKeyModified) { - // Only notify the listener if an API key has changed, so we can refresh the LLM providers list in the UI - notifySettingsChanged(); - } - updateSettingIfModified(hideSearchCheckBox, settings.getHideSearchButtonsFlag(), value -> { - settings.setHideSearchButtonsFlag(Boolean.parseBoolean(value)); - }); - - updateSettingIfModified(ollamaUrlField, settings.getOllamaModelUrl(), settings::setOllamaModelUrl); - updateSettingIfModified(lmstudioUrlField, settings.getLmstudioModelUrl(), settings::setLmstudioModelUrl); - updateSettingIfModified(gpt4allUrlField, settings.getGpt4allModelUrl(), settings::setGpt4allModelUrl); - updateSettingIfModified(janUrlField, settings.getJanModelUrl(), settings::setJanModelUrl); - } - - /** - * Update the setting if the field value has changed - * @param field the field - * @param currentValue the current value - * @param updateAction the update action - */ - public boolean updateSettingIfModified(JComponent field, - Object currentValue, - Consumer updateAction) { - String newValue = extractStringValue(field); - if (newValue != null && !newValue.equals(currentValue)) { - updateAction.accept(newValue); - return true; - } - return false; - } - - /** - * Extract the string value from the field - * @param field the field - * @return the string value - */ - private @Nullable String extractStringValue(JComponent field) { - if (field instanceof JTextField jtextfield) { - return jtextfield.getText(); - } else if (field instanceof JCheckBox jcheckbox) { - return Boolean.toString(jcheckbox.isSelected()); - } - return null; - } - - /** - * Notify the listeners that the settings have changed - */ - private void notifySettingsChanged() { - MessageBus messageBus = ApplicationManager.getApplication().getMessageBus(); - messageBus.syncPublisher(AppTopics.SETTINGS_CHANGED_TOPIC).settingsChanged(); - } - - @Override - public void reset() { - SettingsStateService settingsState = SettingsStateService.getInstance(); - - ollamaUrlField.setText(settingsState.getOllamaModelUrl()); - lmstudioUrlField.setText(settingsState.getLmstudioModelUrl()); - gpt4allUrlField.setText(settingsState.getGpt4allModelUrl()); - janUrlField.setText(settingsState.getJanModelUrl()); - - hideSearchCheckBox.setSelected(settingsState.getHideSearchButtonsFlag()); - } -} diff --git a/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsComponent.java b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsComponent.java index 18cece4a..a986b40b 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsComponent.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsComponent.java @@ -1,6 +1,5 @@ package com.devoxx.genie.ui.settings.llm; -import com.devoxx.genie.service.settings.llm.LLMStateService; import com.devoxx.genie.ui.util.NotificationUtil; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.project.Project; @@ -16,11 +15,11 @@ public class LLMSettingsComponent { + public LLMStateService llmStateService = LLMStateService.getInstance(); + public static final String LINK_EMOJI = "\uD83D\uDD17"; public static final String PASSWORD_EMOJI = "\uD83D\uDD11"; - public LLMStateService llmStateService = LLMStateService.getInstance(); - @Getter private final JTextField ollamaModelUrlField = new JTextField(llmStateService.getOllamaModelUrl()); @Getter @@ -49,12 +48,19 @@ public class LLMSettingsComponent { private final JPasswordField googleSearchApiKeyField = new JPasswordField(llmStateService.getGoogleSearchKey()); @Getter private final JPasswordField googleCSIApiKeyField = new JPasswordField(llmStateService.getGoogleCSIKey()); + @Getter + private final JCheckBox streamModeCheckBox = new JCheckBox("", llmStateService.getStreamMode()); @Getter private final JPanel panel; public LLMSettingsComponent() { panel = FormBuilder.createFormBuilder() + .addComponent(new JXTitledSeparator("Local Large Language Response")) + .addVerticalGap(5) + .addComponent(new JLabel("Enable Stream Mode (Beta)")) + .addComponent(streamModeCheckBox) + .addVerticalGap(20) .addComponent(new JXTitledSeparator("Local Large Language Models")) .addVerticalGap(5) .addComponent(new JLabel("Ollama URL")) @@ -83,14 +89,14 @@ public LLMSettingsComponent() { .addVerticalGap(20) .addComponent(new JXTitledSeparator("Search Providers")) .addVerticalGap(5) - .addComponent(new JLabel("Hide Search Providers")) - .addComponent(hideSearchButtonsField) .addComponent(new JLabel("Tavily Web Search API Key")) .addComponent(createTextWithPasswordButton(tavilySearchApiKeyField, "https://app.tavily.com/home")) .addComponent(new JLabel("Google Web Search API Key")) .addComponent(createTextWithPasswordButton(googleSearchApiKeyField, "https://developers.google.com/custom-search/docs/paid_element#api_key")) .addComponent(new JLabel("Google Custom Search Engine ID")) .addComponent(createTextWithPasswordButton(googleCSIApiKeyField, "https://programmablesearchengine.google.com/controlpanel/create")) + .addComponent(new JLabel("Hide Search Providers")) + .addComponent(hideSearchButtonsField) .getPanel(); hideSearchButtonsField.addItemListener(e -> { diff --git a/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsConfigurable.java b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsConfigurable.java index c0a581f2..5efd80dd 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsConfigurable.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMSettingsConfigurable.java @@ -1,6 +1,5 @@ package com.devoxx.genie.ui.settings.llm; -import com.devoxx.genie.service.settings.llm.LLMStateService; import com.intellij.openapi.options.Configurable; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.Nullable; @@ -55,6 +54,8 @@ public boolean isModified() { isModified |= isFieldModified(llmSettingsComponent.getDeepInfraApiKeyField(), settings.getDeepInfraKey()); isModified |= isFieldModified(llmSettingsComponent.getGeminiApiKeyField(), settings.getGeminiKey()); + isModified |= !settings.getStreamMode().equals(llmSettingsComponent.getStreamModeCheckBox().isSelected()); + isModified |= !settings.getHideSearchButtonsFlag().equals(llmSettingsComponent.getHideSearchButtonsField().isSelected()); isModified |= isFieldModified(llmSettingsComponent.getTavilySearchApiKeyField(), settings.getTavilySearchKey()); isModified |= isFieldModified(llmSettingsComponent.getGoogleSearchApiKeyField(), settings.getGoogleSearchKey()); @@ -69,6 +70,22 @@ public boolean isModified() { public void apply() { LLMStateService settings = LLMStateService.getInstance(); + settings.setOllamaModelUrl(llmSettingsComponent.getOllamaModelUrlField().getText()); + settings.setLmstudioModelUrl(llmSettingsComponent.getLmStudioModelUrlField().getText()); + settings.setGpt4allModelUrl(llmSettingsComponent.getGpt4AllModelUrlField().getText()); + settings.setJanModelUrl(llmSettingsComponent.getJanModelUrlField().getText()); + + settings.setOpenAIKey(new String(llmSettingsComponent.getOpenAIKeyField().getPassword())); + settings.setMistralKey(new String(llmSettingsComponent.getMistralApiKeyField().getPassword())); + settings.setAnthropicKey(new String(llmSettingsComponent.getAnthropicApiKeyField().getPassword())); + settings.setGroqKey(new String(llmSettingsComponent.getGroqApiKeyField().getPassword())); + settings.setDeepInfraKey(new String(llmSettingsComponent.getDeepInfraApiKeyField().getPassword())); + settings.setGeminiKey(new String(llmSettingsComponent.getGeminiApiKeyField().getPassword())); + + settings.setHideSearchButtonsFlag(llmSettingsComponent.getHideSearchButtonsField().isSelected()); + settings.setTavilySearchKey(new String(llmSettingsComponent.getTavilySearchApiKeyField().getPassword())); + settings.setGoogleSearchKey(new String(llmSettingsComponent.getGoogleSearchApiKeyField().getPassword())); + settings.setGoogleCSIKey(new String(llmSettingsComponent.getGoogleCSIApiKeyField().getPassword())); } /** @@ -78,5 +95,22 @@ public void apply() { public void reset() { LLMStateService settings = LLMStateService.getInstance(); + llmSettingsComponent.getOllamaModelUrlField().setText(settings.getOllamaModelUrl()); + llmSettingsComponent.getLmStudioModelUrlField().setText(settings.getLmstudioModelUrl()); + llmSettingsComponent.getGpt4AllModelUrlField().setText(settings.getGpt4allModelUrl()); + llmSettingsComponent.getJanModelUrlField().setText(settings.getJanModelUrl()); + + llmSettingsComponent.getOpenAIKeyField().setText(settings.getOpenAIKey()); + llmSettingsComponent.getMistralApiKeyField().setText(settings.getMistralKey()); + llmSettingsComponent.getAnthropicApiKeyField().setText(settings.getAnthropicKey()); + llmSettingsComponent.getGroqApiKeyField().setText(settings.getGroqKey()); + llmSettingsComponent.getDeepInfraApiKeyField().setText(settings.getDeepInfraKey()); + llmSettingsComponent.getGeminiApiKeyField().setText(settings.getGeminiKey()); + + llmSettingsComponent.getHideSearchButtonsField().setSelected(settings.getHideSearchButtonsFlag()); + llmSettingsComponent.getTavilySearchApiKeyField().setText(settings.getTavilySearchKey()); + llmSettingsComponent.getGoogleSearchApiKeyField().setText(settings.getGoogleSearchKey()); + llmSettingsComponent.getGoogleCSIApiKeyField().setText(settings.getGoogleCSIKey()); + } } diff --git a/src/main/java/com/devoxx/genie/service/settings/llm/LLMStateService.java b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMStateService.java similarity index 93% rename from src/main/java/com/devoxx/genie/service/settings/llm/LLMStateService.java rename to src/main/java/com/devoxx/genie/ui/settings/llm/LLMStateService.java index 8db09a85..4f24d6d4 100644 --- a/src/main/java/com/devoxx/genie/service/settings/llm/LLMStateService.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llm/LLMStateService.java @@ -1,4 +1,4 @@ -package com.devoxx.genie.service.settings.llm; +package com.devoxx.genie.ui.settings.llm; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; @@ -45,6 +45,9 @@ public static LLMStateService getInstance() { private String googleCSIKey = ""; private String tavilySearchKey = ""; + private String lastSelectedProvider = ""; + private String lastSelectedModel = ""; + // Enable stream mode private Boolean streamMode = STREAM_MODE; diff --git a/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsComponent.java b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsComponent.java index c990cb53..dbac993b 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsComponent.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsComponent.java @@ -1,41 +1,88 @@ package com.devoxx.genie.ui.settings.llmconfig; -import com.devoxx.genie.service.settings.prompts.PromptSettingsStateService; +import com.intellij.ide.ui.UINumericRange; +import com.intellij.ui.JBIntSpinner; import com.intellij.util.ui.FormBuilder; import lombok.Getter; +import org.jdesktop.swingx.JXTitledSeparator; import javax.swing.*; +import java.awt.event.ItemEvent; public class LLMConfigSettingsComponent { - public PromptSettingsStateService promptSettingsStateService = PromptSettingsStateService.getInstance(); + public LLMConfigStateService llmConfigStateService = LLMConfigStateService.getInstance(); @Getter - private final JTextArea systemPromptField = new JTextArea(promptSettingsStateService.getSystemPrompt()); + private final JPanel panel; + @Getter - private final JTextArea testPromptField = new JTextArea(promptSettingsStateService.getTestPrompt()); + private final JBIntSpinner chatMemorySizeField = new JBIntSpinner(new UINumericRange(llmConfigStateService.getChatMemorySize(), 1, 100)); @Getter - private final JTextArea explainPromptField = new JTextArea(promptSettingsStateService.getExplainPrompt()); + private final JSpinner temperatureField = new JSpinner(new SpinnerNumberModel(llmConfigStateService.getTemperature().doubleValue(), 0.0d, 1.0d, 0.1d)); @Getter - private final JTextArea reviewPromptField = new JTextArea(promptSettingsStateService.getReviewPrompt()); + private final JSpinner topPField = new JSpinner(new SpinnerNumberModel(llmConfigStateService.getTopP().doubleValue(), 0.0d, 1.0d, 0.1d)); @Getter - private final JTextArea customPromptField = new JTextArea(promptSettingsStateService.getCustomPrompt()); - + private final JBIntSpinner maxOutputTokensField = new JBIntSpinner(new UINumericRange(llmConfigStateService.getMaxOutputTokens(), 1, 1_000_000)); @Getter - private final JPanel panel; + private final JBIntSpinner timeoutField = new JBIntSpinner(new UINumericRange(llmConfigStateService.getTimeout(), 1, 60)); + @Getter + private final JBIntSpinner retryField = new JBIntSpinner(new UINumericRange(llmConfigStateService.getMaxRetries(), 1, 5)); + @Getter + private final JCheckBox astMode = new JCheckBox("", llmConfigStateService.getAstMode()); + @Getter + private final JCheckBox astParentClassCheckBox = new JCheckBox("", llmConfigStateService.getAstParentClass()); + @Getter + private final JCheckBox astReferenceClassesCheckBox = new JCheckBox("", llmConfigStateService.getAstClassReference()); + @Getter + private final JCheckBox astReferenceFieldCheckBox = new JCheckBox("", llmConfigStateService.getAstFieldReference()); + public LLMConfigSettingsComponent() { + panel = FormBuilder.createFormBuilder() - .addComponent(new JLabel("System prompt :")) - .addComponent(systemPromptField) - .addComponent(new JLabel("Test prompt :")) - .addComponent(testPromptField) - .addComponent(new JLabel("Explain prompt :")) - .addComponent(explainPromptField) - .addComponent(new JLabel("Review prompt :")) - .addComponent(reviewPromptField) - .addComponent(new JLabel("Custom prompt :")) - .addComponent(customPromptField) + .addComponent(new JXTitledSeparator("Local Large Language Models")) + .addVerticalGap(5) + .addComponent(new JLabel("Chat Memory Size")) + .addComponent(chatMemorySizeField) + .addVerticalGap(5) + .addComponent(new JLabel("Temperature")) + .addComponent(temperatureField) + .addVerticalGap(5) + .addComponent(new JLabel("Top-P")) + .addComponent(topPField) + .addVerticalGap(5) + .addComponent(new JLabel("Maximum Output Tokens")) + .addComponent(maxOutputTokensField) + .addVerticalGap(5) + .addComponent(new JLabel("Timeout (in secs)")) + .addComponent(timeoutField) + .addVerticalGap(5) + .addComponent(new JLabel("Maximum Retries")) + .addComponent(retryField) + .addVerticalGap(5) + .addComponent(new JXTitledSeparator("Abstract Syntax Tree Config")) + .addVerticalGap(5) + .addComponent(new JLabel("Enable AST Mode (Beta)")) + .addComponent(astMode) + .addVerticalGap(5) + .addComponent(new JLabel("Automatically incorporate code into the prompt window context based on the selected AST options.")) + .addVerticalGap(5) + .addComponent(new JLabel("Include Project Parent Class(es)")) + .addComponent(astParentClassCheckBox) + .addVerticalGap(5) + .addComponent(new JLabel("Include Class References")) + .addComponent(astReferenceClassesCheckBox) + .addVerticalGap(5) + .addComponent(new JLabel("Include Field References")) + .addComponent(astReferenceFieldCheckBox) .getPanel(); + + astMode.addItemListener(e -> { + boolean selected = e.getStateChange() == ItemEvent.SELECTED; + astParentClassCheckBox.setEnabled(selected); + astReferenceClassesCheckBox.setEnabled(selected); + astReferenceFieldCheckBox.setEnabled(selected); + }); } } diff --git a/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsConfigurable.java b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsConfigurable.java index 8444e7bf..3b4b64f6 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsConfigurable.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigSettingsConfigurable.java @@ -1,19 +1,14 @@ package com.devoxx.genie.ui.settings.llmconfig; -import com.devoxx.genie.service.settings.SettingsStateService; -import com.devoxx.genie.service.settings.prompts.PromptSettingsStateService; import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.function.Consumer; public class LLMConfigSettingsConfigurable implements Configurable { - private final LLMConfigSettingsComponent promptSettingsComponent = new LLMConfigSettingsComponent(); + private final LLMConfigSettingsComponent llmConfigSettingsComponent = new LLMConfigSettingsComponent(); /** * Get the display name @@ -22,7 +17,7 @@ public class LLMConfigSettingsConfigurable implements Configurable { @Nls @Override public String getDisplayName() { - return "Prompts"; + return "LLM Settings"; } /** @@ -32,7 +27,7 @@ public String getDisplayName() { @Nullable @Override public JComponent createComponent() { - return promptSettingsComponent.getPanel(); + return llmConfigSettingsComponent.getPanel(); } /** @@ -41,30 +36,37 @@ public JComponent createComponent() { */ @Override public boolean isModified() { - PromptSettingsStateService settings = PromptSettingsStateService.getInstance(); + LLMConfigStateService settingsState = LLMConfigStateService.getInstance(); boolean isModified = false; - isModified |= !StringUtil.equals(promptSettingsComponent.getSystemPromptField().getText(), settings.getSystemPrompt()); - isModified |= !StringUtil.equals(promptSettingsComponent.getTestPromptField().getText(), settings.getTestPrompt()); - isModified |= !StringUtil.equals(promptSettingsComponent.getExplainPromptField().getText(), settings.getExplainPrompt()); - isModified |= !StringUtil.equals(promptSettingsComponent.getReviewPromptField().getText(), settings.getReviewPrompt()); - isModified |= !StringUtil.equals(promptSettingsComponent.getCustomPromptField().getText(), settings.getCustomPrompt()); + isModified |= ((Double)llmConfigSettingsComponent.getTemperatureField().getValue()) != settingsState.getTemperature(); + isModified |= ((Double)llmConfigSettingsComponent.getTopPField().getValue()) != settingsState.getTopP(); + isModified |= llmConfigSettingsComponent.getMaxOutputTokensField().getNumber() != settingsState.getMaxOutputTokens(); + isModified |= llmConfigSettingsComponent.getChatMemorySizeField().getNumber() != settingsState.getChatMemorySize(); + isModified |= llmConfigSettingsComponent.getTimeoutField().getNumber() != settingsState.getTimeout(); + isModified |= llmConfigSettingsComponent.getRetryField().getNumber() != settingsState.getMaxRetries(); + isModified |= !settingsState.getAstMode().equals(llmConfigSettingsComponent.getAstMode().isSelected()); + isModified |= !settingsState.getAstParentClass().equals(llmConfigSettingsComponent.getAstParentClassCheckBox().isSelected()); + isModified |= !settingsState.getAstClassReference().equals(llmConfigSettingsComponent.getAstReferenceClassesCheckBox().isSelected()); + isModified |= !settingsState.getAstFieldReference().equals(llmConfigSettingsComponent.getAstReferenceFieldCheckBox().isSelected()); return isModified; } - /** * Apply the changes to the settings */ @Override public void apply() { - SettingsStateService settings = SettingsStateService.getInstance(); - updateTextAreaIfModified(promptSettingsComponent.getSystemPromptField(), settings.getSystemPrompt(), settings::setSystemPrompt); - updateTextAreaIfModified(promptSettingsComponent.getTestPromptField(), settings.getTestPrompt(), settings::setTestPrompt); - updateTextAreaIfModified(promptSettingsComponent.getExplainPromptField(), settings.getExplainPrompt(), settings::setExplainPrompt); - updateTextAreaIfModified(promptSettingsComponent.getReviewPromptField(), settings.getReviewPrompt(), settings::setReviewPrompt); - updateTextAreaIfModified(promptSettingsComponent.getCustomPromptField(), settings.getCustomPrompt(), settings::setCustomPrompt); + LLMConfigStateService settingsState = LLMConfigStateService.getInstance(); + + settingsState.setTemperature(((Double)llmConfigSettingsComponent.getTemperatureField().getValue())); + settingsState.setTopP(((Double)llmConfigSettingsComponent.getTopPField().getValue())); + + settingsState.setChatMemorySize(llmConfigSettingsComponent.getChatMemorySizeField().getNumber()); + settingsState.setMaxOutputTokens(llmConfigSettingsComponent.getMaxOutputTokensField().getNumber()); + settingsState.setTimeout(llmConfigSettingsComponent.getTimeoutField().getNumber()); + settingsState.setMaxRetries(llmConfigSettingsComponent.getRetryField().getNumber()); } /** @@ -72,27 +74,14 @@ public void apply() { */ @Override public void reset() { - SettingsStateService settingsState = SettingsStateService.getInstance(); - promptSettingsComponent.getSystemPromptField().setText(settingsState.getSystemPrompt()); - promptSettingsComponent.getTestPromptField().setText(settingsState.getTestPrompt()); - promptSettingsComponent.getExplainPromptField().setText(settingsState.getExplainPrompt()); - promptSettingsComponent.getReviewPromptField().setText(settingsState.getReviewPrompt()); - promptSettingsComponent.getCustomPromptField().setText(settingsState.getCustomPrompt()); - } + LLMConfigStateService settingsState = LLMConfigStateService.getInstance(); + llmConfigSettingsComponent.getTemperatureField().setValue(settingsState.getTemperature()); + llmConfigSettingsComponent.getTopPField().setValue(settingsState.getTopP()); - /** - * Update the text area if the value has changed - * @param textArea the text area - * @param currentValue the current value - * @param updateAction the update action - */ - public void updateTextAreaIfModified(@NotNull JTextArea textArea, - Object currentValue, - Consumer updateAction) { - String newValue = textArea.getText(); - if (newValue != null && !newValue.equals(currentValue)) { - updateAction.accept(newValue); - } + llmConfigSettingsComponent.getMaxOutputTokensField().setNumber(settingsState.getMaxOutputTokens()); + llmConfigSettingsComponent.getChatMemorySizeField().setNumber(settingsState.getChatMemorySize()); + llmConfigSettingsComponent.getTimeoutField().setNumber(settingsState.getTimeout()); + llmConfigSettingsComponent.getRetryField().setNumber(settingsState.getMaxRetries()); } } diff --git a/src/main/java/com/devoxx/genie/service/settings/llmconfig/LLMConfigStateService.java b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigStateService.java similarity index 71% rename from src/main/java/com/devoxx/genie/service/settings/llmconfig/LLMConfigStateService.java rename to src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigStateService.java index 52f5bad5..5f77adb9 100644 --- a/src/main/java/com/devoxx/genie/service/settings/llmconfig/LLMConfigStateService.java +++ b/src/main/java/com/devoxx/genie/ui/settings/llmconfig/LLMConfigStateService.java @@ -1,13 +1,11 @@ -package com.devoxx.genie.service.settings.llmconfig; +package com.devoxx.genie.ui.settings.llmconfig; -import com.devoxx.genie.ui.util.DoubleConverter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.Service; 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 lombok.Getter; import lombok.Setter; import org.jetbrains.annotations.NotNull; @@ -27,26 +25,14 @@ public static LLMConfigStateService getInstance() { return ApplicationManager.getApplication().getService(LLMConfigStateService.class); } - // Prompt fields - private String systemPrompt = SYSTEM_PROMPT; - private String testPrompt = TEST_PROMPT; - private String reviewPrompt = REVIEW_PROMPT; - private String explainPrompt = EXPLAIN_PROMPT; - private String customPrompt = CUSTOM_PROMPT; - // LLM settings - @OptionTag(converter = DoubleConverter.class) private Double temperature = TEMPERATURE; - - @OptionTag(converter = DoubleConverter.class) private Double topP = TOP_P; private Integer timeout = TIMEOUT; private Integer maxRetries = MAX_RETRIES; private Integer chatMemorySize = MAX_MEMORY; - - // Was unable to make it work with Integer for some unknown reason - private String maxOutputTokens = MAX_OUTPUT_TOKENS.toString(); + private Integer maxOutputTokens = MAX_OUTPUT_TOKENS; // Last selected LLM provider and model name private String lastSelectedProvider; diff --git a/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsComponent.java b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsComponent.java index 78525adf..844edb8f 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsComponent.java +++ b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsComponent.java @@ -1,6 +1,5 @@ package com.devoxx.genie.ui.settings.prompt; -import com.devoxx.genie.service.settings.prompts.PromptSettingsStateService; import com.intellij.util.ui.FormBuilder; import lombok.Getter; import org.jdesktop.swingx.JXTitledSeparator; diff --git a/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsConfigurable.java b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsConfigurable.java index 1e698d11..a815e314 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsConfigurable.java +++ b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsConfigurable.java @@ -1,6 +1,5 @@ package com.devoxx.genie.ui.settings.prompt; -import com.devoxx.genie.service.settings.prompts.PromptSettingsStateService; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.Nls; diff --git a/src/main/java/com/devoxx/genie/service/settings/prompts/PromptSettingsStateService.java b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsStateService.java similarity index 96% rename from src/main/java/com/devoxx/genie/service/settings/prompts/PromptSettingsStateService.java rename to src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsStateService.java index 7301adcd..f10f2c45 100644 --- a/src/main/java/com/devoxx/genie/service/settings/prompts/PromptSettingsStateService.java +++ b/src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsStateService.java @@ -1,4 +1,4 @@ -package com.devoxx.genie.service.settings.prompts; +package com.devoxx.genie.ui.settings.prompt; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 4e60aa88..cf0e0a38 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -193,7 +193,7 @@ -