Skip to content

Commit 719f086

Browse files
committed
Merge remote-tracking branch 'origin/master' into develop
2 parents 81919db + f831a1f commit 719f086

File tree

51 files changed

+923
-604
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+923
-604
lines changed

buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ checkstyle {
2323
}
2424

2525
dependencies {
26-
implementation("ee.carlrobert:llm-client:0.1.3")
26+
implementation("ee.carlrobert:llm-client:0.2.0")
2727
}
2828

2929
tasks {

codegpt-core/src/main/java/ee/carlrobert/embedding/EmbeddingsService.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,16 @@ public String buildPromptWithContext(String prompt) {
6464
}
6565

6666
public List<Item<Object, double[]>> createEmbeddings(
67-
List<CheckedFile> checkedFiles,
67+
List<ReferencedFile> referencedFiles,
6868
@Nullable ProgressIndicator indicator) {
6969
var words = new ArrayList<Item<Object, double[]>>();
70-
for (int i = 0; i < checkedFiles.size(); i++) {
70+
for (int i = 0; i < referencedFiles.size(); i++) {
7171
try {
72-
var checkedFile = checkedFiles.get(i);
73-
addEmbeddings(checkedFile, words);
72+
var referencedFile = referencedFiles.get(i);
73+
addEmbeddings(referencedFile, words);
7474

7575
if (indicator != null) {
76-
indicator.setFraction((double) i / checkedFiles.size());
76+
indicator.setFraction((double) i / referencedFiles.size());
7777
}
7878
} catch (Throwable t) {
7979
// ignore
@@ -101,24 +101,26 @@ private String getSearchQuery(String userPrompt) throws JsonProcessingException
101101
.getContent();
102102
}
103103

104-
private void addEmbeddings(CheckedFile checkedFile, List<Item<Object, double[]>> prevEmbeddings) {
105-
var fileExtension = checkedFile.getFileExtension();
104+
private void addEmbeddings(
105+
ReferencedFile referencedFile,
106+
List<Item<Object, double[]>> prevEmbeddings) {
107+
var fileExtension = referencedFile.getFileExtension();
106108
var codeSplitter = SplitterFactory.getCodeSplitter(fileExtension);
107109
if (codeSplitter != null) {
108110
var chunks = codeSplitter.split(
109-
checkedFile.getFileName(),
110-
checkedFile.getFileContent());
111+
referencedFile.getFileName(),
112+
referencedFile.getFileContent());
111113
var embeddings = openAIClient.getEmbeddings(chunks);
112114
for (int i = 0; i < chunks.size(); i++) {
113115
prevEmbeddings.add(
114-
new Word(chunks.get(i), checkedFile.getFileName(), normalize(embeddings.get(i))));
116+
new Word(chunks.get(i), referencedFile.getFileName(), normalize(embeddings.get(i))));
115117
}
116118
} else {
117-
var chunks = splitText(checkedFile.getFileContent(), 400);
119+
var chunks = splitText(referencedFile.getFileContent(), 400);
118120
var embeddings = getEmbeddings(chunks);
119121
for (int i = 0; i < chunks.size(); i++) {
120122
prevEmbeddings.add(
121-
new Word(chunks.get(i), checkedFile.getFileName(), normalize(embeddings.get(i))));
123+
new Word(chunks.get(i), referencedFile.getFileName(), normalize(embeddings.get(i))));
122124
}
123125
}
124126
}

codegpt-core/src/main/java/ee/carlrobert/embedding/CheckedFile.java renamed to codegpt-core/src/main/java/ee/carlrobert/embedding/ReferencedFile.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
import java.io.IOException;
55
import java.nio.file.Files;
66
import java.nio.file.Paths;
7+
import java.util.Objects;
78
import java.util.regex.Matcher;
89
import java.util.regex.Pattern;
910

10-
public class CheckedFile {
11+
public class ReferencedFile {
1112

1213
private final String fileName;
1314
private final String filePath;
1415
private final String fileContent;
1516

16-
public CheckedFile(File file) {
17+
public ReferencedFile(File file) {
1718
this.fileName = file.getName();
1819
this.filePath = file.getPath();
1920
try {
@@ -23,7 +24,7 @@ public CheckedFile(File file) {
2324
}
2425
}
2526

26-
public CheckedFile(String fileName, String filePath, String fileContent) {
27+
public ReferencedFile(String fileName, String filePath, String fileContent) {
2728
this.fileName = fileName;
2829
this.filePath = filePath;
2930
this.fileContent = fileContent;
@@ -50,4 +51,22 @@ public String getFileExtension() {
5051
}
5152
return "";
5253
}
54+
55+
@Override
56+
public boolean equals(Object o) {
57+
if (this == o) {
58+
return true;
59+
}
60+
if (o == null || getClass() != o.getClass()) {
61+
return false;
62+
}
63+
64+
ReferencedFile that = (ReferencedFile) o;
65+
return Objects.equals(filePath, that.filePath);
66+
}
67+
68+
@Override
69+
public int hashCode() {
70+
return Objects.hash(filePath);
71+
}
5372
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
You are an AI programming assistant.
2+
Follow the user's requirements carefully & to the letter.
3+
Your responses should be informative and logical.
4+
You should always adhere to technical information.
5+
If the user asks for code or technical questions, you must provide code suggestions and adhere to technical information.
6+
If the question is related to a developer, you must respond with content related to a developer.
7+
First think step-by-step - describe your plan for what to build in pseudocode, written out in great detail.
8+
Then output the code in a single code block.
9+
Minimize any other prose.
10+
Keep your answers short and impersonal.
11+
Use Markdown formatting in your answers.
12+
Make sure to include the programming language name at the start of the Markdown code blocks.
13+
Avoid wrapping the whole response in triple backticks.
14+
The 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.
15+
You can only give one reply for each conversation turn.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
I will provide you with a snippet of code that is causing a compilation error.
2+
Your task is to identify the potential causes of the compilation error(s) and propose code solutions to fix them.
3+
Please approach this step by step, explaining your reasoning as you go.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Write a short and descriptive git commit message for the following git diff.
2+
Use imperative mood, present tense, active voice and verbs.
3+
Your entire response will be passed directly into git commit.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package ee.carlrobert.codegpt;
22

33
import com.intellij.openapi.util.Key;
4-
import ee.carlrobert.embedding.CheckedFile;
4+
import ee.carlrobert.embedding.ReferencedFile;
55
import java.util.List;
66

77
public class CodeGPTKeys {
88

9-
public static final Key<List<CheckedFile>> SELECTED_FILES = Key.create("selectedFiles");
9+
public static final Key<List<ReferencedFile>> SELECTED_FILES = Key.create("selectedFiles");
1010
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package ee.carlrobert.codegpt;
2+
3+
import static ee.carlrobert.codegpt.completions.ConversationType.FIX_COMPILE_ERRORS;
4+
import static java.lang.String.format;
5+
import static java.util.stream.Collectors.joining;
6+
import static java.util.stream.Collectors.toList;
7+
8+
import com.intellij.compiler.CompilerMessageImpl;
9+
import com.intellij.notification.NotificationAction;
10+
import com.intellij.notification.NotificationType;
11+
import com.intellij.openapi.compiler.CompilationStatusListener;
12+
import com.intellij.openapi.compiler.CompileContext;
13+
import com.intellij.openapi.compiler.CompilerMessage;
14+
import com.intellij.openapi.compiler.CompilerMessageCategory;
15+
import com.intellij.openapi.project.Project;
16+
import ee.carlrobert.codegpt.completions.CompletionRequestProvider;
17+
import ee.carlrobert.codegpt.conversations.message.Message;
18+
import ee.carlrobert.codegpt.settings.configuration.ConfigurationState;
19+
import ee.carlrobert.codegpt.toolwindow.chat.standard.StandardChatToolWindowContentManager;
20+
import ee.carlrobert.codegpt.ui.OverlayUtil;
21+
import ee.carlrobert.embedding.ReferencedFile;
22+
import java.io.File;
23+
import java.util.ArrayList;
24+
import java.util.Collection;
25+
import java.util.HashMap;
26+
import java.util.List;
27+
import org.jetbrains.annotations.NotNull;
28+
29+
public class ProjectCompilationStatusListener implements CompilationStatusListener {
30+
31+
private final Project project;
32+
33+
public ProjectCompilationStatusListener(Project project) {
34+
this.project = project;
35+
}
36+
37+
@Override
38+
public void compilationFinished(
39+
boolean aborted,
40+
int errors,
41+
int warnings,
42+
@NotNull CompileContext compileContext) {
43+
var configuration = ConfigurationState.getInstance();
44+
var success = !configuration.isCaptureCompileErrors()
45+
|| (!aborted && errors == 0 && warnings == 0);
46+
if (success) {
47+
return;
48+
}
49+
if (errors > 0) {
50+
OverlayUtil.getDefaultNotification(
51+
CodeGPTBundle.get("notification.compilationError.description"),
52+
NotificationType.INFORMATION)
53+
.addAction(NotificationAction.createSimpleExpiring(
54+
CodeGPTBundle.get("notification.compilationError.okLabel"),
55+
() -> project.getService(StandardChatToolWindowContentManager.class)
56+
.sendMessage(getMultiFileMessage(compileContext), FIX_COMPILE_ERRORS)))
57+
.addAction(NotificationAction.createSimpleExpiring(
58+
CodeGPTBundle.get("checkForUpdatesTask.notification.hideButton"),
59+
() -> ConfigurationState.getInstance().setCaptureCompileErrors(false)))
60+
.notify(project);
61+
}
62+
}
63+
64+
private Message getMultiFileMessage(CompileContext compileContext) {
65+
var errorMapping = getErrorMapping(compileContext);
66+
var prompt = errorMapping.values().stream()
67+
.flatMap(Collection::stream)
68+
.collect(joining("\n\n"));
69+
70+
var message = new Message("Fix the following compile errors:\n\n" + prompt);
71+
message.setReferencedFilePaths(errorMapping.keySet().stream()
72+
.map(ReferencedFile::getFilePath)
73+
.collect(toList()));
74+
message.setUserMessage(message.getPrompt());
75+
message.setPrompt(CompletionRequestProvider.getPromptWithContext(
76+
new ArrayList<>(errorMapping.keySet()),
77+
prompt));
78+
return message;
79+
}
80+
81+
private HashMap<ReferencedFile, List<String>> getErrorMapping(CompileContext compileContext) {
82+
var errorMapping = new HashMap<ReferencedFile, List<String>>();
83+
for (var compilerMessage : compileContext.getMessages(CompilerMessageCategory.ERROR)) {
84+
var key = new ReferencedFile(new File(compilerMessage.getVirtualFile().getPath()));
85+
var prevValue = errorMapping.get(key);
86+
if (prevValue == null) {
87+
prevValue = new ArrayList<>();
88+
}
89+
prevValue.add(getCompilerErrorDetails(compilerMessage));
90+
errorMapping.put(key, prevValue);
91+
}
92+
return errorMapping;
93+
}
94+
95+
private String getCompilerErrorDetails(CompilerMessage compilerMessage) {
96+
if (compilerMessage instanceof CompilerMessageImpl) {
97+
return format(
98+
"%s:%d:%d - `%s`",
99+
compilerMessage.getVirtualFile().getName(),
100+
((CompilerMessageImpl) compilerMessage).getLine(),
101+
((CompilerMessageImpl) compilerMessage).getColumn(),
102+
compilerMessage.getMessage());
103+
}
104+
return format(
105+
"%s - `%s`",
106+
compilerMessage.getVirtualFile().getName(),
107+
compilerMessage.getMessage());
108+
}
109+
}

src/main/java/ee/carlrobert/codegpt/actions/GenerateGitCommitMessageAction.java

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,13 @@
2323
import ee.carlrobert.codegpt.CodeGPTBundle;
2424
import ee.carlrobert.codegpt.EncodingManager;
2525
import ee.carlrobert.codegpt.Icons;
26-
import ee.carlrobert.codegpt.completions.CompletionClientProvider;
26+
import ee.carlrobert.codegpt.completions.CompletionRequestService;
2727
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
2828
import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
29-
import ee.carlrobert.codegpt.settings.configuration.ConfigurationState;
3029
import ee.carlrobert.codegpt.settings.service.ServiceType;
31-
import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
3230
import ee.carlrobert.codegpt.settings.state.SettingsState;
3331
import ee.carlrobert.codegpt.ui.OverlayUtil;
3432
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
35-
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionMessage;
36-
import ee.carlrobert.llm.client.openai.completion.request.OpenAIChatCompletionRequest;
3733
import ee.carlrobert.llm.completion.CompletionEventListener;
3834
import java.io.BufferedReader;
3935
import java.io.File;
@@ -59,7 +55,7 @@ public GenerateGitCommitMessageAction() {
5955
public void update(@NotNull AnActionEvent event) {
6056
var selectedService = SettingsState.getInstance().getSelectedService();
6157
if (selectedService == ServiceType.OPENAI || selectedService == ServiceType.AZURE) {
62-
var filesSelected = !getCheckedFilePaths(event).isEmpty();
58+
var filesSelected = !getReferencedFilePaths(event).isEmpty();
6359
var callAllowed = (selectedService == ServiceType.OPENAI
6460
&& OpenAICredentialsManager.getInstance().isApiKeySet())
6561
|| (selectedService == ServiceType.AZURE
@@ -82,7 +78,7 @@ public void actionPerformed(@NotNull AnActionEvent event) {
8278
return;
8379
}
8480

85-
var gitDiff = getGitDiff(project, getCheckedFilePaths(event));
81+
var gitDiff = getGitDiff(project, getReferencedFilePaths(event));
8682
var tokenCount = encodingManager.countTokens(gitDiff);
8783
if (tokenCount > 4096 && OverlayUtil.showTokenSoftLimitWarningDialog(tokenCount) != OK) {
8884
return;
@@ -91,25 +87,8 @@ public void actionPerformed(@NotNull AnActionEvent event) {
9187
var editor = getCommitMessageEditor(event);
9288
if (editor != null) {
9389
((EditorEx) editor).setCaretVisible(false);
94-
generateMessage(project, editor, gitDiff);
95-
}
96-
}
97-
98-
private void generateMessage(Project project, Editor editor, String gitDiff) {
99-
var request = new OpenAIChatCompletionRequest.Builder(List.of(
100-
new OpenAIChatCompletionMessage("system",
101-
ConfigurationState.getInstance().getCommitMessagePrompt()),
102-
new OpenAIChatCompletionMessage("user", gitDiff)))
103-
.setModel(OpenAISettingsState.getInstance().getModel())
104-
.build();
105-
var selectedService = SettingsState.getInstance().getSelectedService();
106-
if (selectedService == ServiceType.OPENAI) {
107-
CompletionClientProvider.getOpenAIClient()
108-
.getChatCompletion(request, getEventListener(project, editor.getDocument()));
109-
}
110-
if (selectedService == ServiceType.AZURE) {
111-
CompletionClientProvider.getAzureClient()
112-
.getChatCompletion(request, getEventListener(project, editor.getDocument()));
90+
CompletionRequestService.getInstance()
91+
.generateCommitMessageAsync(gitDiff, getEventListener(project, editor.getDocument()));
11392
}
11493
}
11594

@@ -166,7 +145,7 @@ private Process createGitDiffProcess(String projectPath, List<String> filePaths)
166145
}
167146
}
168147

169-
private @NotNull List<String> getCheckedFilePaths(AnActionEvent event) {
148+
private @NotNull List<String> getReferencedFilePaths(AnActionEvent event) {
170149
var changesBrowserBase = event.getData(ChangesBrowserBase.DATA_KEY);
171150
if (changesBrowserBase == null) {
172151
return List.of();

src/main/java/ee/carlrobert/codegpt/actions/IncludeFilesInContextAction.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import ee.carlrobert.codegpt.ui.checkbox.PsiElementCheckboxTree;
3131
import ee.carlrobert.codegpt.ui.checkbox.VirtualFileCheckboxTree;
3232
import ee.carlrobert.codegpt.util.file.FileUtil;
33-
import ee.carlrobert.embedding.CheckedFile;
33+
import ee.carlrobert.embedding.ReferencedFile;
3434
import java.awt.Dimension;
3535
import java.io.IOException;
3636
import java.nio.file.Files;
@@ -62,7 +62,7 @@ public void actionPerformed(@NotNull AnActionEvent e) {
6262
throw new RuntimeException("Could not obtain file tree");
6363
}
6464

65-
var totalTokensLabel = new TotalTokensLabel(checkboxTree.getCheckedFiles());
65+
var totalTokensLabel = new TotalTokensLabel(checkboxTree.getReferencedFiles());
6666
checkboxTree.addCheckboxTreeListener(new CheckboxTreeListener() {
6767
@Override
6868
public void nodeStateChanged(@NotNull CheckedTreeNode node) {
@@ -81,10 +81,10 @@ public void nodeStateChanged(@NotNull CheckedTreeNode node) {
8181
totalTokensLabel,
8282
checkboxTree);
8383
if (show == OK_EXIT_CODE) {
84-
project.putUserData(CodeGPTKeys.SELECTED_FILES, checkboxTree.getCheckedFiles());
84+
project.putUserData(CodeGPTKeys.SELECTED_FILES, checkboxTree.getReferencedFiles());
8585
project.getMessageBus()
8686
.syncPublisher(IncludeFilesInContextNotifier.FILES_INCLUDED_IN_CONTEXT_TOPIC)
87-
.filesIncluded(checkboxTree.getCheckedFiles());
87+
.filesIncluded(checkboxTree.getReferencedFiles());
8888
includedFilesSettings.setPromptTemplate(promptTemplateTextArea.getText());
8989
includedFilesSettings.setRepeatableContext(repeatableContextTextArea.getText());
9090
}
@@ -111,9 +111,9 @@ private static class TotalTokensLabel extends JBLabel {
111111
private int fileCount;
112112
private int totalTokens;
113113

114-
TotalTokensLabel(List<CheckedFile> checkedFiles) {
115-
fileCount = checkedFiles.size();
116-
totalTokens = calculateTotalTokens(checkedFiles);
114+
TotalTokensLabel(List<ReferencedFile> referencedFiles) {
115+
fileCount = referencedFiles.size();
116+
totalTokens = calculateTotalTokens(referencedFiles);
117117
updateText();
118118
}
119119

@@ -167,8 +167,8 @@ private void updateText() {
167167
FileUtil.convertLongValue(totalTokens)));
168168
}
169169

170-
private int calculateTotalTokens(List<CheckedFile> checkedFiles) {
171-
return checkedFiles.stream()
170+
private int calculateTotalTokens(List<ReferencedFile> referencedFiles) {
171+
return referencedFiles.stream()
172172
.mapToInt(file -> encodingManager.countTokens(file.getFileContent()))
173173
.sum();
174174
}

0 commit comments

Comments
 (0)