Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improved popup suggestions and personas support #638

Merged
merged 15 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.IncludedFilesSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.persona.PersonaSettings;
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceChatCompletionSettingsState;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
Expand Down Expand Up @@ -71,9 +72,6 @@

public class CompletionRequestProvider {

public static final String COMPLETION_SYSTEM_PROMPT =
getResourceContent("/prompts/default-completion.txt");

public static final String GENERATE_COMMIT_MESSAGE_SYSTEM_PROMPT =
getResourceContent("/prompts/generate-commit-message.txt");

Expand Down Expand Up @@ -197,7 +195,7 @@ public LlamaCompletionRequest buildLlamaCompletionRequest(
}

var systemPrompt = conversationType == FIX_COMPILE_ERRORS
? FIX_COMPILE_ERRORS_SYSTEM_PROMPT : ConfigurationSettings.getSystemPrompt();
? FIX_COMPILE_ERRORS_SYSTEM_PROMPT : PersonaSettings.getSystemPrompt();

var prompt = promptTemplate.buildPrompt(
systemPrompt,
Expand Down Expand Up @@ -302,7 +300,7 @@ public ClaudeCompletionRequest buildAnthropicChatCompletionRequest(
request.setModel(settings.getModel());
request.setMaxTokens(configuration.getMaxTokens());
request.setStream(true);
request.setSystem(ConfigurationSettings.getSystemPrompt());
request.setSystem(PersonaSettings.getSystemPrompt());
List<ClaudeCompletionMessage> messages = conversation.getMessages().stream()
.filter(prevMessage -> prevMessage.getResponse() != null
&& !prevMessage.getResponse().isEmpty())
Expand Down Expand Up @@ -345,8 +343,8 @@ private List<OllamaChatCompletionMessage> buildOllamaMessages(CallParameters cal
var message = callParameters.getMessage();
var messages = new ArrayList<OllamaChatCompletionMessage>();
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
String systemPrompt = ConfigurationSettings.getCurrentState().getSystemPrompt();
messages.add(new OllamaChatCompletionMessage("system", systemPrompt, null));
messages.add(
new OllamaChatCompletionMessage("system", PersonaSettings.getSystemPrompt(), null));
}
if (callParameters.getConversationType() == ConversationType.FIX_COMPILE_ERRORS) {
messages.add(
Expand Down Expand Up @@ -397,8 +395,8 @@ private List<OpenAIChatCompletionMessage> buildOpenAIMessages(CallParameters cal
var message = callParameters.getMessage();
var messages = new ArrayList<OpenAIChatCompletionMessage>();
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
String systemPrompt = ConfigurationSettings.getCurrentState().getSystemPrompt();
messages.add(new OpenAIChatCompletionStandardMessage("system", systemPrompt));
messages.add(
new OpenAIChatCompletionStandardMessage("system", PersonaSettings.getSystemPrompt()));
}
if (callParameters.getConversationType() == ConversationType.FIX_COMPILE_ERRORS) {
messages.add(
Expand Down Expand Up @@ -474,8 +472,7 @@ private List<GoogleCompletionContent> buildGoogleMessages(CallParameters callPar
// Gemini API does not support direct 'system' prompts:
// see https://www.reddit.com/r/Bard/comments/1b90i8o/does_gemini_have_a_system_prompt_option_while/
if (callParameters.getConversationType() == ConversationType.DEFAULT) {
String systemPrompt = ConfigurationSettings.getCurrentState().getSystemPrompt();
messages.add(new GoogleCompletionContent("user", List.of(systemPrompt)));
messages.add(new GoogleCompletionContent("user", List.of(PersonaSettings.getSystemPrompt())));
messages.add(new GoogleCompletionContent("model", List.of("Understood.")));
}
if (callParameters.getConversationType() == ConversationType.FIX_COMPILE_ERRORS) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ee.carlrobert.codegpt.settings.configuration;

import static ee.carlrobert.codegpt.actions.editor.EditorActionsUtil.DEFAULT_ACTIONS_ARRAY;
import static ee.carlrobert.codegpt.completions.CompletionRequestProvider.COMPLETION_SYSTEM_PROMPT;

import com.intellij.icons.AllIcons;
import com.intellij.icons.AllIcons.Nodes;
Expand Down Expand Up @@ -49,7 +48,6 @@ public class ConfigurationComponent {
private final JBCheckBox autoFormattingCheckBox;
private final JBCheckBox autocompletionPostProcessingCheckBox;
private final JBCheckBox autocompletionContextAwareCheckBox;
private final JTextArea systemPromptTextArea;
private final JTextArea commitMessagePromptTextArea;
private final IntegerField maxTokensField;
private final JBTextField temperatureField;
Expand Down Expand Up @@ -94,17 +92,6 @@ public void changedUpdate(DocumentEvent e) {
maxTokensField.setColumns(12);
maxTokensField.setValue(configuration.getMaxTokens());

systemPromptTextArea = new JTextArea(3, 60);
if (configuration.getSystemPrompt().isBlank()) {
// for backward compatibility
systemPromptTextArea.setText(COMPLETION_SYSTEM_PROMPT);
} else {
systemPromptTextArea.setText(configuration.getSystemPrompt());
}
systemPromptTextArea.setLineWrap(true);
systemPromptTextArea.setWrapStyleWord(true);
systemPromptTextArea.setBorder(JBUI.Borders.empty(8, 4));

commitMessagePromptTextArea = new JTextArea(configuration.getCommitMessagePrompt(), 3, 60);
commitMessagePromptTextArea.setLineWrap(true);
commitMessagePromptTextArea.setWrapStyleWord(true);
Expand Down Expand Up @@ -164,7 +151,6 @@ public ConfigurationState getCurrentFormState() {
state.setTableData(getTableData());
state.setMaxTokens(maxTokensField.getValue());
state.setTemperature(Double.parseDouble(temperatureField.getText()));
state.setSystemPrompt(systemPromptTextArea.getText());
state.setCommitMessagePrompt(commitMessagePromptTextArea.getText());
state.setCheckForPluginUpdates(checkForPluginUpdatesCheckBox.isSelected());
state.setCheckForNewScreenshots(checkForNewScreenshotsCheckBox.isSelected());
Expand All @@ -181,7 +167,6 @@ public void resetForm() {
setTableData(configuration.getTableData());
maxTokensField.setValue(configuration.getMaxTokens());
temperatureField.setText(String.valueOf(configuration.getTemperature()));
systemPromptTextArea.setText(configuration.getSystemPrompt());
commitMessagePromptTextArea.setText(configuration.getCommitMessagePrompt());
checkForPluginUpdatesCheckBox.setSelected(configuration.isCheckForPluginUpdates());
checkForNewScreenshotsCheckBox.setSelected(configuration.isCheckForNewScreenshots());
Expand Down Expand Up @@ -242,15 +227,6 @@ private void addAssistantFormLabeledComponent(

private JPanel createAssistantConfigurationForm() {
var formBuilder = FormBuilder.createFormBuilder();
addAssistantFormLabeledComponent(
formBuilder,
"configurationConfigurable.section.assistant.systemPromptField.label",
"configurationConfigurable.section.assistant.systemPromptField.comment",
JBUI.Panels
.simplePanel(systemPromptTextArea)
.withBorder(JBUI.Borders.customLine(
JBUI.CurrentTheme.CustomFrameDecorations.separatorForeground())));
formBuilder.addVerticalGap(8);
addAssistantFormLabeledComponent(
formBuilder,
"configurationConfigurable.section.assistant.temperatureField.label",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,4 @@ public static ConfigurationState getCurrentState() {
public static ConfigurationSettings getInstance() {
return ApplicationManager.getApplication().getService(ConfigurationSettings.class);
}

public static String getSystemPrompt() {
return getCurrentState().getSystemPrompt();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ee.carlrobert.codegpt.settings.configuration;

import static ee.carlrobert.codegpt.completions.CompletionRequestProvider.COMPLETION_SYSTEM_PROMPT;
import static ee.carlrobert.codegpt.completions.CompletionRequestProvider.GENERATE_COMMIT_MESSAGE_SYSTEM_PROMPT;

import ee.carlrobert.codegpt.actions.editor.EditorActionsUtil;
Expand All @@ -9,7 +8,6 @@

public class ConfigurationState {

private String systemPrompt = COMPLETION_SYSTEM_PROMPT;
private String commitMessagePrompt = GENERATE_COMMIT_MESSAGE_SYSTEM_PROMPT;
private int maxTokens = 2048;
private double temperature = 0.1;
Expand All @@ -24,18 +22,10 @@ public class ConfigurationState {
private boolean autocompletionContextAwareEnabled = false;
private Map<String, String> tableData = EditorActionsUtil.DEFAULT_ACTIONS;

public String getSystemPrompt() {
return systemPrompt;
}

public String getCommitMessagePrompt() {
return commitMessagePrompt;
}

public void setSystemPrompt(String systemPrompt) {
this.systemPrompt = systemPrompt;
}

public void setCommitMessagePrompt(String commitMessagePrompt) {
this.commitMessagePrompt = commitMessagePrompt;
}
Expand Down Expand Up @@ -155,14 +145,13 @@ public boolean equals(Object o) {
&& autoFormattingEnabled == that.autoFormattingEnabled
&& autocompletionPostProcessingEnabled == that.autocompletionPostProcessingEnabled
&& autocompletionContextAwareEnabled == that.autocompletionContextAwareEnabled
&& Objects.equals(systemPrompt, that.systemPrompt)
&& Objects.equals(commitMessagePrompt, that.commitMessagePrompt)
&& Objects.equals(tableData, that.tableData);
}

@Override
public int hashCode() {
return Objects.hash(systemPrompt, commitMessagePrompt, maxTokens, temperature,
return Objects.hash(commitMessagePrompt, maxTokens, temperature,
checkForPluginUpdates, checkForNewScreenshots, createNewChatOnEachAction,
ignoreGitCommitTokenLimit, methodNameGenerationEnabled, captureCompileErrors,
autoFormattingEnabled, autocompletionPostProcessingEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultCompactActionGroup;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.util.Disposer;
Expand All @@ -23,6 +28,8 @@
import ee.carlrobert.codegpt.conversations.ConversationService;
import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.persona.PersonaSettings;
import ee.carlrobert.codegpt.settings.persona.PersonasConfigurable;
import ee.carlrobert.codegpt.settings.service.ProviderChangeNotifier;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTUserDetailsNotifier;
Expand All @@ -35,6 +42,7 @@
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -165,6 +173,8 @@ private ActionToolbar createActionToolbar(
new ClearChatWindowAction(() -> tabbedPane.resetCurrentlyActiveTabPanel(project)));
actionGroup.addSeparator();
actionGroup.add(new OpenInEditorAction());
actionGroup.addSeparator();
actionGroup.add(new SelectedPersonaActionLink(project));

var toolbar = ActionManager.getInstance()
.createActionToolbar("NAVIGATION_BAR_TOOLBAR", actionGroup, true);
Expand All @@ -186,4 +196,47 @@ public void clearSelectedFilesNotification(Project project) {
.syncPublisher(IncludeFilesInContextNotifier.FILES_INCLUDED_IN_CONTEXT_TOPIC)
.filesIncluded(emptyList());
}

private static class SelectedPersonaActionLink extends DumbAwareAction implements
CustomComponentAction {

private final Project project;

SelectedPersonaActionLink(Project project) {
this.project = project;
}

@Override
@NotNull
public JComponent createCustomComponent(
@NotNull Presentation presentation,
@NotNull String place) {
var link = new ActionLink(getSelectedPersonaName(), (e) -> {
ShowSettingsUtil.getInstance()
.showSettingsDialog(project, PersonasConfigurable.class);
});
link.setExternalLinkIcon();
link.setFont(JBUI.Fonts.smallFont());
link.setBorder(JBUI.Borders.empty(0, 4));
return link;
}

@Override
public void updateCustomComponent(
@NotNull JComponent component,
@NotNull Presentation presentation) {
((ActionLink) component).setText(getSelectedPersonaName());
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
}

private String getSelectedPersonaName() {
return ApplicationManager.getApplication().getService(PersonaSettings.class)
.getState()
.getSelectedPersona()
.getName();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ee.carlrobert.codegpt.toolwindow.chat.ui.textarea;

import ee.carlrobert.codegpt.EncodingManager;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.persona.PersonaSettings;

public class TotalTokensDetails {

Expand All @@ -12,7 +12,7 @@ public class TotalTokensDetails {
private int referencedFilesTokens;

public TotalTokensDetails(EncodingManager encodingManager) {
systemPromptTokens = encodingManager.countTokens(ConfigurationSettings.getSystemPrompt());
systemPromptTokens = encodingManager.countTokens(PersonaSettings.getSystemPrompt());
}

public int getSystemPromptTokens() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ee.carlrobert.codegpt.settings.persona

import com.intellij.openapi.components.*

const val DEFAULT_PROMPT =
"You are an AI programming assistant.\nFollow the user's requirements carefully & to the letter.\nYour responses should be informative and logical.\nYou should always adhere to technical information.\nIf the user asks for code or technical questions, you must provide code suggestions and adhere to technical information.\nIf the question is related to a developer, you must respond with content related to a developer.\nFirst think step-by-step - describe your plan for what to build in pseudocode, written out in great detail.\nThen output the code in a single code block.\nMinimize any other prose.\nKeep your answers short and impersonal.\nUse Markdown formatting in your answers.\nMake sure to include the programming language name at the start of the Markdown code blocks.\nAvoid wrapping the whole response in triple backticks.\nThe user works in an IDE built by JetBrains which has a concept for editors with open files, integrated unit test support, and output pane that shows the output of running the code as well as an integrated terminal.\nYou can only give one reply for each conversation turn."

@Service
@State(
name = "CodeGPT_PersonaSettings",
storages = [Storage("CodeGPT_PersonaSettings.xml")]
)
class PersonaSettings :
SimplePersistentStateComponent<PersonaSettingsState>(PersonaSettingsState()) {

companion object {
@JvmStatic
fun getSystemPrompt(): String {
return service<PersonaSettings>().state.selectedPersona.instructions ?: ""
}
}
}

class PersonaSettingsState : BaseState() {
var selectedPersona by property(PersonaDetailsState())
var userCreatedPersonas by list<PersonaDetailsState>()
}

class PersonaDetailsState : BaseState() {
var id by property(1L)
var name by string("CodeGPT Default")
var instructions by string(DEFAULT_PROMPT)
}

@JvmRecord
data class PersonaDetails(val id: Long, val name: String, val instructions: String)

fun PersonaDetails.toPersonaDetailsState(): PersonaDetailsState {
val newState = PersonaDetailsState()
newState.id = id
newState.name = name
newState.instructions = instructions
return newState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ee.carlrobert.codegpt.settings.persona

import com.intellij.openapi.options.Configurable
import javax.swing.JComponent

class PersonasConfigurable : Configurable {

private lateinit var component: PersonasSettingsForm

override fun getDisplayName(): String {
return "CodeGPT: Personas"
}

override fun createComponent(): JComponent {
component = PersonasSettingsForm()
return component.createPanel()
}

override fun isModified(): Boolean = component.isModified()

override fun apply() {
component.applyChanges()
}

override fun reset() {
component.resetChanges()
}
}
Loading