mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-12 22:31:24 +00:00
feat: fast code edits (#601)
* feat: initial implementation of direct code edits * fix: popup model selection * refactor: simplify code replacement logic * feat: interactive code modifications * refactor: remove junk
This commit is contained in:
parent
cf5f38365d
commit
14a0d4085c
21 changed files with 690 additions and 181 deletions
|
|
@ -11,7 +11,7 @@ import javax.swing.Icon;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
abstract class BaseEditorAction extends AnAction {
|
||||
public abstract class BaseEditorAction extends AnAction {
|
||||
|
||||
BaseEditorAction(
|
||||
@Nullable @NlsActions.ActionText String text,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import static java.lang.String.format;
|
|||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package ee.carlrobert.codegpt.actions.editor;
|
|||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.intellij.icons.AllIcons.Actions;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import ee.carlrobert.codegpt.CodeGPTKeys;
|
||||
|
|
@ -47,6 +47,7 @@ public class EditorActionsUtil {
|
|||
if (actionGroup instanceof DefaultActionGroup group) {
|
||||
group.removeAll();
|
||||
group.add(new AskAction());
|
||||
group.add(new EditCodeAction(Actions.EditSource));
|
||||
group.add(new CustomPromptAction());
|
||||
group.addSeparator();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ public class ReplaceCodeInMainEditorAction extends AnAction {
|
|||
var project = event.getProject();
|
||||
var toolWindowEditor = event.getData(PlatformDataKeys.EDITOR);
|
||||
if (project != null && toolWindowEditor != null) {
|
||||
EditorUtil.replaceMainEditorSelection(
|
||||
project,
|
||||
EditorUtil.replaceEditorSelection(
|
||||
toolWindowEditor,
|
||||
requireNonNull(toolWindowEditor.getSelectionModel().getSelectedText()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,20 @@ public class CompletionRequestProvider {
|
|||
.build();
|
||||
}
|
||||
|
||||
public static OpenAIChatCompletionRequest buildEditCodeRequest(
|
||||
String context,
|
||||
String model) {
|
||||
return new OpenAIChatCompletionRequest.Builder(
|
||||
List.of(
|
||||
new OpenAIChatCompletionStandardMessage(
|
||||
"system",
|
||||
getResourceContent("/prompts/edit-code.txt")),
|
||||
new OpenAIChatCompletionStandardMessage("user", context)))
|
||||
.setModel(model)
|
||||
.setStream(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Request buildCustomOpenAICompletionRequest(String system, String context) {
|
||||
return buildCustomOpenAIChatCompletionRequest(
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public class ConfigurationState {
|
|||
|
||||
private String systemPrompt = COMPLETION_SYSTEM_PROMPT;
|
||||
private String commitMessagePrompt = GENERATE_COMMIT_MESSAGE_SYSTEM_PROMPT;
|
||||
private int maxTokens = 1000;
|
||||
private int maxTokens = 2048;
|
||||
private double temperature = 0.1;
|
||||
private boolean checkForPluginUpdates = true;
|
||||
private boolean checkForNewScreenshots = false;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
|
@ -274,7 +275,7 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
panel.add(JBUI.Panels.simplePanel(createUserPromptTextAreaHeader(
|
||||
project,
|
||||
selectedService,
|
||||
() -> {
|
||||
(provider) -> {
|
||||
ConversationService.getInstance().startConversation();
|
||||
contentManager.createNewTabPanel();
|
||||
})), BorderLayout.NORTH);
|
||||
|
|
@ -285,7 +286,7 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
private JPanel createUserPromptTextAreaHeader(
|
||||
Project project,
|
||||
ServiceType selectedService,
|
||||
Runnable onModelChange) {
|
||||
Consumer<ServiceType> onModelChange) {
|
||||
return JBUI.Panels.simplePanel()
|
||||
.withBorder(Borders.emptyBottom(8))
|
||||
.andTransparent()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class ReplaceSelectionAction extends TrackableAction {
|
|||
public void handleAction(@NotNull AnActionEvent event) {
|
||||
var project = requireNonNull(event.getProject());
|
||||
if (EditorUtil.isMainEditorTextSelected(project)) {
|
||||
EditorUtil.replaceMainEditorSelection(project, editor.getDocument().getText());
|
||||
EditorUtil.replaceEditorSelection(editor, editor.getDocument().getText());
|
||||
} else {
|
||||
OverlayUtil.showSelectedEditorSelectionWarning(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
package ee.carlrobert.codegpt.toolwindow.chat.ui.textarea;
|
||||
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CODEGPT;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.GOOGLE;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OLLAMA;
|
||||
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
|
||||
import static java.lang.String.format;
|
||||
|
|
@ -28,20 +32,35 @@ import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
|
|||
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
|
||||
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
|
||||
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ModelComboBoxAction extends ComboBoxAction {
|
||||
|
||||
private final Runnable onModelChange;
|
||||
private final Consumer<ServiceType> onModelChange;
|
||||
private final Project project;
|
||||
private final List<ServiceType> availableProviders;
|
||||
|
||||
public ModelComboBoxAction(Project project, Runnable onModelChange, ServiceType selectedService) {
|
||||
public ModelComboBoxAction(
|
||||
Project project,
|
||||
Consumer<ServiceType> onModelChange,
|
||||
ServiceType selectedService) {
|
||||
this(project, onModelChange, selectedService, Arrays.asList(ServiceType.values()));
|
||||
}
|
||||
|
||||
public ModelComboBoxAction(
|
||||
Project project,
|
||||
Consumer<ServiceType> onModelChange,
|
||||
ServiceType selectedProvider,
|
||||
List<ServiceType> availableProviders) {
|
||||
this.project = project;
|
||||
this.onModelChange = onModelChange;
|
||||
updateTemplatePresentation(selectedService);
|
||||
this.availableProviders = availableProviders;
|
||||
updateTemplatePresentation(selectedProvider);
|
||||
}
|
||||
|
||||
public JComponent createCustomComponent(@NotNull String place) {
|
||||
|
|
@ -70,52 +89,71 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
protected @NotNull DefaultActionGroup createPopupActionGroup(JComponent button) {
|
||||
var presentation = ((ComboBoxButton) button).getPresentation();
|
||||
var actionGroup = new DefaultActionGroup();
|
||||
actionGroup.addSeparator("CodeGPT");
|
||||
actionGroup.addAll(getCodeGPTModelActions(project, presentation));
|
||||
actionGroup.addSeparator("OpenAI");
|
||||
List.of(
|
||||
OpenAIChatCompletionModel.GPT_4_O,
|
||||
OpenAIChatCompletionModel.GPT_4_VISION_PREVIEW,
|
||||
OpenAIChatCompletionModel.GPT_4_0125_128k,
|
||||
OpenAIChatCompletionModel.GPT_3_5_0125_16k)
|
||||
.forEach(model -> actionGroup.add(createOpenAIModelAction(model, presentation)));
|
||||
actionGroup.addSeparator("Custom OpenAI");
|
||||
actionGroup.add(createModelAction(
|
||||
CUSTOM_OPENAI,
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getTemplate()
|
||||
.getProviderName(),
|
||||
Icons.OpenAI,
|
||||
presentation));
|
||||
actionGroup.addSeparator();
|
||||
actionGroup.add(createModelAction(
|
||||
ServiceType.ANTHROPIC,
|
||||
"Anthropic (Claude)",
|
||||
Icons.Anthropic,
|
||||
presentation));
|
||||
actionGroup.addSeparator();
|
||||
actionGroup.add(
|
||||
createModelAction(ServiceType.AZURE, "Azure OpenAI", Icons.Azure, presentation));
|
||||
actionGroup.addSeparator();
|
||||
actionGroup.add(createModelAction(
|
||||
ServiceType.LLAMA_CPP,
|
||||
getLlamaCppPresentationText(),
|
||||
Icons.Llama,
|
||||
presentation));
|
||||
actionGroup.addSeparator("Ollama");
|
||||
ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getAvailableModels()
|
||||
.forEach(model ->
|
||||
actionGroup.add(createOllamaModelAction(model, presentation)));
|
||||
actionGroup.addSeparator();
|
||||
actionGroup.add(createModelAction(
|
||||
ServiceType.GOOGLE,
|
||||
"Google (Gemini)",
|
||||
Icons.Google,
|
||||
presentation));
|
||||
|
||||
if (availableProviders.contains(CODEGPT)) {
|
||||
actionGroup.addSeparator("CodeGPT");
|
||||
actionGroup.addAll(getCodeGPTModelActions(project, presentation));
|
||||
}
|
||||
if (availableProviders.contains(OPENAI)) {
|
||||
actionGroup.addSeparator("OpenAI");
|
||||
List.of(
|
||||
OpenAIChatCompletionModel.GPT_4_O,
|
||||
OpenAIChatCompletionModel.GPT_4_VISION_PREVIEW,
|
||||
OpenAIChatCompletionModel.GPT_4_0125_128k,
|
||||
OpenAIChatCompletionModel.GPT_3_5_0125_16k)
|
||||
.forEach(model -> actionGroup.add(createOpenAIModelAction(model, presentation)));
|
||||
}
|
||||
if (availableProviders.contains(CUSTOM_OPENAI)) {
|
||||
actionGroup.addSeparator("Custom OpenAI");
|
||||
actionGroup.add(createModelAction(
|
||||
CUSTOM_OPENAI,
|
||||
ApplicationManager.getApplication().getService(CustomServiceSettings.class)
|
||||
.getState()
|
||||
.getTemplate()
|
||||
.getProviderName(),
|
||||
Icons.OpenAI,
|
||||
presentation));
|
||||
}
|
||||
if (availableProviders.contains(ANTHROPIC)) {
|
||||
actionGroup.addSeparator("Anthropic");
|
||||
actionGroup.add(createModelAction(
|
||||
ANTHROPIC,
|
||||
"Anthropic (Claude)",
|
||||
Icons.Anthropic,
|
||||
presentation));
|
||||
}
|
||||
if (availableProviders.contains(AZURE)) {
|
||||
actionGroup.addSeparator("Azure");
|
||||
actionGroup.add(
|
||||
createModelAction(AZURE, "Azure OpenAI", Icons.Azure, presentation));
|
||||
}
|
||||
if (availableProviders.contains(GOOGLE)) {
|
||||
actionGroup.addSeparator("Google");
|
||||
actionGroup.add(createModelAction(
|
||||
GOOGLE,
|
||||
"Google (Gemini)",
|
||||
Icons.Google,
|
||||
presentation));
|
||||
}
|
||||
if (availableProviders.contains(LLAMA_CPP)) {
|
||||
actionGroup.addSeparator("LLaMA C/C++");
|
||||
actionGroup.add(createModelAction(
|
||||
LLAMA_CPP,
|
||||
getLlamaCppPresentationText(),
|
||||
Icons.Llama,
|
||||
presentation));
|
||||
}
|
||||
if (availableProviders.contains(OLLAMA)) {
|
||||
actionGroup.addSeparator("Ollama");
|
||||
createOllamaModelAction("Default model", presentation);
|
||||
ApplicationManager.getApplication()
|
||||
.getService(OllamaSettings.class)
|
||||
.getState()
|
||||
.getAvailableModels()
|
||||
.forEach(model ->
|
||||
actionGroup.add(createOllamaModelAction(model, presentation)));
|
||||
}
|
||||
|
||||
return actionGroup;
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +249,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
handleModelChange(serviceType, label, icon, comboBoxPresentation);
|
||||
handleModelChange(serviceType, label, label, icon, comboBoxPresentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -224,12 +262,13 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
private void handleModelChange(
|
||||
ServiceType serviceType,
|
||||
String label,
|
||||
String code,
|
||||
Icon icon,
|
||||
Presentation comboBoxPresentation) {
|
||||
GeneralSettings.getCurrentState().setSelectedService(serviceType);
|
||||
comboBoxPresentation.setIcon(icon);
|
||||
comboBoxPresentation.setText(label);
|
||||
onModelChange.run();
|
||||
onModelChange.accept(serviceType);
|
||||
}
|
||||
|
||||
private AnAction createCodeGPTModelAction(CodeGPTModel model, Presentation comboBoxPresentation) {
|
||||
|
|
@ -249,6 +288,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
handleModelChange(
|
||||
CODEGPT,
|
||||
model.getName(),
|
||||
model.getCode(),
|
||||
model.getIcon(),
|
||||
comboBoxPresentation);
|
||||
}
|
||||
|
|
@ -280,6 +320,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
handleModelChange(
|
||||
OLLAMA,
|
||||
model,
|
||||
model,
|
||||
Icons.Ollama,
|
||||
comboBoxPresentation);
|
||||
}
|
||||
|
|
@ -309,6 +350,7 @@ public class ModelComboBoxAction extends ComboBoxAction {
|
|||
handleModelChange(
|
||||
OPENAI,
|
||||
model.getDescription(),
|
||||
model.getCode(),
|
||||
Icons.OpenAI,
|
||||
comboBoxPresentation);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue