Skip to content

Commit

Permalink
Merge pull request #328 from devoxx/issue-324
Browse files Browse the repository at this point in the history
Issue 324
  • Loading branch information
stephanj authored Nov 8, 2024
2 parents efcacce + fd3695f commit 23ccec2
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 194 deletions.
11 changes: 10 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group = "com.devoxx.genie"
version = "0.2.26"
version = "0.2.27"

repositories {
mavenCentral()
Expand Down Expand Up @@ -56,6 +56,15 @@ dependencies {
implementation("com.knuddels:jtokkit:1.0.0")
implementation("org.commonmark:commonmark:0.22.0")

// TDG : Add Log4j dependencies
implementation("org.apache.logging.log4j:log4j-api:2.22.1")
implementation("org.apache.logging.log4j:log4j-core:2.22.1")

// TDG : Add other TDG dependencies
implementation("org.junit.jupiter:junit-jupiter-api:5.11.3")
implementation("org.junit.jupiter:junit-jupiter-engine:5.11.3")
implementation("org.junit.platform:junit-platform-launcher:1.11.3")

compileOnly("org.projectlombok:lombok:1.18.34")
annotationProcessor("org.projectlombok:lombok:1.18.34")

Expand Down
180 changes: 180 additions & 0 deletions src/main/java/com/devoxx/genie/controller/ActionPanelController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.devoxx.genie.controller;

import com.devoxx.genie.chatmodel.ChatModelProvider;
import com.devoxx.genie.model.LanguageModel;
import com.devoxx.genie.model.enumarations.ModelProvider;
import com.devoxx.genie.model.request.ChatMessageContext;
import com.devoxx.genie.service.*;
import com.devoxx.genie.ui.EditorFileButtonManager;
import com.devoxx.genie.ui.component.PromptInputArea;
import com.devoxx.genie.ui.panel.ActionButtonsPanel;
import com.devoxx.genie.ui.panel.PromptOutputPanel;
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
import com.devoxx.genie.ui.util.NotificationUtil;
import com.devoxx.genie.util.ChatMessageContextUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.ui.ComboBox;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.atomic.AtomicBoolean;

public class ActionPanelController {
private final Project project;
private final ChatPromptExecutor chatPromptExecutor;
private final EditorFileButtonManager editorFileButtonManager;
private final PromptInputArea promptInputArea;
private final PromptOutputPanel promptOutputPanel;
private final ComboBox<ModelProvider> modelProviderComboBox;
private final ComboBox<LanguageModel> modelNameComboBox;
private final ChatModelProvider chatModelProvider = new ChatModelProvider();
private final ActionButtonsPanel actionButtonsPanel;
private boolean isPromptRunning = false;

private ChatMessageContext currentChatMessageContext;

public ActionPanelController(Project project,
PromptInputArea promptInputArea,
PromptOutputPanel promptOutputPanel,
ComboBox<ModelProvider> modelProviderComboBox,
ComboBox<LanguageModel> modelNameComboBox,
ActionButtonsPanel actionButtonsPanel) {

this.project = project;
this.promptInputArea = promptInputArea;
this.promptOutputPanel = promptOutputPanel;
this.chatPromptExecutor = new ChatPromptExecutor(promptInputArea);
this.editorFileButtonManager = new EditorFileButtonManager(project, null);
this.modelProviderComboBox = modelProviderComboBox;
this.modelNameComboBox = modelNameComboBox;
this.actionButtonsPanel = actionButtonsPanel;
}

public boolean isPromptRunning() {
return isPromptRunning;
}

public boolean executePrompt(String actionCommand,
boolean isProjectContextAdded,
String projectContext) {
if (isPromptRunning) {
stopPromptExecution();
return true;
}

if (!validateAndPreparePrompt(actionCommand, isProjectContextAdded, projectContext)) {
return false;
}

isPromptRunning = true;

AtomicBoolean response = new AtomicBoolean(true);
chatPromptExecutor.updatePromptWithCommandIfPresent(currentChatMessageContext, promptOutputPanel)
.ifPresentOrElse(
this::executePromptWithContext,
() -> response.set(false)
);

return response.get();
}

private void executePromptWithContext(String command) {
chatPromptExecutor.executePrompt(currentChatMessageContext, promptOutputPanel, () -> {
isPromptRunning = false;
actionButtonsPanel.enableButtons();
ApplicationManager.getApplication().invokeLater(() -> {
promptInputArea.clear();
promptInputArea.requestInputFocus();
});
});
}

public void stopPromptExecution() {
chatPromptExecutor.stopPromptExecution(project);
isPromptRunning = false;
actionButtonsPanel.enableButtons();
}

/**
* Validate and prepare the prompt.
*
* @param actionCommand the action event command
* @return true if the prompt is valid
*/
private boolean validateAndPreparePrompt(String actionCommand,
boolean isProjectContextAdded,
String projectContext) {
String userPromptText = getUserPromptText();
if (userPromptText == null) {
return false;
}

DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance();
LanguageModel selectedLanguageModel = (LanguageModel) modelNameComboBox.getSelectedItem();

// If selectedLanguageModel is null, create a default one
if (selectedLanguageModel == null) {
selectedLanguageModel = createDefaultLanguageModel(stateService);
}

currentChatMessageContext = ChatMessageContextUtil.createContext(
project,
userPromptText,
selectedLanguageModel,
chatModelProvider,
stateService,
actionCommand,
editorFileButtonManager,
projectContext,
isProjectContextAdded
);

return true;
}

/**
* get the user prompt text.
*/
private @Nullable String getUserPromptText() {
String userPromptText = promptInputArea.getText();
if (userPromptText.isEmpty()) {
NotificationUtil.sendNotification(project, "Please enter a prompt.");
return null;
}
return userPromptText;
}

/**
* Create a default language model.
*
* @param stateService the state service
* @return the default language model
*/
private LanguageModel createDefaultLanguageModel(@NotNull DevoxxGenieSettingsService stateService) {
ModelProvider selectedProvider = (ModelProvider) modelProviderComboBox.getSelectedItem();
if (selectedProvider != null &&
(selectedProvider.equals(ModelProvider.LMStudio) ||
selectedProvider.equals(ModelProvider.GPT4All) ||
selectedProvider.equals(ModelProvider.Jlama) ||
selectedProvider.equals(ModelProvider.LLaMA))) {
return LanguageModel.builder()
.provider(selectedProvider)
.apiKeyUsed(false)
.inputCost(0)
.outputCost(0)
.contextWindow(4096)
.build();
} else {
String modelName = stateService.getSelectedLanguageModel(project.getLocationHash());
return LanguageModel.builder()
.provider(selectedProvider != null ? selectedProvider : ModelProvider.OpenAI)
.modelName(modelName)
.apiKeyUsed(false)
.inputCost(0)
.outputCost(0)
.contextWindow(128_000)
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.devoxx.genie.ui.panel.PromptOutputPanel;
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
import com.devoxx.genie.util.FileTypeUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.ProgressIndicator;
Expand Down Expand Up @@ -61,7 +62,7 @@ public void run(@NotNull ProgressIndicator progressIndicator) {
new WebSearchExecutor().execute(chatMessageContext, promptOutputPanel, () -> {
isRunningMap.put(project, false);
enableButtons.run();
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
promptInputArea.clear();
promptInputArea.requestInputFocus();
});
Expand All @@ -70,7 +71,7 @@ public void run(@NotNull ProgressIndicator progressIndicator) {
streamingPromptExecutor.execute(chatMessageContext, promptOutputPanel, () -> {
isRunningMap.put(project, false);
enableButtons.run();
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
promptInputArea.clear();
promptInputArea.requestInputFocus();
});
Expand All @@ -79,7 +80,7 @@ public void run(@NotNull ProgressIndicator progressIndicator) {
nonStreamingPromptExecutor.execute(chatMessageContext, promptOutputPanel, () -> {
isRunningMap.put(project, false);
enableButtons.run();
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
promptInputArea.clear();
promptInputArea.requestInputFocus();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
*/
public class MessageCreationService {


public static final String CONTEXT_PROMPT = "Context: \n";

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private void finalizeResponse(@NotNull Response<AiMessage> response) {

private void addExpandablePanelIfNeeded() {
if (chatMessageContext.hasFiles()) {
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
ExpandablePanel fileListPanel =
new ExpandablePanel(chatMessageContext, FileListManager.getInstance().getFiles());
fileListPanel.setName(chatMessageContext.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
import com.devoxx.genie.ui.topic.AppTopics;
import com.devoxx.genie.ui.util.NotificationUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
Expand Down Expand Up @@ -314,7 +315,7 @@ private void refreshModels() {
}

if (selectedProvider == ModelProvider.LMStudio || selectedProvider == ModelProvider.Ollama || selectedProvider == ModelProvider.Jan) {
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
refreshButton.setEnabled(false);

ChatModelFactory factory = ChatModelFactoryProvider.getFactoryByProvider(selectedProvider.name())
Expand Down Expand Up @@ -375,7 +376,7 @@ public void startNewConversation() {

chatService.startNewConversation("");

SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
conversationPanel.updateNewConversationLabel();
promptInputArea.clear();
promptOutputPanel.clear();
Expand Down Expand Up @@ -487,7 +488,7 @@ public void settingsChanged() {

@Override
public void onCustomPromptsChanged() {
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
// Update the help panel or any other UI components that display custom prompts
if (promptOutputPanel != null) {
promptOutputPanel.updateHelpText();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ private void handleFileOpenClose() {
FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() {
@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
if (addFileBtn == null) {
return;
}
addFileBtn.setEnabled(true);
addFileBtn.setToolTipText("Select file(s) for prompt context");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void insertString(int offs, String str, AttributeSet a) throws BadLocatio

super.insertString(offs, str, a);

SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
try {
String text = getText(0, getLength());
String[] lines = text.split("\n");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.devoxx.genie.ui.component;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupListener;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
Expand Down Expand Up @@ -33,6 +34,6 @@ public void beforeShown(@NotNull LightweightWindowEvent event) {
});

// Ensure this is on the EDT
SwingUtilities.invokeLater(() -> popup.show(northWest));
ApplicationManager.getApplication().invokeLater(() -> popup.show(northWest));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.devoxx.genie.ui.component;

import com.devoxx.genie.ui.listener.PromptInputFocusListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.ui.JBColor;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -91,7 +92,7 @@ public boolean requestFocusInWindow() {
}

public void requestInputFocus() {
SwingUtilities.invokeLater(() -> {
ApplicationManager.getApplication().invokeLater(() -> {
inputField.requestFocusInWindow();
inputField.setCaretPosition(inputField.getText().length());
});
Expand Down
Loading

0 comments on commit 23ccec2

Please sign in to comment.