Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better diff matching #132

Merged
merged 2 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ repositories {
val kotlin_version = "1.9.21"
val jetty_version = "11.0.18"
val slf4j_version = "2.0.9"
val skyenet_version = "1.0.46"
val skyenet_version = "1.0.47"
val remoterobot_version = "0.11.21"
dependencies {

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

implementation(group = "com.simiacryptus.skyenet", name = "kotlin", version = skyenet_version)
{
exclude(group = "org.jetbrains.kotlin", module = "")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pluginName=intellij-aicoder
pluginRepositoryUrl=https://github.com/SimiaCryptus/intellij-aicoder
pluginVersion=1.2.25
pluginVersion=1.2.26

jvmArgs=-Xmx8g
org.gradle.jvmargs=-Xmx8g
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,43 @@ import org.slf4j.LoggerFactory
import javax.swing.Icon

abstract class BaseAction(
name: String? = null,
description: String? = null,
icon: Icon? = null,
name: String? = null,
description: String? = null,
icon: Icon? = null,
) : AnAction(name, description, icon) {

private val log by lazy { LoggerFactory.getLogger(javaClass) }
//override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
private val log by lazy { LoggerFactory.getLogger(javaClass) }
//override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT

val api: OpenAIClient
get() = IdeaOpenAIClient.instance
val api: OpenAIClient
get() = IdeaOpenAIClient.instance

final override fun update(event: AnActionEvent) {
event.presentation.isEnabledAndVisible = isEnabled(event)
super.update(event)
}
final override fun update(event: AnActionEvent) {
event.presentation.isEnabledAndVisible = isEnabled(event)
super.update(event)
}

abstract fun handle(e: AnActionEvent)
abstract fun handle(e: AnActionEvent)


final override fun actionPerformed(e: AnActionEvent) {
UITools.logAction("""
final override fun actionPerformed(e: AnActionEvent) {
UITools.logAction(
"""
|Action: ${javaClass.simpleName}
""".trimMargin().trim())
IdeaOpenAIClient.lastEvent = e
try {
handle(e)
} catch (e: Throwable) {
UITools.error(log, "Error in Action ${javaClass.simpleName}", e)
}
""".trimMargin().trim()
)
IdeaOpenAIClient.lastEvent = e
try {
handle(e)
} catch (e: Throwable) {
UITools.error(log, "Error in Action ${javaClass.simpleName}", e)
}
}

open fun isEnabled(event: AnActionEvent): Boolean = true

open fun isEnabled(event: AnActionEvent): Boolean = true
companion object {
val log by lazy { LoggerFactory.getLogger(javaClass) }
val scheduledPool = java.util.concurrent.Executors.newScheduledThreadPool(1)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package com.github.simiacryptus.aicoder.actions
import com.github.simiacryptus.aicoder.config.AppSettingsState
import com.github.simiacryptus.aicoder.util.UITools
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import org.slf4j.LoggerFactory
import java.io.File
import java.nio.file.Path
import java.util.concurrent.TimeUnit

abstract class FileContextAction<T : Any>(
private val supportsFiles: Boolean = true,
Expand Down Expand Up @@ -42,18 +45,16 @@ abstract class FileContextAction<T : Any>(
if (it.isCanceled) throw InterruptedException()
}
UITools.writeableFn(e) {
val files = newFiles.map { file ->
val files = newFiles.mapNotNull { file ->
val localFileSystem = LocalFileSystem.getInstance()
localFileSystem.findFileByIoFile(file.parentFile)?.refresh(false, true)
val generatedFile = localFileSystem.findFileByIoFile(file)
if (generatedFile == null) {
log.warn("Generated file not found: ${file.path}")
} else {
generatedFile.refresh(false, false)
FileEditorManager.getInstance(project).openFile(generatedFile, true)
open(project, file.toPath())
}
generatedFile
}.filter { it != null }.toTypedArray<VirtualFile?>()
}.toTypedArray<VirtualFile?>()
Runnable {
files.forEach { it?.delete(this@FileContextAction) }
}
Expand All @@ -78,6 +79,33 @@ abstract class FileContextAction<T : Any>(

companion object {
private val log = LoggerFactory.getLogger(FileContextAction::class.java)

fun open(project: Project, outputPath: Path) {
lateinit var function: () -> Unit
function = {
val file = outputPath.toFile()
if (file.exists()) {
// Ensure the IDE is ready for file operations
ApplicationManager.getApplication().invokeLater {
val ioFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
if (false == (ioFile?.let { FileEditorManager.getInstance(project).isFileOpen(it) })) {
val localFileSystem = LocalFileSystem.getInstance()
// Refresh the file system to ensure the file is visible
val virtualFile = localFileSystem.refreshAndFindFileByIoFile(file)
virtualFile?.let {
FileEditorManager.getInstance(project).openFile(it, true)
} ?: scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
} else {
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}
}
} else {
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}
}
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import com.github.simiacryptus.aicoder.actions.FileContextAction
import com.github.simiacryptus.aicoder.config.AppSettingsState
import com.github.simiacryptus.aicoder.config.Name
import com.github.simiacryptus.aicoder.util.UITools
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.simiacryptus.jopenai.ApiModel
import com.simiacryptus.jopenai.ApiModel.ChatMessage
import com.simiacryptus.jopenai.ApiModel.Role
Expand All @@ -13,6 +16,8 @@ import org.apache.commons.io.FileUtils
import org.apache.commons.io.IOUtils
import java.io.File
import java.io.FileInputStream
import java.nio.file.Path
import java.util.concurrent.TimeUnit
import javax.swing.JTextArea

class AnalogueFileAction : FileContextAction<AnalogueFileAction.Settings>() {
Expand All @@ -33,39 +38,48 @@ class AnalogueFileAction : FileContextAction<AnalogueFileAction.Settings>() {
)
}

class Settings (
var directive: String = ""
class UserSettings(
var directive: String = "",
)

override fun getConfig(project: Project?): Settings? {
return UITools.showDialog(
project,
SettingsUI::class.java,
Settings::class.java,
"Create Analogue File"
class Settings(
val settings: UserSettings? = null,
val project: Project? = null
)

override fun getConfig(project: Project?): Settings {
return Settings(
UITools.showDialog(
project,
SettingsUI::class.java,
UserSettings::class.java,
"Create Analogue File"
), project
)
}

override fun processSelection(state: SelectionState, config: Settings?): Array<File> {
val root = getModuleRootForFile(state.selectedFile).toPath()
val selectedFile = state.selectedFile
val analogue = generateFile(
ProjectFile(
path = state.projectRoot.toPath().relativize(state.selectedFile.toPath()).toString(),
code = IOUtils.toString(FileInputStream(state.selectedFile), "UTF-8")
path = root.relativize(selectedFile.toPath()).toString(),
code = IOUtils.toString(FileInputStream(selectedFile), "UTF-8")
),
config?.directive ?: ""
config?.settings?.directive ?: ""
)
var outputPath = state.projectRoot.toPath().resolve(analogue.path)
var outputPath = root.resolve(analogue.path)
if (outputPath.toFile().exists()) {
val extension = outputPath.toString().split(".").last()
val name = outputPath.toString().split(".").dropLast(1).joinToString(".")
val fileIndex = (1..Int.MAX_VALUE).find {
!File(state.projectRoot, "$name.$it.$extension").exists()
!root.resolve("$name.$it.$extension").toFile().exists()
}
outputPath = state.projectRoot.toPath().resolve("$name.$fileIndex.$extension")
outputPath = root.resolve("$name.$fileIndex.$extension")
}
outputPath.parent.toFile().mkdirs()
FileUtils.write(outputPath.toFile(), analogue.code, "UTF-8")
Thread.sleep(100)
open(config?.project!!, outputPath)
return arrayOf(outputPath.toFile())
}

Expand Down Expand Up @@ -95,13 +109,9 @@ class AnalogueFileAction : FileContextAction<AnalogueFileAction.Settings>() {
```
""".trimIndent().toContentList(), null
)

)
)
val response = api.chat(
chatRequest,
AppSettingsState.instance.defaultChatModel()
).choices.first().message?.content?.trim()
val response = api.chat(chatRequest, model).choices.first().message?.content?.trim()
var outputPath = baseFile.path
val header = response?.split("\n")?.first()
var body = response?.split("\n")?.drop(1)?.joinToString("\n")?.trim()
Expand All @@ -118,4 +128,43 @@ class AnalogueFileAction : FileContextAction<AnalogueFileAction.Settings>() {
code = body ?: ""
)
}

companion object {
fun open(project: Project, outputPath: Path) {
lateinit var function: () -> Unit
function = {
val file = outputPath.toFile()
if (file.exists()) {
// Ensure the IDE is ready for file operations
ApplicationManager.getApplication().invokeLater {
val ioFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
if (false == (ioFile?.let { FileEditorManager.getInstance(project).isFileOpen(it) })) {
val localFileSystem = LocalFileSystem.getInstance()
// Refresh the file system to ensure the file is visible
val virtualFile = localFileSystem.refreshAndFindFileByIoFile(file)
virtualFile?.let {
FileEditorManager.getInstance(project).openFile(it, true)
} ?: scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
} else {
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}
}
} else {
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}
}
scheduledPool.schedule(function, 100, TimeUnit.MILLISECONDS)
}

fun getModuleRootForFile(file: File): File {
var current = file
while (current.parentFile != null) {
if (current.resolve(".git").exists()) {
return current
}
current = current.parentFile
}
return file
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class DiffChatAction : BaseAction() {
The diff should include 2 lines of context before and after every change.
""".trimIndent()

val diffPattern = """(?s)```diff(.*?)```""".toRegex()
val diffPattern = """(?s)(?<![^\n])```diff(.*?)\n```""".toRegex()
var fullPatch = mutableListOf<String>()
override fun renderResponse(response: String): String {
val matches = diffPattern.findAll(response).distinct()
Expand Down
Loading
Loading