fix: build errors

This commit is contained in:
Carl-Robert Linnupuu 2024-09-05 15:50:26 +03:00
parent 15d3423d92
commit e26034367e
7 changed files with 19 additions and 188 deletions

View file

@ -23,13 +23,13 @@ class CodeCompletionEventListener implements CompletionEventListener<String> {
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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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<String> 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()

View file

@ -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<EventSource>(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<CodeCompletionService>().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<String> {
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<ConfigurationSettings>().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<GitRepositoryManager>().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<ConfigurationSettings>().state.autocompletionContextAwareEnabled)
service<CompletionContextService>().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<EncodingManager>().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)
}
}

View file

@ -16,7 +16,7 @@ open class ToolwindowEditorActionLink(
private val highlightedText: String,
) : AnActionLink(title, action) {
private val mainEditor = project.service<FileEditorManager>().selectedTextEditor
private val mainEditor = FileEditorManager.getInstance(project).selectedTextEditor
private val documentListener = object : DocumentListener {
override fun documentChanged(event: DocumentEvent) {
updateActionState()

View file

@ -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)