diff --git a/build.gradle.kts b/build.gradle.kts index 4344fad4..0b98d439 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,5 @@ -import org.jetbrains.changelog.Changelog + +import org.jetbrains.changelog.Changelog import org.jetbrains.changelog.markdownToHTML fun properties(key: String) = providers.gradleProperty(key).get() @@ -7,8 +8,8 @@ fun environment(key: String) = providers.environmentVariable(key).get() plugins { id("java") // Java support id("groovy") - id("org.jetbrains.kotlin.jvm") version "1.9.20" - id("org.jetbrains.intellij") version "1.16.0" + id("org.jetbrains.kotlin.jvm") version "1.9.21" + id("org.jetbrains.intellij") version "1.16.1" id("org.jetbrains.changelog") version "2.2.0" id("org.jetbrains.qodana") version "2023.2.1" id("org.jetbrains.kotlinx.kover") version "0.7.4" @@ -22,17 +23,30 @@ repositories { maven(url = "https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") } -val kotlin_version = "1.9.20" +val kotlin_version = "1.9.21" val jetty_version = "11.0.18" val slf4j_version = "2.0.9" -val skyenet_version = "1.0.40" +val skyenet_version = "1.0.42" dependencies { - implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.36") + implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.40") + { exclude(group = "org.jetbrains.kotlin", module = "") } implementation(group = "com.simiacryptus.skyenet", name = "core", version = skyenet_version) - implementation(group = "com.simiacryptus.skyenet", name = "kotlin", version = skyenet_version) + { exclude(group = "org.jetbrains.kotlin", module = "") } + + compileOnly(group = "com.simiacryptus.skyenet", name = "kotlin", version = skyenet_version) + implementation(group = "com.simiacryptus.skyenet", name = "webui", version = skyenet_version) + { exclude(group = "org.jetbrains.kotlin", module = "") } + +// implementation(kotlin("compiler")) + implementation(files("C:\\Users\\andre\\code\\SkyeNet\\kotlin-hack\\build\\libs\\kotlin-hack-1.0.42.jar")) + +// implementation(group = "com.simiacryptus.skyenet", name = "kotlin-hack", version = "1.0.42") +// { isTransitive = false } + + implementation("org.codehaus.groovy:groovy-all:3.0.13") implementation(group = "org.apache.httpcomponents.client5", name = "httpclient5", version = "5.2.1") implementation(group = "org.eclipse.jetty", name = "jetty-server", version = jetty_version) @@ -42,21 +56,9 @@ dependencies { implementation(group = "org.eclipse.jetty.websocket", name = "websocket-jetty-client", version = jetty_version) implementation(group = "org.eclipse.jetty.websocket", name = "websocket-servlet", version = jetty_version) - implementation("org.codehaus.groovy:groovy-all:3.0.13") - - -// implementation(kotlin("compiler-embeddable")) -// implementation(kotlin("scripting-compiler-embeddable")) -// implementation(kotlin("script-util")) - - implementation(kotlin("stdlib")) - implementation(kotlin("reflect")) - implementation(group = "org.slf4j", name = "slf4j-api", version = slf4j_version) testImplementation(group = "org.slf4j", name = "slf4j-simple", version = slf4j_version) - testImplementation(kotlin("script-runtime")) - testImplementation(group = "com.intellij.remoterobot", name = "remote-robot", version = "0.11.16") testImplementation(group = "com.intellij.remoterobot", name = "remote-fixtures", version = "0.11.16") testImplementation(group = "com.squareup.okhttp3", name = "okhttp", version = "3.14.9") @@ -73,15 +75,20 @@ tasks.named("processResources") { dependsOn("copyGroovySourcesToResources") } + + + + + kotlin { jvmToolchain(17) } tasks { compileKotlin { - kotlinOptions { + compilerOptions { javaParameters = true - jvmTarget = "17" + version = "17" } } @@ -92,7 +99,7 @@ tasks { } compileTestKotlin { - kotlinOptions { + compilerOptions { javaParameters = true } } @@ -157,7 +164,10 @@ intellij { pluginName.set(properties("pluginName")) version.set(properties("platformVersion")) type.set(properties("platformType")) - plugins.set(properties("platformPlugins").split(',').map(String::trim).filter(String::isNotEmpty)) + plugins.set(listOf( + "com.intellij.java", + "org.jetbrains.kotlin:232-1.9.21-release-633-IJ10072.27" + )) } changelog { diff --git a/gradle.properties b/gradle.properties index 08f7012e..3848470c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,47 +1,23 @@ -# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html pluginName=intellij-aicoder pluginRepositoryUrl=https://github.com/SimiaCryptus/intellij-aicoder -# SemVer format -> https://semver.org pluginVersion=1.2.23 + +jvmArgs=-Xmx4g + # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html -#pluginSinceBuild = 203 -pluginSinceBuild=231 -pluginUntilBuild=233.* -# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension -# IntelliJ IDEA Community +pluginSinceBuild=232 +pluginUntilBuild=232.* + platformType = IC -# CLion -#platformType = CL -#platformPlugins = org.rust.lang:0.4.171.4656-213 -#platformPlugins = org.rust.lang:0.4.187.5175-223 -# IntelliJ IDEA Ultimate -#platformType=IU -# https://mvnrepository.com/artifact/com.jetbrains.intellij.idea/ideaIU platformVersion=2023.2.5 -platformPlugins=com.intellij.java -# PhpStorm -#platformType = PS -#platformPlugins = com.jetbrains.php -# Rider -#platformType = RD -#platformPlugins = JavaScript -#platformType = PY -#platformPlugins = Pythonid -# Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion=8.4 # Opt-out flag for bundling Kotlin standard library -> https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library # suppress inspection "UnusedProperty" kotlin.stdlib.default.dependency=false -# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html -org.gradle.configuration-cache = false - # Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html org.gradle.caching = true -# https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#incremental-compilation -kotlin.incremental.useClasspathSnapshot=false - # Enable Gradle Kotlin DSL Lazy Property Assignment -> https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:assignment systemProp.org.gradle.unsafe.kotlin.assignment = true diff --git a/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy b/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy index 62a84502..005235de 100644 --- a/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy +++ b/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy @@ -99,7 +99,7 @@ class AnalogueFileAction extends FileContextAction { """.stripIndent(), null ), new ChatMessage( - Role.user, """ + Role.owner, """ Create a new file based on the following directive: $directive The file should be based on `${baseFile.path}` which contains the following code: diff --git a/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy b/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy index 1def153f..b0eb385b 100644 --- a/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy +++ b/src/main/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy @@ -98,7 +98,7 @@ class CreateFileAction extends FileContextAction { ), //language=TEXT new ChatMessage( - Role.user, """ + Role.owner, """ Create a new file based on the following directive: $directive The file location should be based on the selected path `${basePath}` diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt index 3499c7bd..df37403b 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt @@ -47,6 +47,7 @@ class AppServer( val context = WebAppContext() JettyWebSocketServletContainerInitializer.configure(context, null) context.baseResource = server.baseResource + context.classLoader = AppServer::class.java.classLoader context.contextPath = path context.welcomeFiles = arrayOf("index.html") server.configure(context, baseUrl = "$domainName/$path") diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/InternalCoderAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/InternalCoderAction.kt index 0c5201a4..6ff079fe 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/InternalCoderAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/InternalCoderAction.kt @@ -2,64 +2,65 @@ import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.ComputerLanguage +import com.github.simiacryptus.aicoder.util.IdeaKotlinInterpreter import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys -import com.simiacryptus.jopenai.OpenAIClient import com.simiacryptus.skyenet.apps.coding.CodingApp import com.simiacryptus.skyenet.core.platform.* -import com.simiacryptus.skyenet.kotlin.KotlinInterpreter -import com.simiacryptus.skyenet.webui.chat.CodeChatServer import org.slf4j.LoggerFactory -import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain import java.awt.Desktop -import java.io.File import java.util.* class InternalCoderAction : BaseAction() { - override fun handle(e: AnActionEvent) { - val server = AppServer.getServer(e.project) - val uuid = UUID.randomUUID().toString() - val symbols: MutableMap = mapOf( - "event" to e, - ).toMutableMap() - e.getData(CommonDataKeys.EDITOR)?.apply { symbols["editor"] = this } - e.getData(CommonDataKeys.PSI_FILE)?.apply { symbols["file"] = this } - e.getData(CommonDataKeys.PSI_ELEMENT)?.apply { symbols["element"] = this } - e.getData(CommonDataKeys.VIRTUAL_FILE)?.apply { symbols["virtualFile"] = this } - e.getData(CommonDataKeys.PROJECT)?.apply { symbols["project"] = this } - e.getData(CommonDataKeys.SYMBOLS)?.apply { symbols["symbols"] = this } - e.getData(CommonDataKeys.CARET)?.apply { symbols["psiElement"] = this } - e.getData(CommonDataKeys.CARET)?.apply { symbols["psiElement"] = this } - // TODO: Set this up at startup and lock ApplicationServices - ApplicationServices.clientManager = object : ClientManager() { - override fun createClient(session: Session, user: User?, dataStorage: DataStorage) = - this@InternalCoderAction.api + override fun handle(e: AnActionEvent) { + val server = AppServer.getServer(e.project) + val uuid = UUID.randomUUID().toString() + val symbols: MutableMap = mapOf( + "event" to e, + ).toMutableMap() - override fun createClient(session: Session, user: User?, logfile: File, key: String?) = - this@InternalCoderAction.api - } - server.addApp("/$uuid", CodingApp( - "IntelliJ Internal Coding Agent", - KotlinInterpreter::class, - symbols)) - Thread { - Thread.sleep(500) - try { - Desktop.getDesktop().browse(server.server.uri.resolve("/$uuid/index.html")) - } catch (e: Throwable) { - log.warn("Error opening browser", e) - } - }.start() - } - override fun isEnabled(event: AnActionEvent) = when { - !AppSettingsState.instance.devActions -> false - else -> true + // TODO: Set this up at startup and lock ApplicationServices + ApplicationServices.clientManager = object : ClientManager() { + override fun createClient(session: Session, user: User?, dataStorage: StorageInterface?) = + this@InternalCoderAction.api } + IdeaKotlinInterpreter.project = e.getData(CommonDataKeys.PROJECT) ?: throw IllegalStateException("No project") - companion object { - private val log = LoggerFactory.getLogger(InternalCoderAction::class.java) - } + + e.getData(CommonDataKeys.EDITOR)?.apply { symbols["editor"] = this } + e.getData(CommonDataKeys.PSI_FILE)?.apply { symbols["file"] = this } + e.getData(CommonDataKeys.PSI_ELEMENT)?.apply { symbols["element"] = this } + e.getData(CommonDataKeys.VIRTUAL_FILE)?.apply { symbols["virtualFile"] = this } + IdeaKotlinInterpreter.project?.apply { symbols["project"] = this } + e.getData(CommonDataKeys.SYMBOLS)?.apply { symbols["symbols"] = this } + e.getData(CommonDataKeys.CARET)?.apply { symbols["psiElement"] = this } + e.getData(CommonDataKeys.CARET)?.apply { symbols["psiElement"] = this } + server.addApp( + "/$uuid", CodingApp( + "IntelliJ Internal Coding Agent", + IdeaKotlinInterpreter::class, + symbols + ) + ) + Thread { + Thread.sleep(500) + try { + Desktop.getDesktop().browse(server.server.uri.resolve("/$uuid/index.html")) + } catch (e: Throwable) { + log.warn("Error opening browser", e) + } + }.start() + } + + override fun isEnabled(event: AnActionEvent) = when { + !AppSettingsState.instance.devActions -> false + else -> true + } + + companion object { + private val log = LoggerFactory.getLogger(InternalCoderAction::class.java) + + } } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaKotlinInterpreter.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaKotlinInterpreter.kt new file mode 100644 index 00000000..9716f408 --- /dev/null +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaKotlinInterpreter.kt @@ -0,0 +1,44 @@ +package com.github.simiacryptus.aicoder.util + +import com.intellij.lang.Language +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiFileFactory +import com.simiacryptus.skyenet.kotlin.KotlinInterpreter +import org.jetbrains.kotlin.jsr223.KotlinJsr223StandardScriptEngineFactory4Idea +import org.jetbrains.kotlin.resolve.AnalyzingUtils +import org.slf4j.LoggerFactory +import java.util.Map + +class IdeaKotlinInterpreter(defs: Map) : KotlinInterpreter(defs) { + companion object { + private val log = LoggerFactory.getLogger(IdeaKotlinInterpreter::class.java) + + var project: Project? = null + } + override val scriptEngine: javax.script.ScriptEngine + get() = KotlinJsr223StandardScriptEngineFactory4Idea().scriptEngine + override fun validate(code: String) = try { + val messageCollector = MessageCollectorImpl(code) + val psiFileFactory = PsiFileFactory.getInstance(project!!) + runReadAction { + AnalyzingUtils.checkForSyntacticErrors( + psiFileFactory.createFileFromText( + "Dummy.kt", + Language.findLanguageByID("kotlin")!!, + code + ) + ) + } + if (messageCollector.errors.isEmpty()) { + null + } else RuntimeException( + """ + |${messageCollector.errors.joinToString("\n") { "Error: $it" }} + |${messageCollector.warnings.joinToString("\n") { "Warning: $it" }} + """.trimMargin() + ) + } catch (e: Throwable) { + e + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 6f2e0d3f..d05ee22c 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -4,6 +4,9 @@ SimiaCryptus Software com.intellij.modules.platform + com.intellij.modules.lang + com.intellij.java + org.jetbrains.kotlin diff --git a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy index 62a84502..005235de 100644 --- a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy +++ b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/AnalogueFileAction.groovy @@ -99,7 +99,7 @@ class AnalogueFileAction extends FileContextAction { """.stripIndent(), null ), new ChatMessage( - Role.user, """ + Role.owner, """ Create a new file based on the following directive: $directive The file should be based on `${baseFile.path}` which contains the following code: diff --git a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy index 1def153f..b0eb385b 100644 --- a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy +++ b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/generic/CreateFileAction.groovy @@ -98,7 +98,7 @@ class CreateFileAction extends FileContextAction { ), //language=TEXT new ChatMessage( - Role.user, """ + Role.owner, """ Create a new file based on the following directive: $directive The file location should be based on the selected path `${basePath}`