From 6e432f7fe8bea2de908648c6dfb5523c405690a7 Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Wed, 8 Oct 2025 16:40:43 +0100 Subject: [PATCH 1/2] feat: enable auto apply for inception labs --- .../completions/CompletionRequestService.java | 4 - .../factory/InceptionRequestFactory.kt | 4 +- .../chat/editor/ResponseEditorPanel.kt | 104 +++++++++++------- .../chat/editor/actions/AutoApplyAction.kt | 9 -- .../chat/editor/header/DefaultHeaderPanel.kt | 20 +++- 5 files changed, 82 insertions(+), 59 deletions(-) diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java index a55daf29..a29b5ed6 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestService.java @@ -84,10 +84,6 @@ public EventSource autoApplyAsync( var selectedService = ModelSelectionService.getInstance().getServiceForFeature(FeatureType.AUTO_APPLY); - if (selectedService == INCEPTION) { - return null; - } - var request = CompletionRequestFactory .getFactory(selectedService) .createAutoApplyRequest(params); diff --git a/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/InceptionRequestFactory.kt b/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/InceptionRequestFactory.kt index 497fc9af..b31df424 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/InceptionRequestFactory.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/InceptionRequestFactory.kt @@ -36,10 +36,10 @@ class InceptionRequestFactory : BaseRequestFactory() { .build() } - override fun createAutoApplyRequest(params: AutoApplyParameters): CompletionRequest { + override fun createAutoApplyRequest(params: AutoApplyParameters): InceptionApplyRequest { val model = ModelSelectionService.getInstance().getModelForFeature(FeatureType.AUTO_APPLY) val prompt = - "<|original_code|>\n" + EditorUtil.getFileContent(params.destination) + "\n<|/original_code|>\n\n<|update_snippet|>\n// ... existing code ...\n" + params.source + "\n// ... existing code ...\n<|/update_snippet|>" + "<|original_code|>\n" + EditorUtil.getFileContent(params.destination) + "\n<|/original_code|>\n\n<|update_snippet|>\n" + params.source + "\n<|/update_snippet|>" return InceptionApplyRequest.Builder() .setModel(model) diff --git a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt index 7751e5cd..d864773d 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt @@ -16,17 +16,18 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.readText import com.intellij.util.application import com.intellij.util.ui.JBUI import com.intellij.util.ui.components.BorderLayoutPanel -import ee.carlrobert.codegpt.CodeGPTKeys.CODEGPT_USER_DETAILS import ee.carlrobert.codegpt.codecompletions.CompletionProgressNotifier import ee.carlrobert.codegpt.completions.AutoApplyParameters import ee.carlrobert.codegpt.completions.CompletionClientProvider import ee.carlrobert.codegpt.completions.CompletionRequestService +import ee.carlrobert.codegpt.completions.factory.InceptionRequestFactory +import ee.carlrobert.codegpt.settings.models.ModelSelection import ee.carlrobert.codegpt.settings.service.FeatureType import ee.carlrobert.codegpt.settings.service.ModelSelectionService +import ee.carlrobert.codegpt.settings.service.ServiceType.INCEPTION import ee.carlrobert.codegpt.settings.service.ServiceType.PROXYAI import ee.carlrobert.codegpt.toolwindow.chat.editor.diff.DiffSyncManager import ee.carlrobert.codegpt.toolwindow.chat.editor.factory.ComponentFactory @@ -39,10 +40,9 @@ import ee.carlrobert.codegpt.toolwindow.chat.editor.state.EditorStateManager import ee.carlrobert.codegpt.toolwindow.chat.parser.ReplaceWaiting import ee.carlrobert.codegpt.toolwindow.chat.parser.SearchReplace import ee.carlrobert.codegpt.toolwindow.chat.parser.Segment -import ee.carlrobert.codegpt.util.ApplicationUtil import ee.carlrobert.codegpt.util.EditorUtil -import ee.carlrobert.codegpt.util.file.FileUtil import ee.carlrobert.llm.client.codegpt.request.AutoApplyRequest +import java.util.regex.Pattern class ResponseEditorPanel( private val project: Project, @@ -116,47 +116,59 @@ class ResponseEditorPanel( replaceEditor(oldEditor, newState.editor) } - fun applyCodeAsync( - content: String, - virtualFile: VirtualFile, - editor: EditorEx, - headerPanel: DefaultHeaderPanel? = null + fun applyCode( + modelSelection: ModelSelection, + params: AutoApplyParameters, + headerPanel: DefaultHeaderPanel ) { - var selectedService = - ModelSelectionService.getInstance().getServiceForFeature(FeatureType.AUTO_APPLY); - - if (selectedService == PROXYAI) { - val panel = headerPanel ?: (editor.permanentHeaderComponent as? DefaultHeaderPanel) - panel?.setLoading() - CompletionProgressNotifier.update(project, true) - application.executeOnPooledThread { - val pricingPlan = - CODEGPT_USER_DETAILS[ApplicationUtil.findCurrentProject()]?.pricingPlan - val model = service() - .getModelForFeature(FeatureType.AUTO_APPLY, pricingPlan) - val originalCode = EditorUtil.getFileContent(virtualFile) - try { - val request = AutoApplyRequest(model, originalCode, content) - val response = CompletionClientProvider.getCodeGPTClient().applyChanges(request) - stateManager.transitionToDiffState(originalCode, response.mergedCode, virtualFile) - } catch (e: Exception) { - logger.error("Failed to apply changes", e) - ApplicationManager.getApplication().invokeLater { - if (!project.isDisposed) { - panel?.handleDone() - } + headerPanel.setLoading() + CompletionProgressNotifier.update(project, true) + + application.executeOnPooledThread { + val model = service().getModelForFeature(FeatureType.AUTO_APPLY) + val originalCode = EditorUtil.getFileContent(params.destination) + try { + val response = if (modelSelection.provider == INCEPTION) { + val request = InceptionRequestFactory().createAutoApplyRequest(params) + val responseContent = CompletionClientProvider.getInceptionClient() + .getApplyEditCompletion(request) + .choices[0] + .message + .content + extractUpdatedCode(responseContent) + } else if (modelSelection.provider == PROXYAI) { + val request = AutoApplyRequest(model, originalCode, params.source) + CompletionClientProvider.getCodeGPTClient().applyChanges(request).mergedCode + } else { + null + } + + if (!response.isNullOrBlank()) { + stateManager.transitionToDiffState(originalCode, response, params.destination) + } + } catch (e: Exception) { + logger.error("Failed to apply changes", e) + ApplicationManager.getApplication().invokeLater { + if (!project.isDisposed) { + headerPanel.handleDone() } - } finally { - ApplicationManager.getApplication().invokeLater { - if (!project.isDisposed) { - CompletionProgressNotifier.update(project, false) - } + } + } finally { + if (!project.isDisposed) { + runInEdt { + CompletionProgressNotifier.update(project, false) } } } - return } + } + fun applyCodeAsync( + content: String, + virtualFile: VirtualFile, + editor: EditorEx, + headerPanel: DefaultHeaderPanel + ) { val eventSource = CompletionRequestService.getInstance().autoApplyAsync( AutoApplyParameters(content, virtualFile), AutoApplyListener(project, stateManager, virtualFile, content) { oldEditor, newEditor -> @@ -165,8 +177,7 @@ class ResponseEditorPanel( responseEditorPanel.replaceEditor(oldEditor, newEditor) }) - val panel = headerPanel ?: (editor.permanentHeaderComponent as? DefaultHeaderPanel) - panel?.setLoading(eventSource) + headerPanel.setLoading(eventSource) } internal fun createReplaceWaitingSegment( @@ -310,4 +321,15 @@ class ResponseEditorPanel( ) } } -} + + private fun extractUpdatedCode(content: String): String { + val pattern = + Pattern.compile("<\\|updated_code\\|>(.*?)<\\|/updated_code\\|>", Pattern.DOTALL) + val matcher = pattern.matcher(content) + return if (matcher.find()) { + matcher.group(1).trim() + } else { + content + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/AutoApplyAction.kt b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/AutoApplyAction.kt index eee63a06..3ab77ffb 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/AutoApplyAction.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/AutoApplyAction.kt @@ -36,15 +36,6 @@ class AutoApplyAction( } override fun update(e: AnActionEvent) { - val autoApplyProvider = - ModelSelectionService.getInstance().getServiceForFeature(FeatureType.AUTO_APPLY) - if (autoApplyProvider == INCEPTION) { - anActionLink.text = "Apply" - anActionLink.isEnabled = false - anActionLink.toolTipText = "Auto Apply is temporarily disabled for Inception provider" - return - } - if (virtualFile != null) { anActionLink.text = "Apply" anActionLink.isEnabled = true diff --git a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/header/DefaultHeaderPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/header/DefaultHeaderPanel.kt index 8f9233d5..1544cd6e 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/header/DefaultHeaderPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/header/DefaultHeaderPanel.kt @@ -9,9 +9,13 @@ import com.intellij.openapi.editor.ex.EditorEx import com.intellij.openapi.project.Project import com.intellij.openapi.ui.JBMenuItem import com.intellij.openapi.ui.JBPopupMenu -import com.intellij.openapi.vfs.readText import com.intellij.util.ui.JBUI import ee.carlrobert.codegpt.CodeGPTBundle +import ee.carlrobert.codegpt.completions.AutoApplyParameters +import ee.carlrobert.codegpt.settings.service.FeatureType +import ee.carlrobert.codegpt.settings.service.ModelSelectionService +import ee.carlrobert.codegpt.settings.service.ServiceType.INCEPTION +import ee.carlrobert.codegpt.settings.service.ServiceType.PROXYAI import ee.carlrobert.codegpt.toolwindow.chat.editor.ResponseEditorPanel import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.* import ee.carlrobert.codegpt.util.EditorUtil @@ -90,7 +94,8 @@ class DefaultHeaderPanel(config: HeaderConfig) : HeaderPanel(config) { ?: throw IllegalStateException("Could not find editor panel") val directApplyThreshold = 0.85 - val coefficient = StringUtil.getDiceCoefficient(editor.document.text, EditorUtil.getFileContent(file)) + val coefficient = + StringUtil.getDiceCoefficient(editor.document.text, EditorUtil.getFileContent(file)) if (coefficient > directApplyThreshold) { responseEditorPanel.createDiffEditorForDirectApply( EditorUtil.getFileContent(file), @@ -99,7 +104,16 @@ class DefaultHeaderPanel(config: HeaderConfig) : HeaderPanel(config) { ) return } - responseEditorPanel.applyCodeAsync(editor.document.text, file, editor, this) + + val modelSelection = + ModelSelectionService.getInstance() + .getModelSelectionForFeature(FeatureType.AUTO_APPLY); + val params = AutoApplyParameters(editor.document.text, file) + if (listOf(PROXYAI, INCEPTION).any { it == modelSelection.provider }) { + responseEditorPanel.applyCode(modelSelection, params, this) + } else { + responseEditorPanel.applyCodeAsync(editor.document.text, file, editor, this) + } } catch (e: Exception) { logger.error(e.message, e) } From 86d5ed26e499b89f05b55bdcd481d40e51b2cff2 Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Thu, 9 Oct 2025 10:17:59 +0100 Subject: [PATCH 2/2] fix: improve auto apply error handling --- .../codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt index d864773d..deaf48b4 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.kt @@ -1,6 +1,7 @@ package ee.carlrobert.codegpt.toolwindow.chat.editor import com.intellij.diff.tools.fragmented.UnifiedDiffViewer +import com.intellij.notification.NotificationType import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.runInEdt @@ -40,8 +41,10 @@ import ee.carlrobert.codegpt.toolwindow.chat.editor.state.EditorStateManager import ee.carlrobert.codegpt.toolwindow.chat.parser.ReplaceWaiting import ee.carlrobert.codegpt.toolwindow.chat.parser.SearchReplace import ee.carlrobert.codegpt.toolwindow.chat.parser.Segment +import ee.carlrobert.codegpt.ui.OverlayUtil import ee.carlrobert.codegpt.util.EditorUtil import ee.carlrobert.llm.client.codegpt.request.AutoApplyRequest +import ee.carlrobert.llm.client.codegpt.response.CodeGPTException import java.util.regex.Pattern class ResponseEditorPanel( @@ -149,6 +152,10 @@ class ResponseEditorPanel( } catch (e: Exception) { logger.error("Failed to apply changes", e) ApplicationManager.getApplication().invokeLater { + if (e is CodeGPTException) { + OverlayUtil.showNotification(e.detail, NotificationType.ERROR) + } + if (!project.isDisposed) { headerPanel.handleDone() }