From e9d720ebf181d614f3a7454f20a4258a920f3fd9 Mon Sep 17 00:00:00 2001 From: Andrew Charneski Date: Thu, 26 Oct 2023 09:25:29 -0400 Subject: [PATCH] 1.2.17 --- build.gradle.kts | 4 +- settings.gradle.kts | 4 +- .../code/InsertImplementationAction.groovy | 28 ++-- .../aicoder/actions/code/PasteAction.groovy | 5 +- .../aicoder/actions/SelectionAction.kt | 2 + .../aicoder/actions/dev/AppServer.kt | 116 ++++++++++++++++ .../aicoder/actions/dev/CodeChatAction.kt | 126 +----------------- .../aicoder/actions/dev/CodeChatServer.kt | 87 ++++++++++++ .../actions/dev/LaunchSkyenetAction.kt | 88 +----------- .../dev/SkyenetProjectCodingSessionServer.kt | 64 +++++++++ .../aicoder/config/ActionSettingsRegistry.kt | 2 +- .../aicoder/config/AppSettingsComponent.kt | 8 ++ .../aicoder/config/AppSettingsState.kt | 2 + .../code/InsertImplementationAction.groovy | 28 ++-- .../aicoder/actions/code/PasteAction.groovy | 5 +- 15 files changed, 336 insertions(+), 233 deletions(-) create mode 100644 src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt create mode 100644 src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatServer.kt create mode 100644 src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/SkyenetProjectCodingSessionServer.kt diff --git a/build.gradle.kts b/build.gradle.kts index 6126f909..ac9a3e3a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,10 +25,10 @@ repositories { val kotlin_version = "1.7.22" val jetty_version = "11.0.15" val slf4j_version = "2.0.5" -val skyenet_version = "1.0.17" +val skyenet_version = "1.0.18" dependencies { - implementation(group = "com.simiacryptus", name = "joe-penai", version = "1.0.19") + implementation(group = "com.simiacryptus", name = "joe-penai", version = "1.0.20") implementation(group = "com.simiacryptus.skyenet", name = "util", version = skyenet_version) implementation(group = "com.simiacryptus.skyenet", name = "core", version = skyenet_version) diff --git a/settings.gradle.kts b/settings.gradle.kts index 2e0bd7c1..d95a93bd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,8 +4,8 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version ("0.4.0") } -//includeBuild("../joe-penai/") -//includeBuild("../SkyeNet/") +includeBuild("../joe-penai/") +includeBuild("../SkyeNet/") //includeBuild("../AwsAgent/") diff --git a/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy b/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy index d329fb00..3a4baf0e 100644 --- a/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy +++ b/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy @@ -3,8 +3,10 @@ package com.github.simiacryptus.aicoder.actions.code import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState import com.github.simiacryptus.aicoder.util.ComputerLanguage +import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.psi.PsiClassContext import com.github.simiacryptus.aicoder.util.psi.PsiUtil +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.simiacryptus.openai.proxy.ChatProxy import kotlin.Pair @@ -85,18 +87,20 @@ class InsertImplementationAction extends SelectionAction { .filter { x -> !x.isEmpty() } .reduce { a, b -> "$a $b" }.get() if(null != state.psiFile) { - def psiClassContext = PsiClassContext.getContext( - state.psiFile, - psiClassContextActionParams.selectionStart, - psiClassContextActionParams.selectionEnd, - computerLanguage - ).toString() - def code = proxy.implementCode( - specification, - psiClassContext, - computerLanguage.name(), - humanLanguage, - ).code + def code = UITools.run(state.project, "Insert Implementation", true, true, { + def psiClassContext = PsiClassContext.getContext( + state.psiFile, + psiClassContextActionParams.selectionStart, + psiClassContextActionParams.selectionEnd, + computerLanguage + ).toString() + proxy.implementCode( + specification, + psiClassContext, + computerLanguage.name(), + humanLanguage, + ).code + }) if(null != code) return selectedText + "\n${state.indent}" + code } else { def code = proxy.implementCode( diff --git a/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy b/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy index 227e698f..1809d328 100644 --- a/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy +++ b/src/main/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable import java.awt.Toolkit import java.awt.datatransfer.DataFlavor +import java.awt.datatransfer.Transferable class PasteAction extends SelectionAction { PasteAction() { @@ -62,6 +63,8 @@ class PasteAction extends SelectionAction { } private Object getClipboard() { - return Toolkit.getDefaultToolkit().systemClipboard.getContents(null)?.getTransferData(DataFlavor.stringFlavor) + def contents = Toolkit.getDefaultToolkit().systemClipboard.getContents(null) + if (contents?.isDataFlavorSupported(DataFlavor.stringFlavor) == true) contents?.getTransferData(DataFlavor.stringFlavor) + else null } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt index 0faea58a..17dbee6e 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt @@ -76,6 +76,7 @@ abstract class SelectionAction( indent = indent, contextRanges = editorState.contextRanges, psiFile = editorState.psiFile, + project = event.project ), config = config ) @@ -171,6 +172,7 @@ abstract class SelectionAction( val indent: CharSequence? = null, val contextRanges: Array = arrayOf(), val psiFile: PsiFile?, + val project: Project? ) open fun isLanguageSupported(computerLanguage: ComputerLanguage?): Boolean { 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 new file mode 100644 index 00000000..2977daa0 --- /dev/null +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/AppServer.kt @@ -0,0 +1,116 @@ +package com.github.simiacryptus.aicoder.actions.dev + +import com.github.simiacryptus.aicoder.config.AppSettingsState +import com.github.simiacryptus.aicoder.util.UITools +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.project.Project +import com.simiacryptus.skyenet.body.WebSocketServer +import org.eclipse.jetty.server.Server +import org.eclipse.jetty.server.handler.ContextHandlerCollection +import org.eclipse.jetty.webapp.WebAppContext +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer +import org.slf4j.LoggerFactory +import java.net.InetSocketAddress + +class AppServer( + val localName: String, + val port: Int, + project: Project? +) { + + val log by lazy { LoggerFactory.getLogger(javaClass) } + + var domainName: String = "http://$localName:$port" + + private val contexts by lazy { + val contexts = ContextHandlerCollection() + contexts.handlers = handlers.toTypedArray() + contexts + } + + @Synchronized + fun addApp(path: String, socketServer: WebSocketServer) { + try { + synchronized(serverLock) { + if (server.isRunning) server.stop() // Stop the server + handlers += newWebAppContext(socketServer, path) + contexts.handlers = handlers.toTypedArray() + server.handler = contexts + server.start() // Start the server again to reflect the new context + } + } catch (e: Exception) { + log.error("Error while restarting the server with new context", e) + } + } + + fun newWebAppContext(server: WebSocketServer, path: String): WebAppContext { + val context = WebAppContext() + JettyWebSocketServletContainerInitializer.configure(context, null) + context.baseResource = server.baseResource + context.contextPath = path + context.welcomeFiles = arrayOf("index.html") + val webAppContext = context + server.configure(webAppContext, baseUrl = "$domainName/$path") + return webAppContext + } + + private val handlers = arrayOf().toMutableList() + + val server by lazy { + val server = Server(InetSocketAddress(localName, port)) + server.handler = contexts + server + } + + private val serverLock = Object() + private val progressThread = Thread { + try { + UITools.run( + project, "Running CodeChat Server on $port", false + ) { + while (isRunning(it)) { + Thread.sleep(1000) + } + synchronized(serverLock) { + if (it.isCanceled) { + log.info("Server cancelled") + server.stop() + } else { + log.info("Server stopped") + } + } + } + } finally { + log.info("Stopping Server") + server.stop() + } + } + + fun isRunning(it: ProgressIndicator) = synchronized(serverLock) { !it.isCanceled && server.isRunning } + fun start() { + server.start() + progressThread.start() + } + + companion object { + @Transient + private var server: AppServer? = null + fun getServer(project: Project?): AppServer { + if (null == server || !server!!.server.isRunning) { + server = AppServer( + AppSettingsState.instance.listeningEndpoint, + AppSettingsState.instance.listeningPort, + project + ) + server!!.start() + } + return server!! + } + + fun stop() { + server?.server?.stop() + server = null + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatAction.kt index 09581fe1..850e907e 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatAction.kt @@ -8,140 +8,24 @@ import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys -import com.simiacryptus.openai.OpenAIClient.ChatMessage -import com.simiacryptus.openai.OpenAIClient.ChatRequest -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.body.* -import com.simiacryptus.skyenet.heart.WeakGroovyInterpreter -import org.eclipse.jetty.util.resource.Resource import java.awt.Desktop -import java.util.function.Supplier +import java.util.* class CodeChatAction : BaseAction() { - inner class CodeChatServer( - val e: AnActionEvent, - port: Int, - val language: String, - val codeSelection: String, - baseURL: String = "http://localhost:$port", - ) : SkyenetCodingSessionServer( - applicationName = "Code Chat", - model = AppSettingsState.instance.defaultChatModel(), - apiKey = AppSettingsState.instance.apiKey, - ) { - - val rootOperationID = (0..5).map { ('a'..'z').random() }.joinToString("") - var rootMessageTrail: String = "" - - override fun newSession(sessionId: String): SkyenetCodingSession { - val newSession = CodeChatSession(sessionId) -rootMessageTrail = -"""$rootOperationID,

Code:

${htmlEscape(codeSelection)}
""" - newSession.send(rootMessageTrail) - return newSession - } - - private fun htmlEscape(html: String): String { - return html.replace("&", "&").replace("<", "<") - .replace(">", ">").replace("\"", """) - .replace("'", "'") - } - - open inner class CodeChatSession(sessionId: String) : SkyenetCodingSession(sessionId, this@CodeChatServer) { - override fun run(userMessage: String) { - var messageTrail = ChatSession.divInitializer() - send("""$messageTrail
$userMessage
$spinner
""") - messages += ChatMessage(ChatMessage.Role.user, userMessage) - val response = api.chat(chatRequest, model).choices.first()?.message?.content.orEmpty() - messages += ChatMessage(ChatMessage.Role.assistant, response) - messageTrail += ChatSessionFlexmark.renderMarkdown(response) - send(messageTrail) - } - - val messages = listOf( - ChatMessage( - ChatMessage.Role.system, """ - |You are a helpful AI that helps people with coding. - | - |You will be answering questions about the following code: - | - |```$language - |$codeSelection - |``` - | - |Responses may use markdown formatting. - """.trimMargin() - ) - ).toMutableList() - val chatRequest: ChatRequest - get() { - val chatRequest = ChatRequest() - val model = AppSettingsState.instance.defaultChatModel() - chatRequest.model = model.modelName - chatRequest.max_tokens = model.maxTokens - chatRequest.temperature = AppSettingsState.instance.temperature - chatRequest.messages = messages.toTypedArray() - return chatRequest - } - } - - override val baseResource: Resource - get() = ClasspathResource(javaClass.classLoader.getResource(resourceBase)) - - override fun hands() = java.util.HashMap() as java.util.Map - - override fun toString(e: Throwable): String { - return e.message ?: e.toString() - } - - override fun heart(hands: java.util.Map): Heart = object : WeakGroovyInterpreter(hands) { - override fun wrapExecution(fn: Supplier): T? { - return UITools.run( - e.project, "Running Script", false - ) { - fn.get() - } - } - } - } - override fun handle(event: AnActionEvent) { val editor = event.getData(CommonDataKeys.EDITOR) ?: return val caretModel = editor.caretModel val primaryCaret = caretModel.primaryCaret val selectedText = primaryCaret.selectedText ?: editor.document.text val language = ComputerLanguage.getComputerLanguage(event)?.name ?: return - - val port = (8000 + (Math.random() * 8000).toInt()) - val skyenet = CodeChatServer(event, port, language, selectedText, baseURL = "http://localhost:$port") - val server = skyenet.start(port) - - Thread { - try { - UITools.run( - event.project, "Running CodeChat Server on $port", false - ) { - while (!it.isCanceled && server.isRunning) { - Thread.sleep(1000) - } - if(it.isCanceled) { - log.info("Server cancelled") - server.stop() - } else { - log.info("Server stopped") - } - } - } finally { - log.info("Stopping Server") - server.stop() - } - }.start() - + val server = AppServer.getServer(event.project) + val uuid = UUID.randomUUID().toString() + server.addApp("/$uuid", CodeChatServer(event.project!!, language, selectedText)) Thread { Thread.sleep(500) try { - Desktop.getDesktop().browse(server.uri.resolve("/index.html")) + Desktop.getDesktop().browse(server.server.uri.resolve("/$uuid/index.html")) } catch (e: Throwable) { log.warn("Error opening browser", e) } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatServer.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatServer.kt new file mode 100644 index 00000000..ef6aaa0b --- /dev/null +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/CodeChatServer.kt @@ -0,0 +1,87 @@ +package com.github.simiacryptus.aicoder.actions.dev + +import com.github.simiacryptus.aicoder.config.AppSettingsState +import com.github.simiacryptus.aicoder.util.UITools +import com.intellij.openapi.project.Project +import com.simiacryptus.openai.OpenAIClient +import com.simiacryptus.skyenet.Heart +import com.simiacryptus.skyenet.body.* +import com.simiacryptus.skyenet.heart.WeakGroovyInterpreter +import org.eclipse.jetty.util.resource.Resource +import java.util.HashMap +import java.util.Map +import java.util.function.Supplier + +class CodeChatServer( + val project: Project, + val language: String, + val codeSelection: String, +) : SkyenetBasicChat( + applicationName = "Code Chat", + model = AppSettingsState.instance.defaultChatModel() +) { + + val rootOperationID = (0..5).map { ('a'..'z').random() }.joinToString("") + var rootMessageTrail: String = "" + + override fun newSession(sessionId: String): CodeChatSession { + val newSession = CodeChatSession(sessionId) +rootMessageTrail = +"""$rootOperationID,

Code:

${htmlEscape(codeSelection)}
""" + newSession.send(rootMessageTrail) + return newSession + } + + private fun htmlEscape(html: String): String { + return html.replace("&", "&").replace("<", "<") + .replace(">", ">").replace("\"", """) + .replace("'", "'") + } + + open inner class CodeChatSession(sessionId: String) : BasicChatSession( + parent = this@CodeChatServer, + model = model, + sessionId = sessionId + ) { + override fun run(userMessage: String) { + var messageTrail = ChatSession.divInitializer() + send("""$messageTrail
$userMessage
$spinner
""") + messages += OpenAIClient.ChatMessage(OpenAIClient.ChatMessage.Role.user, userMessage) + val response = api.chat(chatRequest, model).choices.first()?.message?.content.orEmpty() + messages += OpenAIClient.ChatMessage(OpenAIClient.ChatMessage.Role.assistant, response) + messageTrail += ChatSessionFlexmark.renderMarkdown(response) + send(messageTrail) + } + + override val messages = listOf( + OpenAIClient.ChatMessage( + OpenAIClient.ChatMessage.Role.system, """ + |You are a helpful AI that helps people with coding. + | + |You will be answering questions about the following code: + | + |```$language + |$codeSelection + |``` + | + |Responses may use markdown formatting. + """.trimMargin() + ) + ).toMutableList() + + val chatRequest: OpenAIClient.ChatRequest + get() { + val chatRequest = OpenAIClient.ChatRequest() + val model = AppSettingsState.instance.defaultChatModel() + chatRequest.model = model.modelName + chatRequest.max_tokens = model.maxTokens + chatRequest.temperature = AppSettingsState.instance.temperature + chatRequest.messages = messages.toTypedArray() + return chatRequest + } + } + + override val baseResource: Resource + get() = ClasspathResource(javaClass.classLoader.getResource(resourceBase)) + +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LaunchSkyenetAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LaunchSkyenetAction.kt index 675c467d..b0e547cc 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LaunchSkyenetAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LaunchSkyenetAction.kt @@ -8,17 +8,9 @@ import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.OutputInterceptor -import com.simiacryptus.skyenet.body.ClasspathResource -import com.simiacryptus.skyenet.body.SessionServerUtil.asJava -import com.simiacryptus.skyenet.body.SkyenetCodingSessionServer -import com.simiacryptus.skyenet.heart.WeakGroovyInterpreter import com.simiacryptus.util.describe.Description -import org.eclipse.jetty.util.resource.Resource import java.awt.Desktop -import java.util.Map -import java.util.function.Supplier +import java.util.UUID class LaunchSkyenetAction : BaseAction() { @@ -35,81 +27,15 @@ class LaunchSkyenetAction : BaseAction() { } override fun handle(e: AnActionEvent) { - // Random port from range 8000-9000 - val port = (8000 + (Math.random() * 1000).toInt()) - val skyenet = object : SkyenetCodingSessionServer( - applicationName = "IdeaAgent", - model = AppSettingsState.instance.defaultChatModel(), - apiKey = AppSettingsState.instance.apiKey - ) { - override val baseResource: Resource - get() = ClasspathResource(javaClass.classLoader.getResource(resourceBase)) - - override fun hands() = Map.of( - "ide", - object : TestTools { - override fun getProject(): Project { - return e.project!! - } - - override fun getSelectedFolder(): VirtualFile { - return UITools.getSelectedFolder(e)!! - } - - val toolStream = - OutputInterceptor.createInterceptorStream( - System.out - //PrintStream(NullOutputStream.NULL_OUTPUT_STREAM) - ) - - override fun print(msg: String) { - toolStream.println(msg) - } - } as Object, - ).asJava - - override fun toString(e: Throwable): String { - return e.message ?: e.toString() - } - - override fun heart(hands: Map): Heart = object : WeakGroovyInterpreter(hands) { - override fun wrapExecution(fn: Supplier): T? { - return UITools.run( - e.project, "Running Script", false - ) { - fn.get() - } - } - } - } - val server = skyenet.start(port) - - - Thread { - try { - UITools.run( - e.project, "Running Skyenet Server on $port", false - ) { - while (!it.isCanceled && server.isRunning) { - Thread.sleep(1000) - } - if(it.isCanceled) { - log.info("Server cancelled") - server.stop() - } else { - log.info("Server stopped") - } - } - } finally { - log.info("Stopping Server") - server.stop() - } - }.start() - + val project = e.project!! + val selectedFolder = UITools.getSelectedFolder(e)!! + val server = AppServer.getServer(e.project) + val uuid = UUID.randomUUID().toString() + server.addApp("/$uuid", SkyenetProjectCodingSessionServer(project, selectedFolder)) Thread { Thread.sleep(500) try { - Desktop.getDesktop().browse(server.uri.resolve("/index.html")) + Desktop.getDesktop().browse(server.server.uri.resolve("/$uuid/index.html")) } catch (e: Throwable) { log.warn("Error opening browser", e) } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/SkyenetProjectCodingSessionServer.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/SkyenetProjectCodingSessionServer.kt new file mode 100644 index 00000000..289c01ca --- /dev/null +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/SkyenetProjectCodingSessionServer.kt @@ -0,0 +1,64 @@ +package com.github.simiacryptus.aicoder.actions.dev + +import com.github.simiacryptus.aicoder.config.AppSettingsState +import com.github.simiacryptus.aicoder.util.UITools +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.simiacryptus.skyenet.Heart +import com.simiacryptus.skyenet.OutputInterceptor +import com.simiacryptus.skyenet.body.ClasspathResource +import com.simiacryptus.skyenet.body.SessionServerUtil.asJava +import com.simiacryptus.skyenet.body.SkyenetCodingSessionServer +import com.simiacryptus.skyenet.heart.WeakGroovyInterpreter +import org.eclipse.jetty.util.resource.Resource +import java.util.Map +import java.util.function.Supplier + +class SkyenetProjectCodingSessionServer( + val project: Project, + val selectedFolder: VirtualFile +) : SkyenetCodingSessionServer( + applicationName = "IdeaAgent", + model = AppSettingsState.instance.defaultChatModel(), + apiKey = AppSettingsState.instance.apiKey +) { + override val baseResource: Resource + get() = ClasspathResource(javaClass.classLoader.getResource(resourceBase)) + + override fun hands() = Map.of( + "ide", + object : LaunchSkyenetAction.TestTools { + override fun getProject(): Project { + return project + } + + override fun getSelectedFolder(): VirtualFile { + return selectedFolder + } + + val toolStream = + OutputInterceptor.createInterceptorStream( + System.out + //PrintStream(NullOutputStream.NULL_OUTPUT_STREAM) + ) + + override fun print(msg: String) { + toolStream.println(msg) + } + } as Object, + ).asJava + + override fun toString(e: Throwable): String { + return e.message ?: e.toString() + } + + override fun heart(hands: Map): Heart = object : WeakGroovyInterpreter(hands) { + override fun wrapExecution(fn: Supplier): T? { + return UITools.run( + project, "Running Script", false + ) { + fn.get() + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/ActionSettingsRegistry.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/ActionSettingsRegistry.kt index 0867ad93..aeb84ae6 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/ActionSettingsRegistry.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/ActionSettingsRegistry.kt @@ -11,7 +11,7 @@ import java.util.stream.Collectors class ActionSettingsRegistry { val actionSettings: MutableMap = HashMap() - val version = 1.9 + val version = 1.91 fun edit(superChildren: Array): Array { val children = superChildren.toList().toMutableList() diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt index 70c777e8..f9303c71 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt @@ -32,6 +32,14 @@ class AppSettingsComponent { @Name("Human Language") val humanLanguage = JBTextField() + @Suppress("unused") + @Name("Listening Port") + val listeningPort = JBTextField() + + @Suppress("unused") + @Name("Listening Endpoint") + val listeningEndpoint = JBTextField() + @Suppress("unused") @Name("Suppress Errors") val suppressErrors = JBCheckBox() diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt index 1e9b512d..c7429e9b 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt @@ -16,6 +16,8 @@ class SimpleEnvelope(var value: String? = null) @Suppress("MemberVisibilityCanBePrivate") @State(name = "org.intellij.sdk.settings.AppSettingsState", storages = [Storage("SdkSettingsPlugin.xml")]) class AppSettingsState : PersistentStateComponent { + val listeningPort: Int = 8081 + val listeningEndpoint: String = "localhost" val modalTasks: Boolean = false var suppressErrors: Boolean = false var apiLog: Boolean = false diff --git a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy index d329fb00..3a4baf0e 100644 --- a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy +++ b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/InsertImplementationAction.groovy @@ -3,8 +3,10 @@ package com.github.simiacryptus.aicoder.actions.code import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState import com.github.simiacryptus.aicoder.util.ComputerLanguage +import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.psi.PsiClassContext import com.github.simiacryptus.aicoder.util.psi.PsiUtil +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.simiacryptus.openai.proxy.ChatProxy import kotlin.Pair @@ -85,18 +87,20 @@ class InsertImplementationAction extends SelectionAction { .filter { x -> !x.isEmpty() } .reduce { a, b -> "$a $b" }.get() if(null != state.psiFile) { - def psiClassContext = PsiClassContext.getContext( - state.psiFile, - psiClassContextActionParams.selectionStart, - psiClassContextActionParams.selectionEnd, - computerLanguage - ).toString() - def code = proxy.implementCode( - specification, - psiClassContext, - computerLanguage.name(), - humanLanguage, - ).code + def code = UITools.run(state.project, "Insert Implementation", true, true, { + def psiClassContext = PsiClassContext.getContext( + state.psiFile, + psiClassContextActionParams.selectionStart, + psiClassContextActionParams.selectionEnd, + computerLanguage + ).toString() + proxy.implementCode( + specification, + psiClassContext, + computerLanguage.name(), + humanLanguage, + ).code + }) if(null != code) return selectedText + "\n${state.indent}" + code } else { def code = proxy.implementCode( diff --git a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy index 227e698f..1809d328 100644 --- a/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy +++ b/src/main/resources/sources/groovy/com/github/simiacryptus/aicoder/actions/code/PasteAction.groovy @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable import java.awt.Toolkit import java.awt.datatransfer.DataFlavor +import java.awt.datatransfer.Transferable class PasteAction extends SelectionAction { PasteAction() { @@ -62,6 +63,8 @@ class PasteAction extends SelectionAction { } private Object getClipboard() { - return Toolkit.getDefaultToolkit().systemClipboard.getContents(null)?.getTransferData(DataFlavor.stringFlavor) + def contents = Toolkit.getDefaultToolkit().systemClipboard.getContents(null) + if (contents?.isDataFlavorSupported(DataFlavor.stringFlavor) == true) contents?.getTransferData(DataFlavor.stringFlavor) + else null } } \ No newline at end of file