diff --git a/build.gradle.kts b/build.gradle.kts index ca3df6e6..4e1f5b3b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } group = "com.devoxx.genie" -version = "0.2.28" +version = "0.2.30" repositories { mavenCentral() diff --git a/src/main/java/com/devoxx/genie/service/FileListObserver.java b/src/main/java/com/devoxx/genie/service/FileListObserver.java index 077a5f26..32e7895a 100644 --- a/src/main/java/com/devoxx/genie/service/FileListObserver.java +++ b/src/main/java/com/devoxx/genie/service/FileListObserver.java @@ -11,4 +11,3 @@ public interface FileListObserver { void allFilesRemoved(); } - diff --git a/src/main/java/com/devoxx/genie/service/MessageCreationService.java b/src/main/java/com/devoxx/genie/service/MessageCreationService.java index 750c7998..e1cee3e3 100644 --- a/src/main/java/com/devoxx/genie/service/MessageCreationService.java +++ b/src/main/java/com/devoxx/genie/service/MessageCreationService.java @@ -28,6 +28,13 @@ public class MessageCreationService { public static final String CONTEXT_PROMPT = "Context: \n"; + private static final String GIT_DIFF_INSTRUCTIONS = """ + Please analyze the code and provide ONLY the modified code in your response. + Do not include any explanations or comments. + The response should contain just the modified code wrapped in a code block using the appropriate language identifier. + If multiple files need to be modified, provide each file's content in a separate code block. + """; + @NotNull public static MessageCreationService getInstance() { return ApplicationManager.getApplication().getService(MessageCreationService.class); @@ -56,6 +63,11 @@ public UserMessage createUserMessage(@NotNull ChatMessageContext chatMessageCont stringBuilder.append("").append(systemPrompt).append("\n\n"); } + // If git diff is enabled, add special instructions + if (DevoxxGenieStateService.getInstance().getUseDiffMerge()) { + stringBuilder.append("").append(GIT_DIFF_INSTRUCTIONS).append("\n\n"); + } + // The user prompt is always appended appendIfNotEmpty(stringBuilder, "" + chatMessageContext.getUserPrompt() + ""); @@ -124,6 +136,12 @@ public UserMessage createUserMessage(@NotNull ChatMessageContext chatMessageCont String context) { StringBuilder stringBuilder = new StringBuilder(); + // If git diff is enabled, add special instructions at the beginning + if (DevoxxGenieStateService.getInstance().getUseDiffMerge() || + DevoxxGenieStateService.getInstance().getUseSimpleDiff()) { + stringBuilder.append("").append(GIT_DIFF_INSTRUCTIONS).append("\n\n"); + } + // Check if this is the first message in the conversation, if so add the context if (ChatMemoryService.getInstance().messages(chatMessageContext.getProject()).size() == 1) { stringBuilder.append(""); diff --git a/src/main/java/com/devoxx/genie/service/gitdiff/GitMergeService.java b/src/main/java/com/devoxx/genie/service/gitdiff/GitMergeService.java new file mode 100644 index 00000000..43a13323 --- /dev/null +++ b/src/main/java/com/devoxx/genie/service/gitdiff/GitMergeService.java @@ -0,0 +1,113 @@ +package com.devoxx.genie.service.gitdiff; + +import com.devoxx.genie.ui.settings.DevoxxGenieStateService; +import com.devoxx.genie.ui.util.NotificationUtil; +import com.intellij.diff.DiffContentFactory; +import com.intellij.diff.DiffManager; +import com.intellij.diff.DiffManagerImpl; +import com.intellij.diff.contents.DiffContent; +import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.contents.DocumentContentImpl; +import com.intellij.diff.requests.DiffRequest; +import com.intellij.diff.requests.SimpleDiffRequest; +import com.intellij.diff.requests.TextMergeRequestImpl; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class GitMergeService { + + private static final Logger LOG = Logger.getInstance(GitMergeService.class); + + @NotNull + public static GitMergeService getInstance() { + return ApplicationManager.getApplication().getService(GitMergeService.class); + } + + /** + * Shows a three-way merge view with: + * - Left: Original code + * - Center: Merge result (initially empty) + * - Right: LLM's modified version + */ + public void showMerge(@NotNull Project project, + @NotNull String originalContent, + @NotNull String modifiedContent, + @NotNull String title, + @NotNull Document targetDocument) { + DevoxxGenieStateService instance = DevoxxGenieStateService.getInstance(); + if (!instance.getUseSimpleDiff() && !instance.getUseDiffMerge()) { + LOG.info("Diff view is disabled"); + return; + } + + ApplicationManager.getApplication().invokeLater(() -> { + DiffContentFactory factory = DiffContentFactory.getInstance(); + + // Create contents for three-way merge + DocumentContent originalContentDoc = factory.create(project, originalContent); + + DocumentContent modifiedContent1 = factory.create(project, modifiedContent); + DocumentContent targetDocumentContent = factory.create(project, targetDocument); + + Document originalDocument = originalContentDoc.getDocument(); + + TextMergeRequestImpl request = new TextMergeRequestImpl( + project, + targetDocumentContent, + originalDocument.getCharsSequence(), + List.of(originalContentDoc, modifiedContent1, targetDocumentContent), + title, + List.of("Original Code", "LLM Modified Code", "Merge Result") + ); + + // Show the merge dialog + DiffManager.getInstance().showMerge(project, request); + }); + } + + /** + * Git diff view + * @param project the project + */ + public void showDiffView(Project project, VirtualFile originalFile, String suggestedContent) { + + ApplicationManager.getApplication().runReadAction(() -> { + if (originalFile == null) { + NotificationUtil.sendNotification(project, "Files not found"); + return; + } + + if (suggestedContent == null || suggestedContent.isEmpty()) { + NotificationUtil.sendNotification(project, "Suggested content is empty"); + return; + } + Document originalContent = com.intellij.openapi.fileEditor.FileDocumentManager + .getInstance() + .getDocument(originalFile); + + if (originalContent == null) { + NotificationUtil.sendNotification(project, "Error reading file: " + originalFile.getName()); + return; + } + + DiffContent content1 = new DocumentContentImpl(originalContent); + DiffContent content2 = new DocumentContentImpl(new DocumentImpl(suggestedContent)); + + DiffRequest diffRequest = new SimpleDiffRequest( + "Diff", + List.of(content1, content2), + List.of("Original code", "LLM suggested") + ); + + ApplicationManager.getApplication().invokeLater(() -> + DiffManagerImpl.getInstance().showDiff(project, diffRequest)); + }); + } +} diff --git a/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java b/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java index 4803d81d..1bc4f0d4 100644 --- a/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java +++ b/src/main/java/com/devoxx/genie/ui/DevoxxGenieToolWindowContent.java @@ -21,6 +21,11 @@ import com.devoxx.genie.ui.settings.DevoxxGenieStateService; import com.devoxx.genie.ui.topic.AppTopics; import com.devoxx.genie.ui.util.NotificationUtil; +import com.intellij.diff.DiffManagerImpl; +import com.intellij.diff.contents.DiffContent; +import com.intellij.diff.contents.FileContentImpl; +import com.intellij.diff.requests.DiffRequest; +import com.intellij.diff.requests.SimpleDiffRequest; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -28,13 +33,17 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.NlsContexts; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.ui.OnePixelSplitter; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.messages.MessageBusConnection; import lombok.Getter; +import org.apache.xmlbeans.impl.xb.xsdschema.SimpleContentDocument; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; diff --git a/src/main/java/com/devoxx/genie/ui/listener/PromptSubmissionListener.java b/src/main/java/com/devoxx/genie/ui/listener/PromptSubmissionListener.java index 203aada0..9bb1d80c 100644 --- a/src/main/java/com/devoxx/genie/ui/listener/PromptSubmissionListener.java +++ b/src/main/java/com/devoxx/genie/ui/listener/PromptSubmissionListener.java @@ -2,6 +2,17 @@ import com.intellij.openapi.project.Project; +/** + * Interface for listeners that want to be notified when a prompt is submitted. + * + * @see com.intellij.openapi.project.Project + */ public interface PromptSubmissionListener { + /** + * Called when a prompt is submitted. + * + * @param project the current project + * @param prompt the submitted prompt + */ void onPromptSubmitted(Project project, String prompt); } diff --git a/src/main/java/com/devoxx/genie/ui/panel/ChatResponsePanel.java b/src/main/java/com/devoxx/genie/ui/panel/ChatResponsePanel.java index d3796c09..055221d3 100644 --- a/src/main/java/com/devoxx/genie/ui/panel/ChatResponsePanel.java +++ b/src/main/java/com/devoxx/genie/ui/panel/ChatResponsePanel.java @@ -2,12 +2,20 @@ import com.devoxx.genie.model.enumarations.ModelProvider; import com.devoxx.genie.model.request.ChatMessageContext; +import com.devoxx.genie.model.request.EditorInfo; import com.devoxx.genie.service.FileListManager; import com.devoxx.genie.service.ProjectContentService; +import com.devoxx.genie.service.gitdiff.GitMergeService; import com.devoxx.genie.ui.component.ExpandablePanel; import com.devoxx.genie.ui.processor.NodeProcessorFactory; import com.devoxx.genie.ui.settings.DevoxxGenieStateService; import com.devoxx.genie.util.DefaultLLMSettingsUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; import com.knuddels.jtokkit.api.Encoding; @@ -22,7 +30,10 @@ import javax.swing.*; import java.awt.*; import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; +import java.util.Objects; import static com.devoxx.genie.ui.util.DevoxxGenieFontsUtil.SourceCodeProFontPlan14; @@ -53,6 +64,16 @@ public ChatResponsePanel(@NotNull ChatMessageContext chatMessageContext) { private void addResponsePane(@NotNull ChatMessageContext chatMessageContext) { String markDownResponse = chatMessageContext.getAiMessage().text(); Node document = Parser.builder().build().parse(markDownResponse); + + DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); + + // If git diff is enabled, try to extract code blocks and show diff + if (stateService.getUseDiffMerge()) { + processGitMerge(chatMessageContext, document); + } else if (stateService.getUseSimpleDiff()) { + processGitDiff(chatMessageContext, document); + } + addDocumentNodesToPanel(document); if (chatMessageContext.hasFiles()) { @@ -67,6 +88,65 @@ private void addResponsePane(@NotNull ChatMessageContext chatMessageContext) { } } + private void processGitMerge(@NotNull ChatMessageContext chatMessageContext, @NotNull Node document) { + // Get original code from context + String originalCode; + EditorInfo editorInfo = chatMessageContext.getEditorInfo(); + + // Wrap the document access in a read action + originalCode = ApplicationManager + .getApplication() + .runReadAction((Computable) () -> { + if (editorInfo.getSelectedText() != null) { + return editorInfo.getSelectedText(); + } else { + List selectedFiles = editorInfo.getSelectedFiles(); + if (selectedFiles == null || selectedFiles.isEmpty()) { + return null; + } + VirtualFile originalFile = selectedFiles.get(0); + Document originalDoc = FileDocumentManager.getInstance().getDocument(originalFile); + if (originalDoc == null) { + return null; + } + return originalDoc.getText(); + } + }); + + if (originalCode == null) { + return; + } + + + // Find the first code block in the response + Node node = document.getFirstChild(); + while (node != null) { + if (node instanceof FencedCodeBlock codeBlock) { + String modifiedCode = codeBlock.getLiteral(); + + Document editorDocument = com.intellij.openapi.application.ApplicationManager.getApplication() + .runReadAction((com.intellij.openapi.util.Computable) () -> + Objects.requireNonNull(FileEditorManager.getInstance(chatMessageContext.getProject()) + .getSelectedTextEditor()) + .getDocument() + ); + + // Show merge using our service + GitMergeService.getInstance().showMerge( + chatMessageContext.getProject(), + originalCode, + modifiedCode, + "Merge LLM Changes", + editorDocument + ); + + // Only show diff for first code block + break; + } + node = node.getNext(); + } + } + private void addMetricExecutionInfo(@NotNull ChatMessageContext chatMessageContext) { JPanel metricExecutionInfoPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); metricExecutionInfoPanel.setOpaque(false); @@ -99,6 +179,65 @@ private void addMetricExecutionInfo(@NotNull ChatMessageContext chatMessageConte add(metricExecutionInfoPanel); } + /** + * Process the git diff. + * @param chatMessageContext the chat message context + * @param document the document + */ + private void processGitDiff(@NotNull ChatMessageContext chatMessageContext, @NotNull Node document) { + // Get original file info + EditorInfo editorInfo = chatMessageContext.getEditorInfo(); + if (editorInfo == null) { + return; + } + + // Handle single file case + if (editorInfo.getSelectedText() != null) { + Editor editor = FileEditorManager.getInstance(chatMessageContext.getProject()) + .getSelectedTextEditor(); + + if (editor != null) { + String originalCode = editorInfo.getSelectedText(); + + // Find first code block in response + Node node = document.getFirstChild(); + while (node != null) { + if (node instanceof FencedCodeBlock codeBlock) { + + GitMergeService.getInstance().showMerge( + chatMessageContext.getProject(), + originalCode, + codeBlock.getLiteral(), + "Merge LLM Changes", + editor.getDocument() + ); + break; + } + node = node.getNext(); + } + } + } + // Handle multiple files case + else if (editorInfo.getSelectedFiles() != null && !editorInfo.getSelectedFiles().isEmpty()) { + List files = editorInfo.getSelectedFiles(); + List modifiedContents = new ArrayList<>(); + + // Collect modified contents from code blocks + Node node = document.getFirstChild(); + while (node != null) { + if (node instanceof FencedCodeBlock codeBlock) { + modifiedContents.add(codeBlock.getLiteral()); + } + node = node.getNext(); + } + + GitMergeService.getInstance().showDiffView( + chatMessageContext.getProject(), + files.get(0), + modifiedContents.get(0)); + } + } + /** * Ollama does not count the input context tokens in the token usage, this method fixes this. * 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 4849b512..0b4412a5 100644 --- a/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java +++ b/src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java @@ -42,6 +42,10 @@ public static DevoxxGenieStateService getInstance() { private Boolean showExecutionTime = true; + // Git Diff features + private Boolean useDiffMerge = false; + private Boolean useSimpleDiff = false; + // Local LLM URL fields private String ollamaModelUrl = OLLAMA_MODEL_URL; private String lmstudioModelUrl = LMSTUDIO_MODEL_URL; diff --git a/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitDiffMode.java b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitDiffMode.java new file mode 100644 index 00000000..b749a572 --- /dev/null +++ b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitDiffMode.java @@ -0,0 +1,92 @@ +package com.devoxx.genie.ui.settings.gitmerge; + +public enum GitDiffMode { + DISABLED("Disabled", "", ""), + DIFF_MERGE("Git Diff Merge", "/images/diff_merge.jpg", + """ + + + + + +

Three-panel comparison

+

Shows three-way comparison between original, suggested, and merged changes

+
    +
  • Left panel: Original file labeled "Original code"
  • +
  • Center panel: Merge result labeled "Merged"
  • +
  • Right panel: LLM's modified version labeled "LLM suggested"
  • +
+ + """), + SIMPLE_DIFF("Simple Git Diff", "/images/simple_diff.jpg", + """ + + + + + +

Two-panel side-by-side comparison

+

Shows direct comparison between original and suggested changes

+
    +
  • Left panel: Original file labeled "Original content"
  • +
  • Right panel: Modified version labeled "LLM suggested"
  • +
+ + """); + + private final String displayName; + private final String iconPath; + private final String description; + + GitDiffMode(String displayName, String iconPath, String description) { + this.displayName = displayName; + this.iconPath = iconPath; + this.description = description; + } + + public String getDisplayName() { + return displayName; + } + + public String getIconPath() { + return iconPath; + } + + public String getDescription() { + return description; + } +} diff --git a/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsComponent.java b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsComponent.java new file mode 100644 index 00000000..a4ef9a67 --- /dev/null +++ b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsComponent.java @@ -0,0 +1,116 @@ +package com.devoxx.genie.ui.settings.gitmerge; + +import com.devoxx.genie.ui.settings.AbstractSettingsComponent; +import com.devoxx.genie.ui.settings.DevoxxGenieStateService; +import com.intellij.ui.scale.JBUIScale; +import com.intellij.util.ui.JBUI; +import lombok.Getter; +import org.jdesktop.swingx.JXTitledSeparator; +import com.intellij.openapi.ui.ComboBox; +import javax.swing.*; +import java.awt.*; + +public class GitMergeSettingsComponent extends AbstractSettingsComponent { + + private final DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); + + @Getter + private final ComboBox gitDiffModeComboBox; + + @Getter + private final JLabel previewImageLabel = new JLabel(); + + @Getter + private final JEditorPane descriptionLabel = new JEditorPane("text/html", ""); + + public GitMergeSettingsComponent() { + // Create combobox with Git Diff modes + gitDiffModeComboBox = new ComboBox<>(GitDiffMode.values()); + + // Set custom renderer to display the enum's display name + gitDiffModeComboBox.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof GitDiffMode) { + setText(((GitDiffMode) value).getDisplayName()); + } + return this; + } + }); + + // Set initial selected mode from state service + GitDiffMode currentMode = determineCurrentMode(); + gitDiffModeComboBox.setSelectedItem(currentMode); + + // Add listener to update preview when selection changes + gitDiffModeComboBox.addActionListener(e -> { + GitDiffMode selectedMode = (GitDiffMode) gitDiffModeComboBox.getSelectedItem(); + updatePreviewImage(selectedMode); + }); + } + + private GitDiffMode determineCurrentMode() { + if (stateService.getUseDiffMerge()) { + return GitDiffMode.DIFF_MERGE; + } else if (stateService.getUseSimpleDiff()) { + return GitDiffMode.SIMPLE_DIFF; + } + return GitDiffMode.DISABLED; + } + + private void updatePreviewImage(GitDiffMode mode) { + float scaleFactor = JBUIScale.scale(1f); + try { + try (var imageStream = getClass().getResourceAsStream(mode.getIconPath())) { + if (imageStream != null) { + byte[] imageBytes = imageStream.readAllBytes(); + ImageIcon icon = new ImageIcon(imageBytes); + previewImageLabel.setIcon(icon); + descriptionLabel.setText( + mode.getDescription() + .formatted(scaleFactor == 1.0f ? "normal" : scaleFactor * 100 + "%")); + } else { + throw new IllegalStateException("Image not found: " + mode.getIconPath()); + } + } + } catch (Exception e) { + previewImageLabel.setIcon(null); + } + } + + @Override + public JPanel createPanel() { + panel.setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = JBUI.insets(5); + + // Add title + panel.add(new JXTitledSeparator("Git Diff Mode"), gbc); + + gbc.gridy++; + panel.add(new JLabel("Commit LLM suggestions using a Git Diff/Merge view"), gbc); + + // Add combobox + gbc.gridy++; + gbc.gridx = 1; + panel.add(new JLabel("Select Git Diff Mode:"), gbc); + gbc.gridy++; + panel.add(gitDiffModeComboBox, gbc); + + // Add description + gbc.gridy++; + panel.add(descriptionLabel, gbc); + + // Add preview image + gbc.gridy++; + panel.add(previewImageLabel, gbc); + + return panel; + } +} diff --git a/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsConfigurable.java b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsConfigurable.java new file mode 100644 index 00000000..88d66f87 --- /dev/null +++ b/src/main/java/com/devoxx/genie/ui/settings/gitmerge/GitMergeSettingsConfigurable.java @@ -0,0 +1,71 @@ +package com.devoxx.genie.ui.settings.gitmerge; + +import com.devoxx.genie.ui.settings.DevoxxGenieStateService; +import com.intellij.openapi.options.Configurable; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class GitMergeSettingsConfigurable implements Configurable { + + private final GitMergeSettingsComponent diffSettingsComponent; + + public GitMergeSettingsConfigurable() { + diffSettingsComponent = new GitMergeSettingsComponent(); + } + + /** + * Get the display name + * @return the display name + */ + @Nls + @Override + public String getDisplayName() { + return "LLM Git Merge"; + } + + /** + * Get the Prompt Settings component + * + * @return the component + */ + @Nullable + @Override + public JComponent createComponent() { + return diffSettingsComponent.createPanel(); + } + + @Override + public boolean isModified() { + DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); + GitDiffMode currentMode = determineCurrentMode(stateService); + return currentMode != diffSettingsComponent.getGitDiffModeComboBox().getSelectedItem(); + } + + @Override + public void apply() { + DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); + GitDiffMode selectedMode = (GitDiffMode) diffSettingsComponent.getGitDiffModeComboBox().getSelectedItem(); + + stateService.setUseDiffMerge(selectedMode == GitDiffMode.DIFF_MERGE); + stateService.setUseSimpleDiff(selectedMode == GitDiffMode.SIMPLE_DIFF); + } + + @Override + public void reset() { + DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); + GitDiffMode currentMode = determineCurrentMode(stateService); + diffSettingsComponent.getGitDiffModeComboBox().setSelectedItem(currentMode); + } + + private GitDiffMode determineCurrentMode(@NotNull DevoxxGenieStateService stateService) { + if (stateService.getUseDiffMerge()) { + return GitDiffMode.DIFF_MERGE; + } else if (stateService.getUseSimpleDiff()) { + return GitDiffMode.SIMPLE_DIFF; + } + return GitDiffMode.DISABLED; + } +} diff --git a/src/main/java/com/devoxx/genie/ui/util/WelcomeUtil.java b/src/main/java/com/devoxx/genie/ui/util/WelcomeUtil.java index de3241c1..09aa623e 100644 --- a/src/main/java/com/devoxx/genie/ui/util/WelcomeUtil.java +++ b/src/main/java/com/devoxx/genie/ui/util/WelcomeUtil.java @@ -43,6 +43,7 @@ public class WelcomeUtil {

New features 🚀

Configure features in the settings page.
    +
  • 💪🏻Git Diff/Merge: Show Git Diff/Merge dialog to commit LLM suggestion
  • ❌.gitignore: Exclude files and directories based on .gitignore file
  • 👀Chat History: All chats are saved and can be restored or removed
  • 🧠Project Scanner: Add source code (full project or by package) to prompt context (or clipboard) when using Anthropic, OpenAI or Gemini.
  • diff --git a/src/main/java/com/devoxx/genie/util/ChatMessageContextUtil.java b/src/main/java/com/devoxx/genie/util/ChatMessageContextUtil.java index 6d8459fe..7fdb442b 100644 --- a/src/main/java/com/devoxx/genie/util/ChatMessageContextUtil.java +++ b/src/main/java/com/devoxx/genie/util/ChatMessageContextUtil.java @@ -49,7 +49,8 @@ public class ChatMessageContextUtil { .webSearchRequested(actionCommand.equals(TAVILY_SEARCH_ACTION) || actionCommand.equals(GOOGLE_SEARCH_ACTION)) .totalFileCount(FileListManager.getInstance().size()) .executionTimeMs(0) - .cost(0).build(); + .cost(0) + .build(); boolean isStreamMode = stateService.getStreamMode() && actionCommand.equals(Constant.SUBMIT_ACTION); if (isStreamMode) { diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 20cae54e..4d4ae2ce 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -35,9 +35,9 @@ ]]> v0.2.28 +

    v0.3.0

      -
    • +
    • Feature #339: Git Merge Diff

    v0.2.27

      @@ -415,6 +415,11 @@ instance="com.devoxx.genie.ui.settings.costsettings.LanguageModelCostSettingsConfigurable" displayName="Token Cost & Context Window"/> + + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index abf54537..cd4109b7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,2 @@ -#Fri Nov 08 19:17:06 CET 2024 -version=0.2.27 +#Mon Dec 02 18:40:46 CET 2024 +version=0.2.30 diff --git a/src/main/resources/images/diff_merge.jpg b/src/main/resources/images/diff_merge.jpg new file mode 100644 index 00000000..f87acb17 Binary files /dev/null and b/src/main/resources/images/diff_merge.jpg differ diff --git a/src/main/resources/images/simple_diff.jpg b/src/main/resources/images/simple_diff.jpg new file mode 100644 index 00000000..281738bc Binary files /dev/null and b/src/main/resources/images/simple_diff.jpg differ