From e26034367eba4ba8e3fc0cec28edb0d3307bab54 Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Thu, 5 Sep 2024 15:50:26 +0300 Subject: [PATCH] fix: build errors --- .../CodeCompletionEventListener.java | 4 +- .../CodeCompletionRequestProvider.java | 13 +- .../CodeCompletionServiceOld.java | 2 +- .../completions/CompletionRequestService.java | 6 +- .../CodeGPTInlineCompletionSuggestion.kt | 170 ------------------ .../chat/ToolwindowEditorActionLink.kt | 2 +- .../CodeCompletionServiceTest.kt | 10 +- 7 files changed, 19 insertions(+), 188 deletions(-) delete mode 100644 src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionSuggestion.kt diff --git a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionEventListener.java b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionEventListener.java index c90596de..14f29789 100644 --- a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionEventListener.java +++ b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionEventListener.java @@ -23,13 +23,13 @@ class CodeCompletionEventListener implements CompletionEventListener { private final Editor editor; private final int caretOffset; - private final InfillRequestDetails requestDetails; + private final InfillRequest requestDetails; private final BackgroundableProcessIndicator progressIndicator; public CodeCompletionEventListener( Editor editor, int caretOffset, - InfillRequestDetails requestDetails, + InfillRequest requestDetails, @Nullable BackgroundableProcessIndicator progressIndicator) { this.editor = editor; this.caretOffset = caretOffset; diff --git a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java index baea6f8b..798637a6 100644 --- a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestProvider.java @@ -9,15 +9,15 @@ public class CodeCompletionRequestProvider { private static final int MAX_TOKENS = 128; - private final InfillRequestDetails details; + private final InfillRequest request; - public CodeCompletionRequestProvider(InfillRequestDetails details) { - this.details = details; + public CodeCompletionRequestProvider(InfillRequest request) { + this.request = request; } public OpenAITextCompletionRequest buildOpenAIRequest() { - return new OpenAITextCompletionRequest.Builder(details.getPrefix()) - .setSuffix(details.getSuffix()) + return new OpenAITextCompletionRequest.Builder(request.getPrefix()) + .setSuffix(request.getSuffix()) .setStream(true) .setMaxTokens(MAX_TOKENS) .setTemperature(0.1) @@ -26,8 +26,7 @@ public class CodeCompletionRequestProvider { public LlamaCompletionRequest buildLlamaRequest() { InfillPromptTemplate promptTemplate = getLlamaInfillPromptTemplate(); - String prompt = promptTemplate.buildPrompt( - new InfillRequestDetails(details.getPrefix(), details.getSuffix(), null)); + String prompt = promptTemplate.buildPrompt(request); return new LlamaCompletionRequest.Builder(prompt) .setN_predict(MAX_TOKENS) .setStream(true) diff --git a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceOld.java b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceOld.java index d6f4676e..a5fa48c0 100644 --- a/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceOld.java +++ b/src/main/java/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceOld.java @@ -91,7 +91,7 @@ public final class CodeCompletionServiceOld implements Disposable { var prefix = document.getText(new TextRange(0, offset)); var suffix = document.getText(new TextRange(offset, document.getTextLength())); - var request = InfillRequestDetails.Companion.withoutContext(prefix, suffix); + var request = InfillRequest.Companion.builder(prefix, suffix).build(); if (Stream.of(request.getSuffix(), request.getPrefix()).anyMatch(String::isEmpty)) { return; } diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java index 627e5236..547de07c 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java @@ -5,7 +5,7 @@ import com.intellij.openapi.components.Service; import com.intellij.openapi.diagnostic.Logger; import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestFactory; import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestProvider; -import ee.carlrobert.codegpt.codecompletions.InfillRequestDetails; +import ee.carlrobert.codegpt.codecompletions.InfillRequest; import ee.carlrobert.codegpt.completions.llama.LlamaModel; import ee.carlrobert.codegpt.completions.llama.PromptTemplate; import ee.carlrobert.codegpt.credentials.CredentialsStore; @@ -133,13 +133,13 @@ public final class CompletionRequestService { } public EventSource getCodeCompletionAsync( - InfillRequestDetails requestDetails, + InfillRequest requestDetails, CompletionEventListener eventListener) { var httpClient = CompletionClientProvider.getDefaultClientBuilder().build(); var requestProvider = new CodeCompletionRequestProvider(requestDetails); return switch (GeneralSettings.getCurrentState().getSelectedService()) { case CODEGPT -> CompletionClientProvider.getCodeGPTClient() - .getCompletionAsync( + .getCodeCompletionAsync( CodeCompletionRequestFactory.buildCodeGPTRequest(requestDetails), eventListener); case OPENAI -> CompletionClientProvider.getOpenAIClient() diff --git a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionSuggestion.kt b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionSuggestion.kt deleted file mode 100644 index 34a52801..00000000 --- a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeGPTInlineCompletionSuggestion.kt +++ /dev/null @@ -1,170 +0,0 @@ -package ee.carlrobert.codegpt.codecompletions - -import com.intellij.codeInsight.inline.completion.InlineCompletionRequest -import com.intellij.codeInsight.inline.completion.elements.InlineCompletionGrayTextElement -import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionSingleSuggestion -import com.intellij.codeInsight.inline.completion.suggestion.InlineCompletionVariant -import com.intellij.notification.NotificationType -import com.intellij.openapi.application.EDT -import com.intellij.openapi.application.runInEdt -import com.intellij.openapi.components.service -import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.TextRange -import com.intellij.openapi.vcs.VcsException -import com.intellij.refactoring.suggested.startOffset -import ee.carlrobert.codegpt.EncodingManager -import ee.carlrobert.codegpt.codecompletions.psi.CompletionContextService -import ee.carlrobert.codegpt.codecompletions.psi.readText -import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings -import ee.carlrobert.codegpt.ui.OverlayUtil.showNotification -import ee.carlrobert.codegpt.util.GitUtil -import ee.carlrobert.llm.client.openai.completion.ErrorDetails -import ee.carlrobert.llm.completion.CompletionEventListener -import git4idea.repo.GitRepositoryManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.channelFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import okhttp3.sse.EventSource -import java.util.concurrent.atomic.AtomicReference - -class CodeGPTInlineCompletionSuggestion( - private val project: Project, - private val inlineCompletionRequest: InlineCompletionRequest -) : InlineCompletionSingleSuggestion { - - private val currentCall = AtomicReference(null) - - companion object { - private val logger = thisLogger() - private const val MAX_PROMPT_TOKENS = 128 - } - - override suspend fun getVariant() = InlineCompletionVariant.build(elements = channelFlow { - val infillRequest = buildInfillRequest(inlineCompletionRequest) - launch { - val completionCall = - project.service().getCodeCompletionAsync( - infillRequest, - CodeCompletionEventListener { - try { - runInEdt { - trySend(InlineCompletionGrayTextElement(it.toString())) - } - } catch (e: Exception) { - logger.error("Failed to send inline completion suggestion", e) - } - } - ) - currentCall.set(completionCall) - } - awaitClose { currentCall.getAndSet(null)?.cancel() } - }) - - private class CodeCompletionEventListener( - private val completed: (StringBuilder) -> Unit - ) : CompletionEventListener { - - override fun onComplete(messageBuilder: StringBuilder) { - completed(messageBuilder) - } - - override fun onCancelled(messageBuilder: StringBuilder) { - completed(messageBuilder) - } - - override fun onError(error: ErrorDetails, ex: Throwable) { - if (ex.message == null || (ex.message != null && ex.message != "Canceled")) { - showNotification(error.message, NotificationType.ERROR) - logger.error(error.message, ex) - } - } - } - - private suspend fun buildInfillRequest(request: InlineCompletionRequest): InfillRequest { - val caretOffset = withContext(Dispatchers.EDT) { request.editor.caretModel.offset } - val configurationState = service().state - val (prefix, suffix) = withContext(Dispatchers.EDT) { - val prefix = - request.document.getText(TextRange(0, caretOffset)) - val suffix = - request.document.getText( - TextRange( - caretOffset, - request.document.textLength - ) - ) - Pair( - prefix.truncateText(MAX_PROMPT_TOKENS, false), - suffix.truncateText(MAX_PROMPT_TOKENS) - ) - } - val fileExtension = request.file.virtualFile.extension - val fileContent = request.document.text - val infillRequestBuilder = InfillRequest.Builder(prefix, suffix) - .fileDetails(InfillRequest.FileDetails(fileContent, fileExtension)) - val project = request.editor.project ?: return infillRequestBuilder.build() - - val gitRepository = - project.service().getRepositoryForFile(project.workspaceFile) - if (configurationState.autocompletionGitContextEnabled && gitRepository != null) { - try { - val stagedDiff = GitUtil.getStagedDiff(project, gitRepository) - val unstagedDiff = GitUtil.getUnstagedDiff(project, gitRepository) - if (stagedDiff.isNotEmpty() || unstagedDiff.isNotEmpty()) { - infillRequestBuilder.vcsDetails( - InfillRequest.VcsDetails( - stagedDiff.joinToString("\n"), - unstagedDiff.joinToString("\n") - ) - ) - } - } catch (e: VcsException) { - logger.error("Failed to get git context", e) - } - } - - getInfillContext(request, caretOffset)?.let { infillRequestBuilder.context(it) } - - return infillRequestBuilder.build() - } - - private fun getInfillContext( - request: InlineCompletionRequest, - caretOffset: Int - ): InfillContext? { - val infillContext = - if (service().state.autocompletionContextAwareEnabled) - service().findContext(request.editor, caretOffset) - else null - - if (infillContext == null) { - return null - } - - val caretInEnclosingElement = - caretOffset - infillContext.enclosingElement.psiElement.startOffset - val entireText = infillContext.enclosingElement.psiElement.readText() - val prefix = entireText.take(caretInEnclosingElement) - val suffix = - if (entireText.length < caretInEnclosingElement) "" else entireText.takeLast( - entireText.length - caretInEnclosingElement - ) - return truncateContext(prefix + suffix, infillContext) - } - - private fun String.truncateText(maxTokens: Int, fromStart: Boolean = true): String { - return service().truncateText(this, maxTokens, fromStart) - } - - private fun truncateContext(prompt: String, infillContext: InfillContext): InfillContext { - var promptTokens = EncodingManager.getInstance().countTokens(prompt) - val truncatedContextElements = infillContext.contextElements.takeWhile { - promptTokens += it.tokens - promptTokens <= MAX_PROMPT_TOKENS - }.toSet() - return InfillContext(infillContext.enclosingElement, truncatedContextElements) - } -} \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/ToolwindowEditorActionLink.kt b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/ToolwindowEditorActionLink.kt index 27ecf29a..f14d1c64 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/ToolwindowEditorActionLink.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/ToolwindowEditorActionLink.kt @@ -16,7 +16,7 @@ open class ToolwindowEditorActionLink( private val highlightedText: String, ) : AnActionLink(title, action) { - private val mainEditor = project.service().selectedTextEditor + private val mainEditor = FileEditorManager.getInstance(project).selectedTextEditor private val documentListener = object : DocumentListener { override fun documentChanged(event: DocumentEvent) { updateActionState() diff --git a/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt b/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt index 2f193335..976c0dd5 100644 --- a/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt +++ b/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt @@ -15,26 +15,28 @@ import org.assertj.core.api.Assertions.assertThat import testsupport.IntegrationTest class CodeCompletionServiceTest : IntegrationTest() { - private val cursorPosition = VisualPosition(3, 0) + private val cursorPosition = VisualPosition(1, 0) fun testFetchCodeCompletionLlama() { useLlamaService() LlamaSettings.getCurrentState().isCodeCompletionsEnabled = true myFixture.configureByText( "CompletionTest.java", - getResourceContent("/codecompletions/code-completion-file.txt") + """ + [INPUT] + + [\INPUT] + """.trimIndent() ) val editor = myFixture.editor val expectedCompletion = "TEST_SINGLE_LINE_OUTPUT\nTEST_MULTI_LINE_OUTPUT" val prefix = """ - ${"z".repeat(245)} [INPUT] c """.trimIndent() // 128 tokens val suffix = """ [\INPUT] - ${"z".repeat(247)} """.trimIndent() // 128 tokens expectLlama(StreamHttpExchange { request: RequestEntity -> assertThat(request.uri.path)