diff --git a/src/main/java/com/devoxx/genie/model/Constant.java b/src/main/java/com/devoxx/genie/model/Constant.java index c4f15125..ce070759 100644 --- a/src/main/java/com/devoxx/genie/model/Constant.java +++ b/src/main/java/com/devoxx/genie/model/Constant.java @@ -9,12 +9,6 @@ private Constant() { public static final String SYSTEM_PROMPT = """ You are a software developer IDEA plugin with expert knowledge in any programming language. - The Devoxx Genie plugin supports the following commands: - /test: write unit tests on selected code - /explain: explain the selected code - /review: review selected code - /help: show commands - The Devoxx Genie is open source and available at https://github.com/devoxx/DevoxxGenieIDEAPlugin. You can follow us on Bluesky @ https://bsky.app/profile/devoxxgenie.bsky.social. Do not include any more info which might be incorrect, like discord, documentation or other websites. @@ -27,13 +21,15 @@ private Constant() { public static final String REVIEW_PROMPT = "Review the selected code, can it be improved or are there any bugs?"; public static final String EXPLAIN_PROMPT = "Break down the code in simple terms to help a junior developer grasp its functionality."; public static final String TDG_PROMPT = "You are a professional Java developer. Give me a SINGLE FILE COMPLETE java implementation that will pass this test. Do not respond with a test. Give me only complete code and no snippets. Include imports and use the right package."; - public static final String FIND_PROMPT = "Perform semantic search on the project files using RAG and show matching files."; + public static final String FIND_PROMPT = "Perform semantic search on the project files using RAG and show matching files. (NOTE: The /find command requires RAG to be enabled in settings)"; + public static final String HELP_PROMPT = "Display help and available commands for the Genie Devoxx Plugin"; public static final String TEST_COMMAND = "test"; public static final String FIND_COMMAND = "find"; public static final String REVIEW_COMMAND = "review"; public static final String EXPLAIN_COMMAND = "explain"; public static final String TDG_COMMAND = "tdg"; + public static final String HELP_COMMAND = "help"; // The Local LLM Model URLs, these can be overridden in the settings page public static final String OLLAMA_MODEL_URL = "http://localhost:11434/"; diff --git a/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java b/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java index df14ab28..dea33aa6 100644 --- a/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java +++ b/src/main/java/com/devoxx/genie/service/ChatPromptExecutor.java @@ -22,11 +22,13 @@ import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.ConcurrentHashMap; import static com.devoxx.genie.model.Constant.FIND_COMMAND; +import static com.devoxx.genie.model.Constant.HELP_COMMAND; public class ChatPromptExecutor { @@ -183,10 +185,25 @@ public void stopPromptExecution(Project project) { private Optional getCommandFromPrompt(@NotNull ChatMessageContext chatMessageContext, PromptOutputPanel promptOutputPanel) { String prompt = chatMessageContext.getUserPrompt().trim(); - if (prompt.startsWith("/")) { - DevoxxGenieSettingsService settings = DevoxxGenieStateService.getInstance(); + DevoxxGenieSettingsService settings = DevoxxGenieStateService.getInstance(); + List customPrompts = settings.getCustomPrompts(); + + Optional matchingPrompt = customPrompts.stream() + .filter(customPrompt -> + prompt.equalsIgnoreCase("/" + customPrompt.getName()) + ) + .findFirst(); + + // if OK + if (matchingPrompt.isPresent()) { + // Check if the prompt is "/help" --> we display the help + if (matchingPrompt.get().getName().equalsIgnoreCase(HELP_COMMAND)) { + promptOutputPanel.showHelpText(); + return Optional.empty(); // Return empty since we handled the help case + } - if (prompt.toLowerCase().startsWith("/" + FIND_COMMAND + " ")) { + // Check for the /find command + if (matchingPrompt.get().getName().equalsIgnoreCase(FIND_COMMAND)) { if (Boolean.FALSE.equals(DevoxxGenieStateService.getInstance().getRagEnabled())) { NotificationUtil.sendNotification(chatMessageContext.getProject(), "The /find command requires RAG to be enabled in settings"); @@ -196,15 +213,9 @@ private Optional getCommandFromPrompt(@NotNull ChatMessageContext chatMe return Optional.of(prompt.substring(6).trim()); } - // Check for custom prompts - for (CustomPrompt customPrompt : settings.getCustomPrompts()) { - if (prompt.equalsIgnoreCase("/" + customPrompt.getName())) { - chatMessageContext.setCommandName(customPrompt.getName()); - return Optional.of(customPrompt.getPrompt()); - } - } - promptOutputPanel.showHelpText(); - return Optional.empty(); + // Set the command name and return the prompt + chatMessageContext.setCommandName(matchingPrompt.get().getName()); + return Optional.of(matchingPrompt.get().getPrompt()); } return Optional.of(prompt); } diff --git a/src/main/java/com/devoxx/genie/ui/component/input/CommandAutoCompleteTextField.java b/src/main/java/com/devoxx/genie/ui/component/input/CommandAutoCompleteTextField.java index e78a8956..d7556616 100644 --- a/src/main/java/com/devoxx/genie/ui/component/input/CommandAutoCompleteTextField.java +++ b/src/main/java/com/devoxx/genie/ui/component/input/CommandAutoCompleteTextField.java @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.List; +import static com.devoxx.genie.model.Constant.*; + public class CommandAutoCompleteTextField extends JBTextArea implements CustomPromptChangeListener { private static final Logger LOG = Logger.getInstance(CommandAutoCompleteTextField.class); @@ -46,11 +48,11 @@ public CommandAutoCompleteTextField(Project project) { private void initializeCommands() { commands.clear(); - commands.add("/test"); - commands.add("/explain"); - commands.add("/review"); - commands.add("/tdg"); - commands.add("/help"); + commands.add("/" + TEST_COMMAND); + commands.add("/" + EXPLAIN_COMMAND); + commands.add("/" + REVIEW_COMMAND); + commands.add("/" + TDG_COMMAND); + commands.add("/" + HELP_COMMAND); DevoxxGenieSettingsService stateService = DevoxxGenieStateService.getInstance(); for (CustomPrompt customPrompt : stateService.getCustomPrompts()) { diff --git a/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java b/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java index f7ceb651..33ea095a 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java +++ b/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java @@ -38,6 +38,15 @@ public static DevoxxGenieStateService getInstance() { private List customPrompts = new ArrayList<>(); + private final List defaultPrompts = Arrays.asList( + new CustomPrompt(TEST_COMMAND, TEST_PROMPT), + new CustomPrompt(EXPLAIN_COMMAND, EXPLAIN_PROMPT), + new CustomPrompt(REVIEW_COMMAND, REVIEW_PROMPT), + new CustomPrompt(TDG_COMMAND, TDG_PROMPT), + new CustomPrompt(FIND_COMMAND, FIND_PROMPT), + new CustomPrompt(HELP_COMMAND, HELP_PROMPT) + ); + private List languageModels = new ArrayList<>(); private Boolean showExecutionTime = true; @@ -160,16 +169,13 @@ public static DevoxxGenieStateService getInstance() { private List loadListeners = new ArrayList<>(); public DevoxxGenieStateService() { - initializeDefaultPrompts(); + initializeUserPrompt(); } - private void initializeDefaultPrompts() { - if (customPrompts.isEmpty()) { - customPrompts.add(new CustomPrompt(TEST_COMMAND, TEST_PROMPT)); - customPrompts.add(new CustomPrompt(EXPLAIN_COMMAND, EXPLAIN_PROMPT)); - customPrompts.add(new CustomPrompt(REVIEW_COMMAND, REVIEW_PROMPT)); - customPrompts.add(new CustomPrompt(FIND_COMMAND, FIND_PROMPT)); - customPrompts.add(new CustomPrompt(TDG_COMMAND, TDG_PROMPT)); + private void initializeUserPrompt() { + //If User prompt happens to be empty then we load the default list + if (customPrompts == null || customPrompts.isEmpty()) { + customPrompts = new ArrayList<>(defaultPrompts); } } @@ -182,7 +188,7 @@ public DevoxxGenieStateService getState() { public void loadState(@NotNull DevoxxGenieStateService state) { XmlSerializerUtil.copyBean(state, this); initializeDefaultCostsIfEmpty(); - initializeDefaultPrompts(); + initializeUserPrompt(); // Notify all listeners that the state has been loaded for (Runnable listener : loadListeners) { 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 833b5269..faac6d00 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 @@ -25,6 +25,8 @@ public class PromptSettingsComponent extends AbstractSettingsComponent { private static final int NAME_COLUMN = 0; private static final int PROMPT_COLUMN = 1; + + private final DevoxxGenieStateService settings; @Getter private final JTextArea systemPromptField = new JTextArea(stateService.getSystemPrompt()); @Getter @@ -48,7 +50,7 @@ public boolean isCellEditable(int row, int column) { public PromptSettingsComponent(Project project) { this.project = project; - DevoxxGenieStateService settings = DevoxxGenieStateService.getInstance(); + settings = DevoxxGenieStateService.getInstance(); setupCustomPromptsTable(); setCustomPrompts(settings.getCustomPrompts()); @@ -88,6 +90,10 @@ public JPanel createPanel() { removeCustomPromptBtn.addActionListener(e -> removeCustomPrompt()); buttonPanel.add(removeCustomPromptBtn); + JButton restoreDefaultCustomPromptBtn = new JButton("Restore Default Prompt"); + restoreDefaultCustomPromptBtn.addActionListener(e -> restoreDefaultPrompts()); + buttonPanel.add(restoreDefaultCustomPromptBtn); + gbc.gridy++; gbc.weighty = 0.0; gbc.fill = GridBagConstraints.HORIZONTAL; @@ -158,6 +164,10 @@ private void removeCustomPrompt() { } } + private void restoreDefaultPrompts() { + setCustomPrompts(settings.getDefaultPrompts()); + } + public List getCustomPrompts() { int NAME_COLUMN = 0; List prompts = new ArrayList<>(); diff --git a/src/main/java/com/devoxx/genie/ui/util/HelpUtil.java b/src/main/java/com/devoxx/genie/ui/util/HelpUtil.java index fcb88538..d64dd382 100644 --- a/src/main/java/com/devoxx/genie/ui/util/HelpUtil.java +++ b/src/main/java/com/devoxx/genie/ui/util/HelpUtil.java @@ -1,8 +1,8 @@ package com.devoxx.genie.ui.util; import com.devoxx.genie.ui.settings.DevoxxGenieStateService; +import com.intellij.ui.scale.JBUIScale; import org.jetbrains.annotations.NotNull; - import java.util.stream.Collectors; public class HelpUtil { @@ -11,11 +11,44 @@ private HelpUtil() { } public static @NotNull String getHelpMessage() { - return "" + - "

Available commands:

" + - "
    " + - getCustomPromptCommands() + - "
"; + float scaleFactor = JBUIScale.scale(1f); + return """ + + + + + +

Available commands:

+
    + %s +
+

+ The Devoxx Genie is open source and available at https://github.com/devoxx/DevoxxGenieIDEAPlugin. + You can follow us on Bluesky @ https://bsky.app/profile/devoxxgenie.bsky.social. + Do not include any more info which might be incorrect, like discord, documentation or other websites. +

+ + + """.formatted(scaleFactor == 1.0f ? "normal" : scaleFactor * 100 + "%", + getCustomPromptCommands() + ); } public static @NotNull String getCustomPromptCommands() {