From 1196e0235ccd3eef08859eca55730ea5b9647a9e Mon Sep 17 00:00:00 2001 From: Andrew Charneski Date: Fri, 18 Oct 2024 12:43:30 -0400 Subject: [PATCH] 1.8.0 (#194) * 1.8.0 * fix * fix --- build.gradle.kts | 12 +-- gradle.properties | 21 ++--- .../aicoder/actions/BaseAction.kt | 2 - .../aicoder/actions/FileContextAction.kt | 2 +- .../aicoder/actions/OpenWebPageAction.kt | 1 - .../aicoder/actions/SelectionAction.kt | 14 ++-- .../aicoder/actions/code/DescribeAction.kt | 2 +- .../aicoder/actions/code/PasteAction.kt | 76 +++++++++++++---- .../actions/dev/LineFilterChatAction.kt | 6 +- .../aicoder/actions/generic/CodeChatAction.kt | 8 +- .../actions/generic/CommandAutofixAction.kt | 6 +- .../CreateFileFromDescriptionAction.kt | 5 +- .../actions/generic/CreateImageAction.kt | 17 ++-- .../aicoder/actions/generic/DiffChatAction.kt | 16 ++-- .../generic/DocumentDataExtractorAction.kt | 23 +++--- .../generic/GenerateDocumentationAction.kt | 10 +-- .../generic/GenerateRelatedFileAction.kt | 2 +- .../actions/generic/GenericChatAction.kt | 4 +- .../actions/generic/MassPatchAction.kt | 15 ++-- .../actions/generic/MultiCodeChatAction.kt | 37 ++++----- .../actions/generic/MultiDiffChatAction.kt | 18 ++--- .../actions/generic/MultiStepPatchAction.kt | 37 +++++---- .../actions/generic/PlanAheadAction.kt | 10 +-- .../actions/generic/PlanAheadConfigDialog.kt | 81 ++++++++++--------- .../aicoder/actions/generic/PlanChatAction.kt | 10 +-- .../aicoder/actions/generic/PrePlanAction.kt | 14 ++-- .../actions/generic/SaveAsQueryIndexAction.kt | 2 +- .../actions/generic/SessionProxyApp.kt | 2 +- .../actions/generic/ShellCommandAction.kt | 7 +- .../actions/generic/SimpleCommandAction.kt | 16 ++-- .../generic/WebDevelopmentAssistantAction.kt | 31 +++---- .../actions/git/ChatWithCommitAction.kt | 12 +-- .../actions/git/ChatWithCommitDiffAction.kt | 28 ++++--- .../git/ChatWithWorkingCopyDiffAction.kt | 14 ++-- .../actions/git/ReplicateCommitAction.kt | 15 ++-- .../legacy/AppendTextWithChatAction.kt | 2 +- .../aicoder/actions/legacy/CommentsAction.kt | 2 +- .../aicoder/actions/legacy/DocAction.kt | 2 +- .../actions/legacy/ImplementStubAction.kt | 2 +- .../legacy/InsertImplementationAction.kt | 2 +- .../actions/legacy/RenameVariablesAction.kt | 4 +- .../legacy/ReplaceWithSuggestionsAction.kt | 2 +- .../actions/legacy/VoiceToTextAction.kt | 2 +- .../markdown/MarkdownImplementActionGroup.kt | 3 +- .../actions/markdown/MarkdownListAction.kt | 2 +- .../actions/problems/AnalyzeProblemAction.kt | 17 ++-- .../actions/test/TestResultAutofixAction.kt | 54 +++++++------ .../aicoder/config/AppSettingsComponent.kt | 62 +++++++++++--- .../aicoder/config/AppSettingsState.kt | 24 +++++- .../simiacryptus/aicoder/config/MRUItems.kt | 2 +- .../config/StaticAppSettingsConfigurable.kt | 33 ++++++++ .../simiacryptus/aicoder/config/UIAdapter.kt | 2 +- .../simiacryptus/aicoder/config/UsageTable.kt | 2 +- .../aicoder/ui/SettingsWidgetFactory.kt | 15 ++-- .../simiacryptus/aicoder/util/BrowseUtil.kt | 4 +- .../aicoder/util/CodeChatSocketManager.kt | 9 +-- .../aicoder/util/FileSystemUtils.kt | 3 - .../aicoder/util/IdeaChatClient.kt | 69 ++++++++++++---- .../aicoder/util/IdeaOpenAIClient.kt | 5 +- .../aicoder/util/LanguageUtils.kt | 13 +-- .../aicoder/util/PluginStartupActivity.kt | 23 +++++- .../simiacryptus/aicoder/util/UITools.kt | 4 +- src/main/kotlin/icons/MyIcons.kt | 3 +- src/main/resources/META-INF/plugin.xml | 10 +-- .../aicoder/test/actions/ActionTestBase.kt | 2 +- .../test/actions/code/CommentsActionTest.kt | 6 +- .../test/actions/code/CustomEditActionTest.kt | 6 +- .../test/actions/code/DescribeActionTest.kt | 6 +- .../test/actions/code/DocActionTest.kt | 6 +- .../actions/code/ImplementStubActionTest.kt | 6 +- .../code/InsertImplementationActionTest.kt | 6 +- .../actions/code/RenameVariablesActionTest.kt | 6 +- .../actions/generic/AnalogueFileActionTest.kt | 3 +- .../test/actions/generic/AppendActionTest.kt | 6 +- .../actions/generic/CreateFileActionTest.kt | 3 +- .../generic/ReplaceOptionsActionTest.kt | 6 +- .../markdown/MarkdownImplementActionTest.kt | 4 +- .../aicoder/test/util/DiffMatchPatchTest.kt | 6 +- src/test/resources/logback.xml | 2 +- 79 files changed, 614 insertions(+), 413 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7bc6ba5f..0bf4e2b4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("org.jetbrains.intellij.platform") version "2.1.0" id("org.jetbrains.changelog") version "2.2.1" id("org.jetbrains.qodana") version "2024.2.3" - id("org.jetbrains.kotlinx.kover") version "0.9.0-RC" + //id("org.jetbrains.kotlinx.kover") version "0.9.0-RC" id("org.jetbrains.dokka") version "2.0.0-Beta" } @@ -28,7 +28,7 @@ repositories { val jetty_version = "11.0.24" val slf4j_version = "2.0.16" -val skyenet_version = "1.2.11" +val skyenet_version = "1.2.12" val remoterobot_version = "0.11.23" val jackson_version = "2.17.2" @@ -43,7 +43,7 @@ dependencies { implementation("com.googlecode.java-diff-utils:diffutils:1.3.0") implementation(group = "org.apache.httpcomponents.client5", name = "httpclient5", version = "5.2.3") - implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.1.9") + implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.1.10") implementation(group = "com.simiacryptus.skyenet", name = "kotlin", version = skyenet_version) implementation(group = "com.simiacryptus.skyenet", name = "core", version = skyenet_version) implementation(group = "com.simiacryptus.skyenet", name = "webui", version = skyenet_version) @@ -51,7 +51,7 @@ dependencies { implementation(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = jackson_version) implementation(group = "com.fasterxml.jackson.core", name = "jackson-annotations", version = jackson_version) implementation(group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version = jackson_version) - implementation ("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version") implementation(group = "org.eclipse.jetty", name = "jetty-server", version = jetty_version) implementation(group = "org.eclipse.jetty", name = "jetty-servlet", version = jetty_version) @@ -181,7 +181,7 @@ intellijPlatform { } publishing { - // Include VCS plugin + // Include VCS plugin token = providers.environmentVariable("PUBLISH_TOKEN") // The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3 // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more: @@ -208,6 +208,7 @@ changelog { } // Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration +/* kover { reports { total { @@ -217,6 +218,7 @@ kover { } } } +*/ tasks { wrapper { diff --git a/gradle.properties b/gradle.properties index 59936483..4d0795e1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,31 +1,24 @@ pluginName=intellij-aicoder pluginRepositoryUrl=https://github.com/SimiaCryptus/intellij-aicoder -pluginVersion=1.7.2 - +pluginVersion=1.8.0 jvmArgs=-Xmx8g org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g - # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html pluginSinceBuild=233 pluginUntilBuild=242.* - -platformType = IU +platformType=IU platformVersion=2024.2 gradleVersion=8.10.2 - -platformPlugins = -platformBundledPlugins = - +platformPlugins= +platformBundledPlugins= # 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 Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html -org.gradle.configuration-cache = false -org.gradle.caching = true - +org.gradle.configuration-cache=false +org.gradle.caching=true # 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 +systemProp.org.gradle.unsafe.kotlin.assignment=true org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true # Disable deprecated features warnings diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/BaseAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/BaseAction.kt index b08f4870..0efc61ce 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/BaseAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/BaseAction.kt @@ -5,9 +5,7 @@ import com.github.simiacryptus.aicoder.util.IdeaOpenAIClient import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.util.NlsSafe import com.simiacryptus.jopenai.ChatClient -import com.simiacryptus.jopenai.OpenAIClient import org.slf4j.LoggerFactory import javax.swing.Icon diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/FileContextAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/FileContextAction.kt index ba7ac5a6..ddf20002 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/FileContextAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/FileContextAction.kt @@ -50,7 +50,7 @@ abstract class FileContextAction( } val start = System.currentTimeMillis() val fileSystem = LocalFileSystem.getInstance() - while(null == fileSystem.refreshAndFindFileByIoFile(newFiles.firstOrNull() ?: throw IllegalStateException())) { + while (null == fileSystem.refreshAndFindFileByIoFile(newFiles.firstOrNull() ?: throw IllegalStateException())) { if (System.currentTimeMillis() - start > 10000) { throw IllegalStateException("File not found: ${newFiles.firstOrNull()}") } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/OpenWebPageAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/OpenWebPageAction.kt index 45728e2d..65951ac3 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/OpenWebPageAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/OpenWebPageAction.kt @@ -1,6 +1,5 @@ package com.github.simiacryptus.aicoder.actions -import com.github.simiacryptus.aicoder.util.BrowseUtil import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent 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 dbb974ad..514d154c 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/SelectionAction.kt @@ -1,8 +1,8 @@ package com.github.simiacryptus.aicoder.actions import com.github.simiacryptus.aicoder.util.ComputerLanguage -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.LanguageUtils +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.command.WriteCommandAction @@ -55,9 +55,9 @@ abstract class SelectionAction( val editorState = editorState(editor) val (start, end) = retarget(editorState, selectedText, selectionStart, selectionEnd) ?: return val text = editorState.text - selectedText = text.substring(start.coerceIn(0, text.length-1), end.coerceIn(0, text.length-1)) - selectionEnd = end.coerceIn(0, text.length-1) - selectionStart = start.coerceIn(0, text.length-1) + selectedText = text.substring(start.coerceIn(0, (text.length - 1).coerceAtLeast(0)), end.coerceIn(0, (text.length - 1).coerceAtLeast(0))) + selectionEnd = end.coerceIn(0, (text.length - 1).coerceAtLeast(0)) + selectionStart = start.coerceIn(0, (text.length - 1).coerceAtLeast(0)) UITools.redoableTask(e) { val document = e.getData(CommonDataKeys.EDITOR)?.document @@ -74,7 +74,7 @@ abstract class SelectionAction( selectionOffset = selectionStart, selectionLength = selectionEnd - selectionStart, entireDocument = editor.document.text, - language = LanguageUtils.getComputerLanguage(e), + language = LanguageUtils.getComputerLanguage(e), indent = indent, contextRanges = editorState.contextRanges, psiFile = editorState.psiFile, @@ -160,7 +160,7 @@ abstract class SelectionAction( if (start >= end) return false } } - val computerLanguage = LanguageUtils.getComputerLanguage(event) + val computerLanguage = LanguageUtils.getComputerLanguage(event) return isLanguageSupported(computerLanguage) } @@ -177,7 +177,7 @@ abstract class SelectionAction( ) open fun isLanguageSupported(computerLanguage: ComputerLanguage?): Boolean { - return LanguageUtils.isLanguageSupported(computerLanguage) + return LanguageUtils.isLanguageSupported(computerLanguage) } open fun defaultSelection(editorState: EditorState, offset: Int) = editorState.line diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/DescribeAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/DescribeAction.kt index 7b37be04..cf31c9c4 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/DescribeAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/DescribeAction.kt @@ -2,10 +2,10 @@ package com.github.simiacryptus.aicoder.actions.code import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.IndentedText import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy import com.simiacryptus.util.StringUtil diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/PasteAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/PasteAction.kt index f8725b9f..ed745ff6 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/PasteAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/code/PasteAction.kt @@ -2,20 +2,20 @@ package com.github.simiacryptus.aicoder.actions.code import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import org.jsoup.Jsoup -import org.jsoup.nodes.Document import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ChatModel +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy +import org.jsoup.Jsoup +import org.jsoup.nodes.Document import java.awt.Toolkit import java.awt.datatransfer.DataFlavor import kotlin.toString -abstract class PasteActionBase(private val model: (AppSettingsState) -> ChatModels) : SelectionAction(false) { +abstract class PasteActionBase(private val model: (AppSettingsState) -> ChatModel) : SelectionAction(false) { override fun getActionUpdateThread() = ActionUpdateThread.BGT interface VirtualAPI { @@ -81,20 +81,62 @@ abstract class PasteActionBase(private val model: (AppSettingsState) -> ChatMode } } - protected open fun scrubHtml(str: String): String { + protected open fun scrubHtml(str: String, maxLength: Int = 100 * 1024): String { val document: Document = Jsoup.parse(str) - document.select("script, style").remove() // Remove script and style tags - document.select("*").forEach { element -> - val importantAttributes = listOf("href", "src", "alt", "title", "width", "height", "style", "class", "id") - element.attributes().filter { it.key !in importantAttributes }.forEach { element.removeAttr(it.key) } - } // Remove all non-important attributes - document.select("*").forEach { element -> - if (element.text().isNullOrEmpty()) { - element.remove() + // Remove unnecessary elements, attributes, and optimize the document + document.apply { + if (document.body().html().length > maxLength) return@apply + select("script, style, link, meta, iframe, noscript").remove() // Remove unnecessary and potentially harmful tags + outputSettings().prettyPrint(false) // Disable pretty printing for compact output + if (document.body().html().length > maxLength) return@apply + // Remove comments + select("*").forEach { it.childNodes().removeAll { node -> node.nodeName() == "#comment" } } + if (document.body().html().length > maxLength) return@apply + // Remove data-* attributes + select("*[data-*]").forEach { it.attributes().removeAll { attr -> attr.key.startsWith("data-") } } + if (document.body().html().length > maxLength) return@apply + select("*").forEach { element -> + val importantAttributes = setOf("href", "src", "alt", "title", "width", "height", "style", "class", "id", "name") + element.attributes().removeAll { it.key !in importantAttributes } + } + if (document.body().html().length > maxLength) return@apply + // Remove empty elements + select("*").filter { it.text().isBlank() && it.attributes().isEmpty() && !it.hasAttr("img") }.forEach { remove() } + if (document.body().html().length > maxLength) return@apply + // Unwrap single-child elements with no attributes + select("*").forEach { element -> + if (element.childNodes().size == 1 && element.childNodes()[0].nodeName() == "#text" && element.attributes().isEmpty()) { + element.unwrap() + } + } + if (document.body().html().length > maxLength) return@apply + // Convert relative URLs to absolute + select("[href],[src]").forEach { element -> + element.attr("href")?.let { href -> element.attr("href", href.makeAbsolute()) } + element.attr("src")?.let { src -> element.attr("src", src.makeAbsolute()) } } - } // Remove elements with empty text - val text = document.toString() - return text // Return the plain text content + if (document.body().html().length > maxLength) return@apply + // Remove empty attributes + select("*").forEach { element -> + element.attributes().removeAll { it.value.isBlank() } + } + } + + // Truncate if necessary + val result = document.body().html() + return if (result.length > maxLength) { + result.substring(0, maxLength) + } else { + result + } + } + + private fun String.makeAbsolute(): String { + return if (startsWith("http://") || startsWith("https://") || startsWith("//")) { + this + } else { + "https://$this" + } } } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LineFilterChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LineFilterChatAction.kt index cb11ec3f..6810c357 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LineFilterChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/dev/LineFilterChatAction.kt @@ -12,8 +12,8 @@ import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.fileEditor.FileDocumentManager import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.chat.ChatSocketManager @@ -27,7 +27,7 @@ class LineFilterChatAction : BaseAction() { override fun handle(e: AnActionEvent) { val editor = e.getData(CommonDataKeys.EDITOR) ?: return - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val language = ComputerLanguage.getComputerLanguage(e)?.name ?: return val filename = FileDocumentManager.getInstance().getFile(editor.document)?.name ?: return val code = editor.caretModel.primaryCaret.selectedText ?: editor.document.text diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CodeChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CodeChatAction.kt index ee023fa8..d1acd045 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CodeChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CodeChatAction.kt @@ -3,16 +3,16 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.CodeChatSocketManager import com.github.simiacryptus.aicoder.util.LanguageUtils -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.fileEditor.FileDocumentManager +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import org.slf4j.LoggerFactory @@ -23,7 +23,7 @@ class CodeChatAction : BaseAction() { override fun handle(e: AnActionEvent) { val editor = e.getData(CommonDataKeys.EDITOR) ?: return - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val language = LanguageUtils.getComputerLanguage(e)?.name ?: "" val filename = FileDocumentManager.getInstance().getFile(editor.document)?.name ?: return diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CommandAutofixAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CommandAutofixAction.kt index c4777d8b..022bf0d2 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CommandAutofixAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CommandAutofixAction.kt @@ -3,8 +3,8 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys @@ -14,7 +14,7 @@ import com.intellij.openapi.ui.DialogWrapper import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.general.CmdPatchApp import com.simiacryptus.skyenet.apps.general.PatchApp -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import org.slf4j.LoggerFactory @@ -37,7 +37,7 @@ class CommandAutofixAction : BaseAction() { } else { event.project?.basePath?.let { File(it).toPath() } }!! - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val patchApp = CmdPatchApp( root, session, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CreateFileFromDescriptionAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CreateFileFromDescriptionAction.kt index 50cd980e..4989d43f 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CreateFileFromDescriptionAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CreateFileFromDescriptionAction.kt @@ -1,10 +1,9 @@ package com.github.simiacryptus.aicoder.actions.generic -import ai.grazie.utils.dropPrefix import com.github.simiacryptus.aicoder.actions.FileContextAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.config.Name +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project @@ -29,10 +28,12 @@ class CreateFileFromDescriptionAction : FileContextAction String = { "" }, actorMap: Map> = mapOf( ActorTypes.MainActor to ImageActor( @@ -213,6 +215,7 @@ class CreateImageAction : BaseAction() { ).call() } } + private fun write( code: ImageResponse, path: Path diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DiffChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DiffChatAction.kt index e1f311cf..121f9794 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DiffChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DiffChatAction.kt @@ -1,26 +1,26 @@ package com.github.simiacryptus.aicoder.actions.generic -import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.AppServer +import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.CodeChatSocketManager import com.github.simiacryptus.aicoder.util.ComputerLanguage -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse -import com.simiacryptus.diff.addApplyDiffLinks import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.util.TextRange +import com.simiacryptus.diff.addApplyDiffLinks +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.session.SessionTask -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData import org.intellij.lang.annotations.Language import org.slf4j.LoggerFactory @@ -31,7 +31,7 @@ class DiffChatAction : BaseAction() { override fun handle(e: AnActionEvent) { val editor = e.getData(CommonDataKeys.EDITOR) ?: return - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val language = ComputerLanguage.getComputerLanguage(e)?.name ?: "" val document = editor.document val filename = FileDocumentManager.getInstance().getFile(document)?.name ?: return diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorAction.kt index 63f9bf0d..58bdd70e 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorAction.kt @@ -3,20 +3,19 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.parsers.CodeParsingModel -import com.simiacryptus.skyenet.apps.parsers.DocumentParsingModel import com.simiacryptus.skyenet.apps.parsers.DocumentParserApp -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.file.DataStorage -import org.slf4j.LoggerFactory +import com.simiacryptus.skyenet.apps.parsers.DocumentParsingModel import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.file.DataStorage import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer +import org.slf4j.LoggerFactory import java.io.File class DocumentDataExtractorAction : BaseAction() { @@ -26,14 +25,14 @@ class DocumentDataExtractorAction : BaseAction() { override fun getActionUpdateThread() = ActionUpdateThread.BGT override fun isEnabled(event: AnActionEvent): Boolean { - if(!super.isEnabled(event)) return false + if (!super.isEnabled(event)) return false val selectedFile = UITools.getSelectedFile(event) return selectedFile != null && ( - selectedFile.name.endsWith(".pdf", ignoreCase = true) || - selectedFile.name.endsWith(".txt", ignoreCase = true) || - selectedFile.name.endsWith(".md", ignoreCase = true) || - selectedFile.name.endsWith(".html", ignoreCase = true) - ) + selectedFile.name.endsWith(".pdf", ignoreCase = true) || + selectedFile.name.endsWith(".txt", ignoreCase = true) || + selectedFile.name.endsWith(".md", ignoreCase = true) || + selectedFile.name.endsWith(".html", ignoreCase = true) + ) } override fun handle(e: AnActionEvent) { @@ -50,7 +49,7 @@ class DocumentDataExtractorAction : BaseAction() { if (!configDialog.showAndGet()) return settings = configDialog.settings - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val pdfFile = selectedFile.toFile DataStorage.sessionPaths[session] = pdfFile.parentFile diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateDocumentationAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateDocumentationAction.kt index 47ce926f..e5655f03 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateDocumentationAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateDocumentationAction.kt @@ -4,7 +4,6 @@ import com.github.simiacryptus.aicoder.actions.FileContextAction import com.github.simiacryptus.aicoder.actions.test.TestResultAutofixAction import com.github.simiacryptus.aicoder.actions.test.TestResultAutofixAction.Companion.getProjectStructure import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.config.Name import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread @@ -17,10 +16,10 @@ import com.intellij.openapi.ui.Messages import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.ui.CheckBoxList import com.intellij.ui.components.JBScrollPane -import javax.swing.JComboBox import com.intellij.ui.components.JBTextArea import com.intellij.ui.components.JBTextField import com.simiacryptus.jopenai.models.ApiModel +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.ClientUtil.toContentList import org.apache.commons.io.IOUtils import java.awt.BorderLayout @@ -29,13 +28,14 @@ import java.io.File import java.io.FileInputStream import java.nio.file.Files import java.nio.file.Path +import java.util.TreeMap import java.util.concurrent.Executors import java.util.concurrent.Future -import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException +import java.util.concurrent.atomic.AtomicReference import javax.swing.* -import java.util.TreeMap +import javax.swing.JComboBox class GenerateDocumentationAction : FileContextAction() { @@ -111,7 +111,7 @@ class GenerateDocumentationAction : FileContextAction files.filter { path -> settingsUI.filesToProcess.isItemSelected(path) }.sortedBy { it.toString() }.toList() else -> listOf() } - if(settings.filesToProcess.isEmpty()) return null + if (settings.filesToProcess.isEmpty()) return null mruDocumentationInstructions.addInstructionToHistory("${settings.outputFilename} ${settings.transformationMessage}") //.map { path -> return@map root?.resolve(path) }.filterNotNull() return Settings(settings, project) diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateRelatedFileAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateRelatedFileAction.kt index 5b39b2a3..e83df78e 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateRelatedFileAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateRelatedFileAction.kt @@ -2,7 +2,6 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.actions.FileContextAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.config.Name import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread @@ -14,6 +13,7 @@ import com.intellij.openapi.vfs.LocalFileSystem import com.simiacryptus.jopenai.models.ApiModel import com.simiacryptus.jopenai.models.ApiModel.ChatMessage import com.simiacryptus.jopenai.models.ApiModel.Role +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.ClientUtil.toContentList import com.simiacryptus.skyenet.core.util.getModuleRootForFile import org.apache.commons.io.FileUtils diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenericChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenericChatAction.kt index a275635a..9902142f 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenericChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenericChatAction.kt @@ -8,7 +8,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.chat.ChatSocketManager @@ -23,7 +23,7 @@ class GenericChatAction : BaseAction() { val model = AppSettingsState.instance.smartModel.chatModel() override fun handle(e: AnActionEvent) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.agents[session] = ChatSocketManager( session = session, model = model, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MassPatchAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MassPatchAction.kt index 1ac6ffb9..4f60eb7a 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MassPatchAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MassPatchAction.kt @@ -4,10 +4,9 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.actions.generic.MassPatchAction.Settings import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.config.Name -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project @@ -18,21 +17,21 @@ import com.intellij.ui.components.JBTextArea import com.simiacryptus.diff.FileValidationUtils.Companion.isLLMIncludable import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.ChatClient import com.simiacryptus.jopenai.models.ApiModel import com.simiacryptus.jopenai.models.ApiModel.Role -import com.simiacryptus.jopenai.ChatClient +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.ClientUtil.toContentList import com.simiacryptus.skyenet.Discussable import com.simiacryptus.skyenet.TabbedDisplay import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.application.ApplicationSocketManager import com.simiacryptus.skyenet.webui.session.SocketManager -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.session.SocketManagerBase import java.awt.BorderLayout import java.awt.Dimension @@ -121,7 +120,7 @@ class MassPatchAction : BaseAction() { val project = e.project val config = getConfig(project, e) - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", singleInput = true, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiCodeChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiCodeChatAction.kt index 7d049931..c7e8cb8c 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiCodeChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiCodeChatAction.kt @@ -4,9 +4,8 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.actions.generic.MultiStepPatchAction.AutoDevApp.Settings import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys @@ -14,12 +13,12 @@ import com.intellij.openapi.vfs.VirtualFile import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.ChatClient +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.GPT4Tokenizer import com.simiacryptus.skyenet.Retryable import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.core.util.getModuleRootForFile import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown import com.simiacryptus.skyenet.webui.application.AppInfoData @@ -60,7 +59,7 @@ class MultiCodeChatAction : BaseAction() { val files = getFiles(virtualFiles, root!!) codeFiles.addAll(files) - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.chats[session] = PatchApp(root.toFile(), { codeSummary() }, codeFiles) ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", @@ -143,19 +142,21 @@ class MultiCodeChatAction : BaseAction() { |${renderMarkdown(codeSummary())} | | - |
${renderMarkdown( - ui.socketManager?.addApplyFileDiffLinks( - root = root.toPath(), - response = design, - handle = { newCodeMap -> - newCodeMap.forEach { (path, newCode) -> - content.append("$path Updated") - } - }, - ui = ui, - api = api, - )!! - )}
+ |
${ + renderMarkdown( + ui.socketManager?.addApplyFileDiffLinks( + root = root.toPath(), + response = design, + handle = { newCodeMap -> + newCodeMap.forEach { (path, newCode) -> + content.append("$path Updated") + } + }, + ui = ui, + api = api, + )!! + ) + }
""".trimMargin() }, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiDiffChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiDiffChatAction.kt index 0b3e0f49..f26467e3 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiDiffChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiDiffChatAction.kt @@ -4,30 +4,29 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.actions.generic.MultiStepPatchAction.AutoDevApp.Settings import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.vfs.VirtualFile import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.ChatClient import com.simiacryptus.jopenai.models.ApiModel import com.simiacryptus.jopenai.models.ApiModel.Role -import com.simiacryptus.jopenai.ChatClient -import com.simiacryptus.jopenai.util.GPT4Tokenizer +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.ClientUtil.toContentList +import com.simiacryptus.jopenai.util.GPT4Tokenizer import com.simiacryptus.skyenet.Discussable import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.core.util.getModuleRootForFile -import com.simiacryptus.skyenet.webui.application.ApplicationInterface -import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.skyenet.webui.application.ApplicationInterface +import com.simiacryptus.skyenet.webui.application.ApplicationServer import org.slf4j.LoggerFactory import java.io.File import java.nio.file.Path @@ -51,7 +50,7 @@ class MultiDiffChatAction : BaseAction() { } val initialFiles = getFiles(virtualFiles, root) - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.chats[session] = PatchApp(root.toFile(), initialFiles) ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", @@ -155,6 +154,7 @@ class MultiDiffChatAction : BaseAction() { """.trimMargin(), model = AppSettingsState.instance.smartModel.chatModel() ) + val settings = getSettings(session, user) ?: Settings() if (api is ChatClient) api.budget = settings.budget ?: 2.00 diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiStepPatchAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiStepPatchAction.kt index ec682049..dff29145 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiStepPatchAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/MultiStepPatchAction.kt @@ -4,22 +4,21 @@ import ai.grazie.utils.mpp.UUID import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API -import com.simiacryptus.jopenai.models.ApiModel -import com.simiacryptus.jopenai.models.ApiModel.Role import com.simiacryptus.jopenai.ChatClient import com.simiacryptus.jopenai.describe.Description -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ApiModel +import com.simiacryptus.jopenai.models.ApiModel.Role +import com.simiacryptus.jopenai.models.ChatModel +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ValidatedObject import com.simiacryptus.jopenai.util.ClientUtil.toContentList -import com.simiacryptus.util.JsonUtil.toJson import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Discussable import com.simiacryptus.skyenet.Retryable @@ -27,11 +26,14 @@ import com.simiacryptus.skyenet.TabbedDisplay import com.simiacryptus.skyenet.core.actors.* import com.simiacryptus.skyenet.core.platform.* import com.simiacryptus.skyenet.core.platform.file.DataStorage +import com.simiacryptus.skyenet.core.platform.model.StorageInterface +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.core.util.commonRoot -import com.simiacryptus.skyenet.webui.application.ApplicationInterface -import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.skyenet.webui.application.ApplicationInterface +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.util.JsonUtil.toJson import org.slf4j.LoggerFactory import java.io.File import java.nio.file.Path @@ -44,7 +46,7 @@ class MultiStepPatchAction : BaseAction() { val path = "/autodev" override fun handle(e: AnActionEvent) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val storage = ApplicationServices.dataStorageFactory(AppSettingsState.instance.pluginHome) as DataStorage? val selectedFile = UITools.getSelectedFolder(e) if (null != storage && null != selectedFile) { @@ -108,7 +110,7 @@ class MultiStepPatchAction : BaseAction() { data class Settings( val budget: Double? = 2.00, val tools: List = emptyList(), - val model: ChatModels? = AppSettingsState.instance.smartModel.chatModel(), + val model: ChatModel? = AppSettingsState.instance.smartModel.chatModel(), ) override val settingsClass: Class<*> get() = Settings::class.java @@ -123,8 +125,8 @@ class MultiStepPatchAction : BaseAction() { session: Session, user: User?, val ui: ApplicationInterface, - val model: ChatModels, - val parsingModel: ChatModels, + val model: ChatModel, + val parsingModel: ChatModel, actorMap: Map> = mapOf( ActorTypes.DesignActor to ParsedActor( resultClass = TaskList::class.java, @@ -254,7 +256,7 @@ class MultiStepPatchAction : BaseAction() { val task = ui.newTask(false).apply { taskTabs[description] = placeholder } pool.submit { task.header("Task: $description") - Retryable(ui,task) { + Retryable(ui, task) { try { val filter = codeFiles.filter { path -> paths?.find { path.toString().contains(it) }?.isNotEmpty() == true @@ -282,7 +284,7 @@ class MultiStepPatchAction : BaseAction() { filter.joinToString("\n\n") { "# ${it}\n```${ it.toString().split('.').last().let { /*escapeHtml4*/it/*.indent(" ")*/ } - }\n${ root.resolve(it).toFile().readText() }\n```" + }\n${root.resolve(it).toFile().readText()}\n```" }, architectureResponse.text, "Provide a change for ${paths?.joinToString(",") { it } ?: ""} ($description)" @@ -294,7 +296,8 @@ class MultiStepPatchAction : BaseAction() { }, ui = ui, api = api - )) + ) + ) } catch (e: Exception) { task.error(ui, e) "" @@ -302,8 +305,8 @@ class MultiStepPatchAction : BaseAction() { } } }.toTypedArray().forEach { it.get() } - } catch (e : Exception) { - log.warn("Error",e) + } catch (e: Exception) { + log.warn("Error", e) } } } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadAction.kt index dc6a22cc..1faa0b08 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadAction.kt @@ -3,15 +3,15 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.general.PlanAheadApp -import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows import com.simiacryptus.skyenet.apps.plan.PlanSettings -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.core.platform.file.DataStorage import com.simiacryptus.skyenet.core.util.getModuleRootForFile import com.simiacryptus.skyenet.webui.application.AppInfoData @@ -40,7 +40,7 @@ class PlanAheadAction : BaseAction() { ) if (dialog.showAndGet()) { // Settings are applied only if the user clicks OK - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val folder = UITools.getSelectedFolder(e) val root = folder?.toFile ?: getModuleRootForFile( UITools.getSelectedFile(e)?.parent?.toFile ?: throw RuntimeException("") diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadConfigDialog.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadConfigDialog.kt index 27121f62..a7766d00 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadConfigDialog.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanAheadConfigDialog.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper import com.intellij.ui.components.JBScrollPane import com.intellij.ui.table.JBTable -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ChatModel import com.simiacryptus.skyenet.apps.plan.PlanSettings import com.simiacryptus.skyenet.apps.plan.TaskSettings import com.simiacryptus.skyenet.apps.plan.TaskType @@ -34,35 +34,38 @@ class PlanAheadConfigDialog( override fun isCellEditable(row: Int, column: Int) = column == 0 || column == 2 } private val taskTable = JBTable(taskTableModel).apply { putClientProperty("terminateEditOnFocusLost", true) } - // Add a function to retrieve visible models - private fun getVisibleModels() = - ChatModels.values().map { it.value }.filter { isVisible(it) }.toList() - .sortedBy { "${it.provider.name} - ${it.modelName}" } - // Custom renderer to display provider name and model name - private fun getModelRenderer() = object : DefaultTableCellRenderer() { - override fun getTableCellRendererComponent( - table: JTable, - value: Any, - isSelected: Boolean, - hasFocus: Boolean, - row: Int, - column: Int - ): Component { - val label = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column) as JLabel - if (value is String) { - val model = getVisibleModels().find { it.modelName == value } - label.text = "${model?.provider?.name} - $value" - } - return label + + // Add a function to retrieve visible models + private fun getVisibleModels() = + ChatModel.values().map { it.value }.filter { isVisible(it) }.toList() + .sortedBy { "${it.provider.name} - ${it.modelName}" } + + // Custom renderer to display provider name and model name + private fun getModelRenderer() = object : DefaultTableCellRenderer() { + override fun getTableCellRendererComponent( + table: JTable, + value: Any, + isSelected: Boolean, + hasFocus: Boolean, + row: Int, + column: Int + ): Component { + val label = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column) as JLabel + if (value is String) { + val model = getVisibleModels().find { it.modelName == value } + label.text = "${model?.provider?.name} - $value" } + return label } - companion object { - fun isVisible(it: ChatModels): Boolean { - val hasApiKey = - AppSettingsState.instance.apiKey?.filter { it.value.isNotBlank() }?.keys?.contains(it.provider.name) - return false != hasApiKey - } + } + + companion object { + fun isVisible(it: ChatModel): Boolean { + val hasApiKey = + AppSettingsState.instance.apiKey?.filter { it.value.isNotBlank() }?.keys?.contains(it.provider.name) + return false != hasApiKey } + } private val checkboxStates = AppSettingsState.instance.executables.map { true }.toMutableList() private val tableModel = object : DefaultTableModel(arrayOf("Enabled", "Command"), 0) { @@ -103,19 +106,19 @@ class PlanAheadConfigDialog( private val editCommandButton = JButton("Edit Command") - init { - taskTable.columnModel.getColumn(2).apply { - preferredWidth = 200 - maxWidth = 250 - val modelComboBox = JComboBox(getVisibleModels().map { it.modelName }.toTypedArray()) - cellEditor = DefaultCellEditor(modelComboBox) - cellRenderer = getModelRenderer() - } + init { + taskTable.columnModel.getColumn(2).apply { + preferredWidth = 200 + maxWidth = 250 + val modelComboBox = JComboBox(getVisibleModels().map { it.modelName }.toTypedArray()) + cellEditor = DefaultCellEditor(modelComboBox) + cellRenderer = getModelRenderer() + } init() title = "Configure Plan Ahead Action" // Add model combobox and change listener to update the settings based on slider value - + temperatureSlider.addChangeListener { settings.temperature = temperatureSlider.value / 100.0 } @@ -175,8 +178,8 @@ class PlanAheadConfigDialog( } editCommandButton.isEnabled = false // Initialize task table - val values = TaskType.values() - values.forEach { taskType -> + val values = TaskType.values() + values.forEach { taskType -> val taskSettings = settings.getTaskSettings(taskType) taskTableModel.addRow( arrayOf( @@ -227,7 +230,7 @@ class PlanAheadConfigDialog( for (i in 0 until taskTableModel.rowCount) { val taskType = TaskType.valueOf(taskTableModel.getValueAt(i, 1) as String) val modelName = taskTableModel.getValueAt(i, 2) as String - val selectedModel = ChatModels.values().toList().find { it.first == modelName }?.second + val selectedModel = ChatModel.values().toList().find { it.first == modelName }?.second settings.setTaskSettings(taskType, TaskSettings(taskTableModel.getValueAt(i, 0) as Boolean).apply { this.model = selectedModel }) diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanChatAction.kt index b5d7a642..73240b28 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PlanChatAction.kt @@ -3,15 +3,15 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.general.PlanChatApp -import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows import com.simiacryptus.skyenet.apps.plan.PlanSettings -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.core.platform.file.DataStorage import com.simiacryptus.skyenet.core.util.getModuleRootForFile import com.simiacryptus.skyenet.webui.application.AppInfoData @@ -38,7 +38,7 @@ class PlanChatAction : BaseAction() { ) if (dialog.showAndGet()) { // Settings are applied only if the user clicks OK - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val folder = UITools.getSelectedFolder(e) val root = folder?.toFile ?: getModuleRootForFile( UITools.getSelectedFile(e)?.parent?.toFile ?: throw RuntimeException("") diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PrePlanAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PrePlanAction.kt index e7b9ac77..c798cca6 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PrePlanAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/PrePlanAction.kt @@ -3,24 +3,24 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.Messages import com.intellij.ui.components.JBTextField -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.general.PlanAheadApp import com.simiacryptus.skyenet.apps.plan.PlanSettings import com.simiacryptus.skyenet.apps.plan.PlanUtil import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.core.platform.file.DataStorage import com.simiacryptus.skyenet.core.util.getModuleRootForFile import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.util.JsonUtil import org.slf4j.LoggerFactory import java.awt.GridBagConstraints import java.awt.GridBagLayout @@ -45,8 +45,8 @@ class PrePlanAction : BaseAction() { try { val taskBreakdownWithPrompt = JsonUtil.fromJson(jsonInput, PlanUtil.TaskBreakdownWithPrompt::class.java) - - val session = StorageInterface.newGlobalID() + + val session = Session.newGlobalID() val folder = UITools.getSelectedFolder(e) val root = folder?.toFile ?: getModuleRootForFile( UITools.getSelectedFile(e)?.parent?.toFile ?: throw RuntimeException("No file selected") @@ -83,7 +83,7 @@ class PrePlanAction : BaseAction() { loadImages = false, showMenubar = false ) - + val server = AppServer.getServer(e.project) openBrowser(server, session.toString()) } catch (ex: Exception) { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SaveAsQueryIndexAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SaveAsQueryIndexAction.kt index a62d29c9..9ac0b5f7 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SaveAsQueryIndexAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SaveAsQueryIndexAction.kt @@ -44,7 +44,7 @@ class SaveAsQueryIndexAction : BaseAction() { try { indicator.isIndeterminate = false indicator.fraction = 0.0 - saveAsBinary>( + saveAsBinary>( IdeaOpenAIClient.instance, outputPath, Executors.newFixedThreadPool(8), diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SessionProxyApp.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SessionProxyApp.kt index 7215f546..75f1eb58 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SessionProxyApp.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SessionProxyApp.kt @@ -1,7 +1,7 @@ package com.github.simiacryptus.aicoder.actions.generic import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.chat.ChatServer diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/ShellCommandAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/ShellCommandAction.kt index 91bb0621..babd3268 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/ShellCommandAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/ShellCommandAction.kt @@ -3,8 +3,8 @@ package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.ui.Messages @@ -13,8 +13,7 @@ import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.apps.coding.CodingAgent import com.simiacryptus.skyenet.core.actors.CodingActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.interpreter.ProcessInterpreter import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface @@ -35,7 +34,7 @@ class ShellCommandAction : BaseAction() { Messages.showErrorDialog(project, "Please select a directory", "Error") return } - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", singleInput = true, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SimpleCommandAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SimpleCommandAction.kt index cb3f1634..f1c89e4d 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SimpleCommandAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/SimpleCommandAction.kt @@ -1,13 +1,11 @@ - package com.github.simiacryptus.aicoder.actions.generic import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.FileSystemUtils.isGitignore import com.github.simiacryptus.aicoder.util.UITools -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys @@ -18,19 +16,19 @@ import com.simiacryptus.diff.FileValidationUtils.Companion.isLLMIncludable import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.describe.Description -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Retryable import com.simiacryptus.skyenet.core.actors.ParsedActor import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.session.SessionTask -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.util.JsonUtil import org.slf4j.LoggerFactory import java.io.File import java.nio.file.Files @@ -54,7 +52,7 @@ class SimpleCommandAction : BaseAction() { return } - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val patchApp = createPatchApp(root.toFile(), session, settings, virtualFiles) SessionProxyServer.chats[session] = patchApp ApplicationServer.appInfoMap[session] = AppInfoData( diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/WebDevelopmentAssistantAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/WebDevelopmentAssistantAction.kt index 69ceb63b..785394c3 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/WebDevelopmentAssistantAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/WebDevelopmentAssistantAction.kt @@ -3,36 +3,36 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.vfs.VirtualFile import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API -import com.simiacryptus.jopenai.models.ApiModel -import com.simiacryptus.jopenai.models.ApiModel.Role import com.simiacryptus.jopenai.ChatClient import com.simiacryptus.jopenai.describe.Description -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ApiModel +import com.simiacryptus.jopenai.models.ApiModel.Role +import com.simiacryptus.jopenai.models.ChatModel import com.simiacryptus.jopenai.models.ImageModels import com.simiacryptus.jopenai.models.OpenAIModels import com.simiacryptus.jopenai.proxy.ValidatedObject import com.simiacryptus.jopenai.util.ClientUtil.toContentList -import com.simiacryptus.util.JsonUtil import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Discussable import com.simiacryptus.skyenet.TabbedDisplay import com.simiacryptus.skyenet.core.actors.* import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User import com.simiacryptus.skyenet.core.platform.file.DataStorage +import com.simiacryptus.skyenet.core.platform.model.StorageInterface +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.session.SessionTask -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.util.JsonUtil import org.slf4j.LoggerFactory import java.io.ByteArrayOutputStream import java.io.File @@ -50,7 +50,7 @@ class WebDevelopmentAssistantAction : BaseAction() { val path = "/webDev" override fun handle(e: AnActionEvent) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() val selectedFile = UITools.getSelectedFolder(e) if (null != selectedFile) { DataStorage.sessionPaths[session] = selectedFile.toFile @@ -87,7 +87,7 @@ class WebDevelopmentAssistantAction : BaseAction() { applicationName: String = "Web Development Agent", val temperature: Double = 0.1, root: VirtualFile?, - override val singleInput : Boolean = false, + override val singleInput: Boolean = false, ) : ApplicationServer( applicationName = applicationName, path = "/webdev", @@ -121,8 +121,8 @@ class WebDevelopmentAssistantAction : BaseAction() { data class Settings( val budget: Double? = 2.00, val tools: List = emptyList(), - val model: ChatModels = OpenAIModels.GPT4o, - val parsingModel: ChatModels = OpenAIModels.GPT4oMini, + val model: ChatModel = OpenAIModels.GPT4o, + val parsingModel: ChatModel = OpenAIModels.GPT4oMini, ) override val settingsClass: Class<*> get() = Settings::class.java @@ -137,8 +137,8 @@ class WebDevelopmentAssistantAction : BaseAction() { session: Session, user: User?, val ui: ApplicationInterface, - val model: ChatModels, - val parsingModel: ChatModels, + val model: ChatModel, + val parsingModel: ChatModel, val tools: List = emptyList(), actorMap: Map> = mapOf( ActorTypes.ArchitectureDiscussionActor to ParsedActor( @@ -620,6 +620,7 @@ class WebDevelopmentAssistantAction : BaseAction() { companion object { private val log = LoggerFactory.getLogger(WebDevelopmentAssistantAction::class.java) val root: File get() = File(AppSettingsState.instance.pluginHome, "code_chat") + data class ProjectSpec( @Description("Files in the project design, including all local html, css, and js files.") val files: List = emptyList() diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitAction.kt index 84fc6e46..9a9804b0 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitAction.kt @@ -3,10 +3,9 @@ package com.github.simiacryptus.aicoder.actions.git import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.generic.SessionProxyServer import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.CodeChatSocketManager import com.github.simiacryptus.aicoder.util.IdeaChatClient -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys @@ -15,8 +14,9 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.vcs.VcsDataKeys import com.intellij.openapi.vfs.VirtualFile import com.simiacryptus.diff.IterativePatchUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import java.io.File @@ -69,7 +69,7 @@ class ChatWithCommitAction : AnAction() { } private fun openChatWithDiff(e: AnActionEvent, diffInfo: String) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.agents[session] = CodeChatSocketManager( session = session, language = "diff", @@ -112,8 +112,8 @@ class ChatWithCommitAction : AnAction() { } override fun update(e: AnActionEvent) { - e.presentation.isEnabledAndVisible = e.getData(PlatformDataKeys.PROJECT) != null && - e.getData(VcsDataKeys.VCS)?.name != "Git" + e.presentation.isEnabledAndVisible = e.getData(PlatformDataKeys.PROJECT) != null && + e.getData(VcsDataKeys.VCS)?.name != "Git" } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitDiffAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitDiffAction.kt index 42211397..b30ecf74 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitDiffAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithCommitDiffAction.kt @@ -3,27 +3,27 @@ package com.github.simiacryptus.aicoder.actions.git import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.generic.SessionProxyServer import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.CodeChatSocketManager import com.github.simiacryptus.aicoder.util.IdeaChatClient -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.vcs.LocalFilePath -import com.intellij.openapi.vcs.VcsDataKeys -import com.intellij.openapi.vcs.changes.TextRevisionNumber -import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.webui.application.AppInfoData -import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.intellij.openapi.vcs.ProjectLevelVcsManager +import com.intellij.openapi.vcs.VcsDataKeys import com.intellij.openapi.vcs.changes.Change import com.intellij.openapi.vcs.changes.ChangeListManager +import com.intellij.openapi.vcs.changes.CurrentContentRevision +import com.intellij.openapi.vcs.changes.TextRevisionNumber import com.intellij.openapi.vcs.history.VcsRevisionNumber import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vcs.changes.CurrentContentRevision +import com.simiacryptus.jopenai.models.chatModel +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.skyenet.webui.application.ApplicationServer import javax.swing.JOptionPane class ChatWithCommitDiffAction : AnAction() { @@ -53,7 +53,7 @@ class ChatWithCommitDiffAction : AnAction() { } private fun openChatWithDiff(e: AnActionEvent, diffInfo: String) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.agents[session] = CodeChatSocketManager( session = session, language = "diff", @@ -97,12 +97,14 @@ class ChatWithCommitDiffAction : AnAction() { } } } + private fun getDiffForChange(project: Project, change: Change, selectedCommit: VcsRevisionNumber): String? { val file = change.virtualFile ?: return null val currentContent = change.afterRevision?.content ?: return null val selectedContent = getContentForRevision(project, file, selectedCommit) ?: return null return createSimpleDiff(currentContent, selectedContent) } + private fun getContentForRevision(project: Project, file: VirtualFile, revisionNumber: VcsRevisionNumber): String? { try { val contentRevision = CurrentContentRevision(LocalFilePath(file.path, file.isDirectory)) @@ -112,6 +114,7 @@ class ChatWithCommitDiffAction : AnAction() { return null } } + private fun createSimpleDiff(currentContent: String, selectedContent: String): String { val currentLines = currentContent.lines() val selectedLines = selectedContent.lines() @@ -133,11 +136,10 @@ class ChatWithCommitDiffAction : AnAction() { } - override fun update(e: AnActionEvent) { val project = e.project - e.presentation.isEnabledAndVisible = project != null && - ProjectLevelVcsManager.getInstance(project).allActiveVcss.isNotEmpty() + e.presentation.isEnabledAndVisible = project != null && + ProjectLevelVcsManager.getInstance(project).allActiveVcss.isNotEmpty() } } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithWorkingCopyDiffAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithWorkingCopyDiffAction.kt index 368b9313..92f0b112 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithWorkingCopyDiffAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ChatWithWorkingCopyDiffAction.kt @@ -3,17 +3,17 @@ package com.github.simiacryptus.aicoder.actions.git import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.generic.SessionProxyServer import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.CodeChatSocketManager import com.github.simiacryptus.aicoder.util.IdeaChatClient -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.vcs.VcsDataKeys import com.intellij.openapi.vcs.changes.ChangeListManager +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface +import com.simiacryptus.skyenet.core.platform.Session import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationServer import javax.swing.JOptionPane @@ -41,7 +41,7 @@ class ChatWithWorkingCopyDiffAction : AnAction() { } private fun openChatWithDiff(e: AnActionEvent, diffInfo: String) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.agents[session] = CodeChatSocketManager( session = session, language = "diff", @@ -74,16 +74,16 @@ class ChatWithWorkingCopyDiffAction : AnAction() { } - private fun getWorkingCopyDiff(changeListManager: ChangeListManager): String { val changes = changeListManager.allChanges return changes.joinToString("\n\n") { change -> val diffForChange = getDiffForChange(change) "File: ${change.virtualFile?.path ?: "Unknown"}\n" + - "Type: ${change.type}\n" + - (diffForChange ?: "No diff available") + "Type: ${change.type}\n" + + (diffForChange ?: "No diff available") }.ifEmpty { "No changes found" } } + private fun getDiffForChange(change: com.intellij.openapi.vcs.changes.Change): String? { val beforeRevision = change.beforeRevision val afterRevision = change.afterRevision diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ReplicateCommitAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ReplicateCommitAction.kt index 255c1556..05f08338 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ReplicateCommitAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/git/ReplicateCommitAction.kt @@ -5,10 +5,9 @@ import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.actions.generic.SessionProxyServer import com.github.simiacryptus.aicoder.actions.generic.toFile import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.FileSystemUtils.isGitignore import com.github.simiacryptus.aicoder.util.UITools -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys @@ -21,19 +20,19 @@ import com.simiacryptus.diff.IterativePatchUtil import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.describe.Description -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Retryable import com.simiacryptus.skyenet.core.actors.ParsedActor import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.session.SessionTask -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.util.JsonUtil import org.slf4j.LoggerFactory import java.io.File import java.nio.file.Files @@ -60,7 +59,7 @@ class ReplicateCommitAction : BaseAction() { val virtualFiles1 = event.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) val files = expand(virtualFiles1) val changes = event.getData(VcsDataKeys.CHANGES) - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() Thread { try { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/AppendTextWithChatAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/AppendTextWithChatAction.kt index 98e12826..5e2d1b36 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/AppendTextWithChatAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/AppendTextWithChatAction.kt @@ -2,11 +2,11 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project import com.simiacryptus.jopenai.models.ApiModel.* +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.util.ClientUtil.toContentList class AppendTextWithChatAction : SelectionAction() { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/CommentsAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/CommentsAction.kt index 424d531f..03541b52 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/CommentsAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/CommentsAction.kt @@ -2,12 +2,12 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.LanguageUtils import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy class CommentsAction : SelectionAction() { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/DocAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/DocAction.kt index d04d12f1..d96af2fb 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/DocAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/DocAction.kt @@ -2,13 +2,13 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.IndentedText import com.github.simiacryptus.aicoder.util.psi.PsiUtil import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy class DocAction : SelectionAction() { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ImplementStubAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ImplementStubAction.kt index 6a1180e7..99c1f8dc 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ImplementStubAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ImplementStubAction.kt @@ -2,12 +2,12 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.psi.PsiUtil import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy import com.simiacryptus.util.StringUtil import java.util.* diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/InsertImplementationAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/InsertImplementationAction.kt index e72d9a96..8ce6f94f 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/InsertImplementationAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/InsertImplementationAction.kt @@ -2,7 +2,6 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.TextBlock import com.github.simiacryptus.aicoder.util.UITools @@ -12,6 +11,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.runReadAction import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy class InsertImplementationAction : SelectionAction() { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/RenameVariablesAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/RenameVariablesAction.kt index e120fa60..6ee6a838 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/RenameVariablesAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/RenameVariablesAction.kt @@ -2,13 +2,13 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage -import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.LanguageUtils +import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy open class RenameVariablesAction : SelectionAction() { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ReplaceWithSuggestionsAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ReplaceWithSuggestionsAction.kt index a8ded4da..f182ec9c 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ReplaceWithSuggestionsAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/ReplaceWithSuggestionsAction.kt @@ -2,11 +2,11 @@ package com.github.simiacryptus.aicoder.actions.legacy import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy import com.simiacryptus.util.StringUtil import kotlin.math.ceil diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/VoiceToTextAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/VoiceToTextAction.kt index 6d27e731..7d036809 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/VoiceToTextAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/legacy/VoiceToTextAction.kt @@ -117,7 +117,7 @@ class VoiceToTextAction : BaseAction() { } override fun isEnabled(event: AnActionEvent): Boolean { - if(!AppSettingsState.instance.enableLegacyActions) return false + if (!AppSettingsState.instance.enableLegacyActions) return false return try { null != targetDataLine.get(50, TimeUnit.MILLISECONDS) } catch (e: Exception) { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownImplementActionGroup.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownImplementActionGroup.kt index 6115f065..b40c22e5 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownImplementActionGroup.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownImplementActionGroup.kt @@ -2,7 +2,6 @@ package com.github.simiacryptus.aicoder.actions.markdown import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.UITools import com.intellij.openapi.actionSystem.ActionGroup @@ -10,6 +9,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy class MarkdownImplementActionGroup : ActionGroup() { @@ -42,6 +42,7 @@ class MarkdownImplementActionGroup : ActionGroup() { open class MarkdownImplementAction(private val language: String) : SelectionAction(true) { override fun getActionUpdateThread() = ActionUpdateThread.BGT + init { templatePresentation.text = language templatePresentation.description = language diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownListAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownListAction.kt index a6f321f3..54f16208 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownListAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/markdown/MarkdownListAction.kt @@ -2,7 +2,6 @@ import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.github.simiacryptus.aicoder.util.UITools import com.github.simiacryptus.aicoder.util.UITools.getIndent @@ -13,6 +12,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.application.ApplicationManager +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.jopenai.proxy.ChatProxy import com.simiacryptus.util.StringUtil diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/problems/AnalyzeProblemAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/problems/AnalyzeProblemAction.kt index 24489a8e..52fdbd52 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/problems/AnalyzeProblemAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/problems/AnalyzeProblemAction.kt @@ -9,10 +9,9 @@ import com.github.simiacryptus.aicoder.actions.test.TestResultAutofixAction.Comp import com.github.simiacryptus.aicoder.actions.test.TestResultAutofixAction.ParsedError import com.github.simiacryptus.aicoder.actions.test.TestResultAutofixAction.ParsedErrors import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.IdeaChatClient import com.intellij.analysis.problemsView.toolWindow.ProblemNode -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys @@ -20,26 +19,26 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.util.TextRange +import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.simiacryptus.diff.addApplyFileDiffLinks import com.simiacryptus.jopenai.API -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Retryable import com.simiacryptus.skyenet.core.actors.ParsedActor import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.application.ApplicationSocketManager import com.simiacryptus.skyenet.webui.session.SessionTask import com.simiacryptus.skyenet.webui.session.SocketManager -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.util.JsonUtil import javax.swing.JOptionPane class AnalyzeProblemAction : AnAction() { @@ -105,7 +104,7 @@ class AnalyzeProblemAction : AnAction() { } private fun openAnalysisSession(project: Project, problemInfo: String, gitRoot: VirtualFile?) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.chats[session] = ProblemAnalysisApp(session, problemInfo, gitRoot) ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/test/TestResultAutofixAction.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/test/TestResultAutofixAction.kt index 02cbc552..555a013e 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/actions/test/TestResultAutofixAction.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/actions/test/TestResultAutofixAction.kt @@ -4,33 +4,32 @@ import com.github.simiacryptus.aicoder.AppServer import com.github.simiacryptus.aicoder.actions.BaseAction import com.github.simiacryptus.aicoder.actions.generic.SessionProxyServer import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.chatModel +import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.github.simiacryptus.aicoder.util.FileSystemUtils.isGitignore import com.github.simiacryptus.aicoder.util.IdeaChatClient import com.intellij.execution.testframework.AbstractTestProxy import com.intellij.execution.testframework.sm.runner.SMTestProxy -import com.github.simiacryptus.aicoder.util.BrowseUtil.browse import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.vfs.VirtualFile import com.simiacryptus.diff.FileValidationUtils.Companion.isGitignore import com.simiacryptus.diff.addApplyFileDiffLinks -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.chatModel import com.simiacryptus.skyenet.AgentPatterns import com.simiacryptus.skyenet.Retryable import com.simiacryptus.skyenet.core.actors.ParsedActor import com.simiacryptus.skyenet.core.actors.SimpleActor import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.skyenet.webui.application.AppInfoData import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.application.ApplicationSocketManager import com.simiacryptus.skyenet.webui.session.SessionTask import com.simiacryptus.skyenet.webui.session.SocketManager -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.skyenet.webui.application.AppInfoData +import com.simiacryptus.util.JsonUtil import org.jetbrains.annotations.NotNull import java.io.File import java.nio.file.Path @@ -46,8 +45,8 @@ class TestResultAutofixAction : BaseAction() { ): MutableSet { val codeFiles = mutableSetOf() // Set to avoid duplicates virtualFiles?.forEach { file -> - if(file.name.startsWith(".")) return@forEach - if(isGitignore(file)) return@forEach + if (file.name.startsWith(".")) return@forEach + if (isGitignore(file)) return@forEach if (file.isDirectory) { codeFiles.addAll(getFiles(file.children)) } else { @@ -56,13 +55,14 @@ class TestResultAutofixAction : BaseAction() { } return codeFiles } + fun getFiles( virtualFiles: Array? ): MutableSet { val codeFiles = mutableSetOf() // Set to avoid duplicates virtualFiles?.forEach { file -> - if(file.fileName.startsWith(".")) return@forEach - if(isGitignore(file)) return@forEach + if (file.fileName.startsWith(".")) return@forEach + if (isGitignore(file)) return@forEach if (file.toFile().isDirectory) { codeFiles.addAll(getFiles(file.toFile().listFiles().map { it.toPath() }.toTypedArray())) } else { @@ -73,7 +73,7 @@ class TestResultAutofixAction : BaseAction() { } fun getProjectStructure(projectPath: VirtualFile?): String { - return getProjectStructure(Path.of((projectPath?: return "Project path is null").path)) + return getProjectStructure(Path.of((projectPath ?: return "Project path is null").path)) } fun getProjectStructure(root: Path): String { @@ -139,22 +139,22 @@ class TestResultAutofixAction : BaseAction() { val sb = StringBuilder() sb.appendLine("Test Name: ${testProxy.name}") sb.appendLine("Duration: ${testProxy.duration} ms") - + if (testProxy.errorMessage != null) { sb.appendLine("Error Message:") sb.appendLine(testProxy.errorMessage) } - + if (testProxy.stacktrace != null) { sb.appendLine("Stacktrace:") sb.appendLine(testProxy.stacktrace) } - + return sb.toString() } private fun openAutofixWithTestResult(e: AnActionEvent, testInfo: String, projectStructure: String) { - val session = StorageInterface.newGlobalID() + val session = Session.newGlobalID() SessionProxyServer.chats[session] = TestResultAutofixApp(session, testInfo, e.project?.basePath, projectStructure) ApplicationServer.appInfoMap[session] = AppInfoData( applicationName = "Code Chat", @@ -221,15 +221,17 @@ class TestResultAutofixAction : BaseAction() { model = AppSettingsState.instance.smartModel.chatModel() ).answer(listOf(testInfo), api = IdeaChatClient.instance) - task.add(AgentPatterns.displayMapInTabs( - mapOf( - "Text" to renderMarkdown(plan.text, ui = ui), - "JSON" to renderMarkdown( - "${tripleTilde}json\n${JsonUtil.toJson(plan.obj)}\n$tripleTilde", - ui = ui - ), + task.add( + AgentPatterns.displayMapInTabs( + mapOf( + "Text" to renderMarkdown(plan.text, ui = ui), + "JSON" to renderMarkdown( + "${tripleTilde}json\n${JsonUtil.toJson(plan.obj)}\n$tripleTilde", + ui = ui + ), + ) ) - )) + ) plan.obj.errors?.forEach { error -> Retryable(ui, task) { @@ -264,7 +266,7 @@ class TestResultAutofixAction : BaseAction() { error: ParsedError, summary: String, filesToFix: List - ) : String { + ): String { val response = SimpleActor( prompt = """ You are a helpful AI that helps people with coding. @@ -303,7 +305,7 @@ $projectStructure data class ParsedErrors( val errors: List? = null - ) + ) data class ParsedError( val message: String? = null, 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 27c2084f..479129c5 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsComponent.kt @@ -17,7 +17,8 @@ import com.intellij.ui.components.JBCheckBox import com.intellij.ui.components.JBList import com.intellij.ui.components.JBTextField import com.intellij.ui.table.JBTable -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.APIProvider +import com.simiacryptus.jopenai.models.ChatModel import com.simiacryptus.jopenai.models.ImageModels import com.simiacryptus.skyenet.core.platform.ApplicationServices import java.awt.BorderLayout @@ -31,6 +32,13 @@ import javax.swing.table.DefaultTableCellRenderer import javax.swing.table.DefaultTableModel class AppSettingsComponent : com.intellij.openapi.Disposable { + @Suppress("unused") + @Name("Store Metadata") + val storeMetadata = JTextArea().apply { + lineWrap = true + wrapStyleWord = true + } + val executablesModel = DefaultListModel().apply { AppSettingsState.instance.executables.forEach { addElement(it) } } @@ -170,6 +178,7 @@ class AppSettingsComponent : com.intellij.openapi.Disposable { @Suppress("unused") @Name("Edit API Requests") val editRequests = JBCheckBox() + @Suppress("unused") @Name("Disable Auto-Open URLs") val disableAutoOpenUrls = JBCheckBox() @@ -220,8 +229,43 @@ class AppSettingsComponent : com.intellij.openapi.Disposable { } } + @Name("User-Supplied Models") + val userSuppliedModels = JBTable(DefaultTableModel(arrayOf("Display Name", "Model ID", "Provider"), 0)).apply { + columnModel.getColumn(0).preferredWidth = 150 + columnModel.getColumn(1).preferredWidth = 200 + columnModel.getColumn(2).preferredWidth = 100 + columnModel.getColumn(2).cellEditor = DefaultCellEditor(JComboBox(APIProvider.values().map { it.name }.toTypedArray())) + } + val addUserModelButton = JButton("Add Model").apply { + addActionListener { + (userSuppliedModels.model as DefaultTableModel).addRow(arrayOf("", "", APIProvider.OpenAI)) + } + } + val removeUserModelButton = JButton("Remove Model").apply { + addActionListener { + if (userSuppliedModels.selectedRow != -1) + (userSuppliedModels.model as DefaultTableModel).removeRow(userSuppliedModels.selectedRow) + } + } + + @Name("Editor Actions") var usage = UsageTable(ApplicationServices.usageManager) + fun getUserSuppliedModels(): List { + return (0 until userSuppliedModels.rowCount).map { row -> + AppSettingsState.UserSuppliedModel( + userSuppliedModels.getValueAt(row, 0) as String, + userSuppliedModels.getValueAt(row, 1) as String, + userSuppliedModels.getValueAt(row, 2) as APIProvider + ) + } + } + + fun setUserSuppliedModels(models: List) { + val model = userSuppliedModels.model as DefaultTableModel + model.rowCount = 0 + models.forEach { model.addRow(arrayOf(it.displayName, it.modelId, it.provider)) } + } init { // Initialize executables list @@ -238,7 +282,7 @@ class AppSettingsComponent : com.intellij.openapi.Disposable { ((executablesPanel.getComponent(0) as? JScrollPane)?.viewport?.view as? JList)?.model as? DefaultListModel return model?.elements()?.toList()?.toSet() ?: emptySet() } - ChatModels.values() + ChatModel.values() .filter { AppSettingsState.instance.apiKey?.filter { it.value.isNotBlank() }?.keys?.contains(it.value.provider.name) ?: false @@ -252,21 +296,21 @@ class AppSettingsComponent : com.intellij.openapi.Disposable { } // Sort the items in the ComboBoxes val smartModelItems = (0 until smartModel.itemCount).map { smartModel.getItemAt(it) } - .filter { modelItem -> - isVisible(ChatModels.values().entries.find { it.value.modelName == modelItem }?.value ?: return@filter false) + .filter { modelItem -> + isVisible(ChatModel.values().entries.find { it.value.modelName == modelItem }?.value ?: return@filter false) } .sortedBy { modelItem -> val model = - ChatModels.values().entries.find { it.value.modelName == modelItem }?.value ?: return@sortedBy "" + ChatModel.values().entries.find { it.value.modelName == modelItem }?.value ?: return@sortedBy "" "${model.provider.name} - ${model.modelName}" }.toList() val fastModelItems = (0 until fastModel.itemCount).map { fastModel.getItemAt(it) } - .filter { modelItem -> - isVisible(ChatModels.values().entries.find { it.value.modelName == modelItem }?.value ?: return@filter false) + .filter { modelItem -> + isVisible(ChatModel.values().entries.find { it.value.modelName == modelItem }?.value ?: return@filter false) } .sortedBy { modelItem -> val model = - ChatModels.values().entries.find { it.value.modelName == modelItem }?.value ?: return@sortedBy "" + ChatModel.values().entries.find { it.value.modelName == modelItem }?.value ?: return@sortedBy "" "${model.provider.name} - ${model.modelName}" }.toList() smartModel.removeAllItems() @@ -295,7 +339,7 @@ class AppSettingsComponent : com.intellij.openapi.Disposable { ) { text = value // Here you can add more customization if needed if (value != null) { - val model = ChatModels.values().entries.find { it.value.modelName == value }?.value + val model = ChatModel.values().entries.find { it.value.modelName == value }?.value text = "${model?.provider?.name} - $value" } } 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 cafd0f4e..29b4bc18 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/AppSettingsState.kt @@ -1,20 +1,19 @@ package com.github.simiacryptus.aicoder.config import com.fasterxml.jackson.annotation.JsonIgnore +import com.github.simiacryptus.aicoder.util.PluginStartupActivity.Companion.addUserSuppliedModels import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.PersistentStateComponent import com.intellij.openapi.components.State import com.intellij.openapi.components.Storage import com.intellij.openapi.util.io.FileUtil import com.intellij.util.xmlb.XmlSerializerUtil -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.APIProvider import com.simiacryptus.jopenai.models.ImageModels import com.simiacryptus.jopenai.models.OpenAIModels import com.simiacryptus.util.JsonUtil -import org.slf4j.Logger import org.slf4j.LoggerFactory import java.io.File -import java.util.* @State(name = "org.intellij.sdk.settings.AppSettingsState", storages = [Storage("SdkSettingsPlugin.xml")]) data class AppSettingsState( @@ -34,6 +33,7 @@ data class AppSettingsState( var devActions: Boolean = false, var editRequests: Boolean = false, var disableAutoOpenUrls: Boolean = false, + var storeMetadata: String? = null, var pluginHome: File = run { var logPath = System.getProperty("idea.plugins.path") if (logPath == null) { @@ -51,6 +51,7 @@ data class AppSettingsState( var executables: MutableSet = mutableSetOf(), var recentArguments: MutableList = mutableListOf(), val recentCommands: MutableMap = mutableMapOf(), + var userSuppliedModels: MutableList = mutableListOf() ) : PersistentStateComponent { private var onSettingsLoadedListeners = mutableListOf<() -> Unit>() @@ -71,6 +72,7 @@ data class AppSettingsState( AppSettingsState() } XmlSerializerUtil.copyBean(fromJson, this) + addUserSuppliedModels(fromJson.userSuppliedModels) recentCommands.clear() recentCommands.putAll(fromJson.recentCommands) notifySettingsLoaded() @@ -103,6 +105,7 @@ data class AppSettingsState( if (apiLog != other.apiLog) return false if (devActions != other.devActions) return false if (editRequests != other.editRequests) return false + if (storeMetadata != other.storeMetadata) return false if (FileUtil.filesEqual(pluginHome, other.pluginHome)) return false if (recentCommands != other.recentCommands) return false if (showWelcomeScreen != other.showWelcomeScreen) return false @@ -110,6 +113,8 @@ data class AppSettingsState( if (mainImageModel != other.mainImageModel) return false if (enableLegacyActions != other.enableLegacyActions) return false if (executables != other.executables) return false + //userSuppliedModels + if (userSuppliedModels.toTypedArray().contentDeepEquals(other.userSuppliedModels.toTypedArray()).not()) return false return true } @@ -130,6 +135,7 @@ data class AppSettingsState( result = 31 * result + apiLog.hashCode() result = 31 * result + devActions.hashCode() result = 31 * result + editRequests.hashCode() + result = 31 * result + (storeMetadata?.hashCode() ?: 0) result = 31 * result + FileUtil.fileHashCode(pluginHome) result = 31 * result + recentCommands.hashCode() result = 31 * result + showWelcomeScreen.hashCode() @@ -137,10 +143,12 @@ data class AppSettingsState( result = 31 * result + mainImageModel.hashCode() result = 31 * result + enableLegacyActions.hashCode() result = 31 * result + executables.hashCode() + result = 31 * result + userSuppliedModels.hashCode() return result } companion object { + val log = LoggerFactory.getLogger(AppSettingsState::class.java) var auxiliaryLog: File? = null const val WELCOME_VERSION: String = "1.5.0" @@ -158,4 +166,14 @@ data class AppSettingsState( fun getDefaultShell() = if (System.getProperty("os.name").lowercase().contains("win")) "powershell" else "bash" } + + data class UserSuppliedModel( + var displayName: String = "", + var modelId: String = "", + var provider: APIProvider = APIProvider.OpenAI + ) + + interface SettingsChangeListener { + fun onSettingsChange(newSettings: AppSettingsState) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/MRUItems.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/MRUItems.kt index 997d929c..b8409ad7 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/MRUItems.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/MRUItems.kt @@ -1,13 +1,13 @@ package com.github.simiacryptus.aicoder.config import com.fasterxml.jackson.annotation.JsonIgnore -import kotlin.math.min import java.io.Serializable import java.time.Instant import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.locks.ReentrantReadWriteLock import kotlin.concurrent.read import kotlin.concurrent.write +import kotlin.math.min class MRUItems : Serializable { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/StaticAppSettingsConfigurable.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/StaticAppSettingsConfigurable.kt index 9aefe33c..83482ca1 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/StaticAppSettingsConfigurable.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/StaticAppSettingsConfigurable.kt @@ -1,20 +1,26 @@ package com.github.simiacryptus.aicoder.config import com.github.simiacryptus.aicoder.util.IdeaChatClient +import com.github.simiacryptus.aicoder.util.PluginStartupActivity.Companion.addUserSuppliedModels import com.simiacryptus.jopenai.models.APIProvider import java.awt.BorderLayout +import java.awt.Dimension import java.awt.FlowLayout +import java.awt.GridBagConstraints +import java.awt.GridBagLayout import java.io.File import java.io.FileOutputStream import javax.swing.BoxLayout import javax.swing.JComponent import javax.swing.JLabel import javax.swing.JPanel +import javax.swing.JScrollPane import javax.swing.table.DefaultTableModel class StaticAppSettingsConfigurable : AppSettingsConfigurable() { override fun apply() { super.apply() + addUserSuppliedModels(settingsInstance.userSuppliedModels) if (settingsInstance.apiLog) { val file = File(AppSettingsState.instance.pluginHome, "openai.log") if (AppSettingsState.auxiliaryLog?.absolutePath?.lowercase() != file.absolutePath.lowercase()) { @@ -97,6 +103,29 @@ class StaticAppSettingsConfigurable : AppSettingsConfigurable() { add(JLabel("Disable Auto-Open URLs:")) add(component.disableAutoOpenUrls) }) + add(JPanel(BorderLayout()).apply { + add(JLabel("Store Metadata (JSON):"), BorderLayout.NORTH) + val scrollPane = JScrollPane(component.storeMetadata) + scrollPane.preferredSize = Dimension(300, 100) + add(scrollPane, BorderLayout.CENTER) + }) + add(JPanel(BorderLayout()).apply { + add(JLabel("User-Supplied Models:"), BorderLayout.NORTH) + add(JScrollPane(component.userSuppliedModels).apply { + preferredSize = Dimension(500, 200) + }, BorderLayout.CENTER) + add(JPanel(GridBagLayout()).apply { + val gbc = GridBagConstraints().apply { + gridx = 0 + gridy = 0 + fill = GridBagConstraints.HORIZONTAL + weightx = 1.0 + } + add(component.addUserModelButton, gbc) + gbc.gridx++ + add(component.removeUserModelButton, gbc) + }, BorderLayout.SOUTH) + }) add(JPanel(FlowLayout(FlowLayout.LEFT)).apply { add(JLabel("Enable API Log:")) add(component.apiLog) @@ -156,6 +185,7 @@ class StaticAppSettingsConfigurable : AppSettingsConfigurable() { component.devActions.isSelected = settings.devActions component.editRequests.isSelected = settings.editRequests component.mainImageModel.selectedItem = settings.mainImageModel + component.storeMetadata.text = settings.storeMetadata ?: "" component.temperature.text = settings.temperature.toString() component.pluginHome.text = settings.pluginHome.absolutePath component.shellCommand.text = settings.shellCommand @@ -168,6 +198,7 @@ class StaticAppSettingsConfigurable : AppSettingsConfigurable() { component.showWelcomeScreen.isSelected = settings.showWelcomeScreen component.enableLegacyActions.isSelected = settings.enableLegacyActions component.setExecutables(settings.executables) + component.setUserSuppliedModels(settings.userSuppliedModels) } catch (e: Exception) { log.warn("Error setting UI", e) } @@ -190,6 +221,7 @@ class StaticAppSettingsConfigurable : AppSettingsConfigurable() { settings.editRequests = component.editRequests.isSelected settings.disableAutoOpenUrls = component.disableAutoOpenUrls.isSelected settings.temperature = component.temperature.text.safeDouble() + settings.storeMetadata = component.storeMetadata.text.takeIf { it.isNotBlank() } settings.mainImageModel = (component.mainImageModel.selectedItem as String) settings.pluginHome = File(component.pluginHome.text) settings.shellCommand = component.shellCommand.text @@ -216,6 +248,7 @@ class StaticAppSettingsConfigurable : AppSettingsConfigurable() { } } settings.showWelcomeScreen = component.showWelcomeScreen.isSelected + settings.userSuppliedModels = component.getUserSuppliedModels().toMutableList() } catch (e: Exception) { log.warn("Error reading UI", e) } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/UIAdapter.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/UIAdapter.kt index b03181b8..1652089d 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/UIAdapter.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/UIAdapter.kt @@ -56,7 +56,7 @@ abstract class UIAdapter( log.error("Error reading settings", e) settingsInstance } - + override fun isModified() = when { component == null -> false getSettings() != settingsInstance -> true diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/config/UsageTable.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/config/UsageTable.kt index 4eb5f2c1..4e2cd908 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/config/UsageTable.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/config/UsageTable.kt @@ -3,7 +3,7 @@ import com.github.simiacryptus.aicoder.util.IdeaChatClient import com.intellij.ui.components.JBScrollPane import com.intellij.ui.table.JBTable -import com.simiacryptus.skyenet.core.platform.UsageInterface +import com.simiacryptus.skyenet.core.platform.model.UsageInterface import org.jdesktop.swingx.JXTable import java.awt.BorderLayout import java.awt.event.ActionEvent diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/ui/SettingsWidgetFactory.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/ui/SettingsWidgetFactory.kt index be51e61c..44b17e58 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/ui/SettingsWidgetFactory.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/ui/SettingsWidgetFactory.kt @@ -11,7 +11,7 @@ import com.intellij.openapi.wm.StatusBarWidgetFactory import com.intellij.ui.CollectionListModel import com.intellij.ui.SimpleListCellRenderer import com.intellij.ui.components.JBList -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ChatModel import icons.MyIcons import kotlinx.coroutines.CoroutineScope import java.awt.BorderLayout @@ -44,8 +44,8 @@ class SettingsWidgetFactory : StatusBarWidgetFactory { } } - fun models() = ChatModels.values().filter { isVisible(it.value) } - .entries.sortedBy { "${it.value.provider.name} - ${it.value.modelName}" }.map { it.value }.toList() + fun models() = ChatModel.values().filter { it.value != null && isVisible(it.value!!) } + .entries.sortedBy { "${it.value!!.provider.name} - ${it.value!!.modelName}" }.map { it.value }.toList() override fun ID(): String { return "AICodingAssistant.SettingsWidget" @@ -78,7 +78,8 @@ class SettingsWidgetFactory : StatusBarWidgetFactory { cursor = Cursor(Cursor.HAND_CURSOR) addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) = browse( - URI("https://plugins.jetbrains.com/plugin/20724-ai-coding-assistant/edit/reviews")) + URI("https://plugins.jetbrains.com/plugin/20724-ai-coding-assistant/edit/reviews") + ) }) }, BorderLayout.EAST) return header @@ -98,14 +99,14 @@ class SettingsWidgetFactory : StatusBarWidgetFactory { ) { text = value // Here you can add more customization if needed if (value != null) { - val model = models().find { it.modelName == value } + val model = models().find { it?.modelName == value } text = "${model?.provider?.name} - $value" // Enhance label formatting } } } override fun getPopup(): JBPopup { - val listModel = CollectionListModel(models().map { it.modelName }) + val listModel = CollectionListModel(models().map { it?.modelName ?: "" }) val list = JBList(listModel) list.cellRenderer = getRenderer() list.visibleRowCount = 20 @@ -131,7 +132,7 @@ class SettingsWidgetFactory : StatusBarWidgetFactory { } companion object { - fun isVisible(it: ChatModels): Boolean { + fun isVisible(it: ChatModel): Boolean { val hasApiKey = AppSettingsState.instance.apiKey?.filter { it.value.isNotBlank() }?.keys?.contains(it.provider.name) return false != hasApiKey diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/BrowseUtil.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/BrowseUtil.kt index 236e7cab..6a5332bd 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/BrowseUtil.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/BrowseUtil.kt @@ -3,10 +3,10 @@ package com.github.simiacryptus.aicoder.util import com.github.simiacryptus.aicoder.config.AppSettingsState import org.slf4j.LoggerFactory import java.awt.Desktop -import java.net.URI -import java.net.DatagramSocket import java.net.DatagramPacket +import java.net.DatagramSocket import java.net.InetAddress +import java.net.URI object BrowseUtil { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/CodeChatSocketManager.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/CodeChatSocketManager.kt index d6c7a93f..b08c5daf 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/CodeChatSocketManager.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/CodeChatSocketManager.kt @@ -1,11 +1,10 @@ package com.github.simiacryptus.aicoder.util import com.simiacryptus.jopenai.ChatClient -import com.simiacryptus.jopenai.OpenAIClient -import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.ChatModel import com.simiacryptus.skyenet.core.platform.Session -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.model.StorageInterface +import com.simiacryptus.skyenet.core.platform.model.User import com.simiacryptus.skyenet.webui.application.ApplicationServer import com.simiacryptus.skyenet.webui.chat.ChatSocketManager @@ -15,7 +14,7 @@ open class CodeChatSocketManager( val filename: String, val codeSelection: String, api: ChatClient, - model: ChatModels, + model: ChatModel, storage: StorageInterface?, ) : ChatSocketManager( session = session, diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/FileSystemUtils.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/FileSystemUtils.kt index f69997d6..83cfd8fb 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/FileSystemUtils.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/FileSystemUtils.kt @@ -1,13 +1,10 @@ package com.github.simiacryptus.aicoder.util import com.intellij.openapi.vfs.VirtualFile -import com.simiacryptus.diff.FileValidationUtils import com.simiacryptus.diff.FileValidationUtils.Companion.isGitignore -import java.io.File import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import java.util.* object FileSystemUtils { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaChatClient.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaChatClient.kt index f9def1cc..ba9f75bd 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaChatClient.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaChatClient.kt @@ -2,22 +2,25 @@ import com.github.simiacryptus.aicoder.config.AppSettingsState import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper import com.intellij.ui.components.JBScrollPane import com.intellij.util.ui.FormBuilder -import com.simiacryptus.jopenai.models.ApiModel.* import com.simiacryptus.jopenai.ChatClient +import com.simiacryptus.jopenai.isSanctioned import com.simiacryptus.jopenai.models.APIProvider +import com.simiacryptus.jopenai.models.ApiModel.* import com.simiacryptus.jopenai.models.OpenAIModel -import com.simiacryptus.jopenai.models.OpenAITextModel -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.TextModel import com.simiacryptus.skyenet.core.platform.ApplicationServices -import com.simiacryptus.skyenet.core.platform.StorageInterface -import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.model.User +import com.simiacryptus.util.JsonUtil import org.apache.hc.core5.http.HttpRequest import org.slf4j.LoggerFactory +import org.slf4j.event.Level import java.io.File import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference @@ -25,11 +28,14 @@ import javax.swing.JPanel import javax.swing.JTextArea -class IdeaChatClient : ChatClient( - key = AppSettingsState.instance.apiKey?.mapKeys { APIProvider.valueOf(it.key) }?.entries?.toTypedArray() +open class IdeaChatClient( + key: Map = AppSettingsState.instance.apiKey?.mapKeys { APIProvider.valueOf(it.key) }?.entries?.toTypedArray() ?.associate { it.key to it.value } ?: mapOf(), - apiBase = AppSettingsState.instance.apiBase?.mapKeys { APIProvider.valueOf(it.key) }?.entries?.toTypedArray() + apiBase: Map = AppSettingsState.instance.apiBase?.mapKeys { APIProvider.valueOf(it.key) }?.entries?.toTypedArray() ?.associate { it.key to it.value } ?: mapOf(), +) : ChatClient( + key = key, + apiBase = apiBase, ) { init { @@ -39,6 +45,26 @@ class IdeaChatClient : ChatClient( } } + private class IdeaChildClient( + val inner: IdeaChatClient, + key: Map, + apiBase: Map + ) : IdeaChatClient( + key = key, + apiBase = apiBase + ) { + override fun log(level: Level, msg: String) { + if (isSanctioned) return + super.log(level, msg) + inner.log(level, msg) + } + } + + override fun getChildClient(): ChatClient = IdeaChildClient(inner = this, key = key, apiBase = apiBase).apply { + session = inner.session + user = inner.user + } + private val isInRequest = AtomicBoolean(false) override fun onUsage(model: OpenAIModel?, tokens: Usage) { @@ -58,9 +84,25 @@ class IdeaChatClient : ChatClient( @Suppress("NAME_SHADOWING") override fun chat( chatRequest: ChatRequest, - model: OpenAITextModel + model: TextModel ): ChatResponse { + val storeMetadata = AppSettingsState.instance.storeMetadata + var chatRequest = chatRequest.copy( + store = storeMetadata?.let { !isSanctioned && it.isNotBlank() }, + metadata = storeMetadata?.let { JsonUtil.fromJson(it, Map::class.java) } + ) + val lastEvent = lastEvent lastEvent ?: return super.chat(chatRequest, model) + chatRequest = chatRequest.copy( + store = chatRequest.store, + metadata = chatRequest.metadata?.let { + it + mapOf( + "project" to lastEvent.project?.name, + "action" to lastEvent.presentation.text, + "language" to lastEvent.getData(CommonDataKeys.PSI_FILE)?.language?.displayName, + ) + } + ) if (isInRequest.getAndSet(true)) { val response = super.chat(chatRequest, model) if (null != response.usage) { @@ -86,7 +128,7 @@ class IdeaChatClient : ChatClient( } return withJsonDialog(chatRequest, { chatRequest -> UITools.run( - lastEvent!!.project, "OpenAI Request", true, suppressProgress = false + lastEvent.project, "OpenAI Request", true, suppressProgress = false ) { val response = super.chat(chatRequest, model) if (null != response.usage) { @@ -106,10 +148,9 @@ class IdeaChatClient : ChatClient( } + companion object { - companion object { - - val instance by lazy { + val instance by lazy { //log.info("Initializing OpenAI Client", Throwable()) val client = IdeaChatClient() if (AppSettingsState.instance.apiLog) { @@ -191,7 +232,7 @@ class IdeaChatClient : ChatClient( } private val log = LoggerFactory.getLogger(IdeaChatClient::class.java) - val currentSession = StorageInterface.newGlobalID() + val currentSession = Session.newGlobalID() val localUser = User(id = "1", email = "user@localhost") } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaOpenAIClient.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaOpenAIClient.kt index d833e70b..ff84ea18 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaOpenAIClient.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/IdeaOpenAIClient.kt @@ -1,9 +1,9 @@ package com.github.simiacryptus.aicoder.util import com.github.simiacryptus.aicoder.config.AppSettingsState -import com.simiacryptus.jopenai.models.ApiModel import com.simiacryptus.jopenai.OpenAIClient import com.simiacryptus.jopenai.models.APIProvider +import com.simiacryptus.jopenai.models.ApiModel import com.simiacryptus.jopenai.models.OpenAIModel import com.simiacryptus.skyenet.core.platform.ApplicationServices import org.apache.hc.core5.http.HttpRequest @@ -31,7 +31,8 @@ class IdeaOpenAIClient : OpenAIClient( // AppSettingsState.instance.tokenCounter += tokens.total_tokens ApplicationServices.usageManager.incrementUsage( IdeaChatClient.currentSession, - IdeaChatClient.localUser, model!!, tokens) + IdeaChatClient.localUser, model!!, tokens + ) } override fun authorize(request: HttpRequest, apiProvider: APIProvider) { diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/LanguageUtils.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/LanguageUtils.kt index 4e2eadfb..0d5490d6 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/LanguageUtils.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/LanguageUtils.kt @@ -3,6 +3,7 @@ package com.github.simiacryptus.aicoder.util import com.github.simiacryptus.aicoder.actions.generic.toFile import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager @@ -15,10 +16,12 @@ object LanguageUtils { } fun getComputerLanguage(e: AnActionEvent): ComputerLanguage? { - val editor = e.getData(CommonDataKeys.EDITOR) ?: return null - val virtualFile: VirtualFile = FileDocumentManager.getInstance().getFile(editor.document) ?: return null - val file = PsiManager.getInstance(e.project!!).findFile(virtualFile)?.virtualFile?.toFile ?: return null - val extension = if (file.extension != null) file.extension.lowercase(Locale.getDefault()) else "" - return ComputerLanguage.findByExtension(extension) + return ApplicationManager.getApplication().runReadAction { + val editor = e.getData(CommonDataKeys.EDITOR) ?: return@runReadAction null + val virtualFile: VirtualFile = FileDocumentManager.getInstance().getFile(editor.document) ?: return@runReadAction null + val file = PsiManager.getInstance(e.project!!).findFile(virtualFile)?.virtualFile?.toFile ?: return@runReadAction null + val extension = if (file.extension != null) file.extension.lowercase(Locale.getDefault()) else "" + return@runReadAction ComputerLanguage.findByExtension(extension) + } } } diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/PluginStartupActivity.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/PluginStartupActivity.kt index e55e6bd6..b9a4a388 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/PluginStartupActivity.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/PluginStartupActivity.kt @@ -7,9 +7,15 @@ import com.intellij.openapi.fileEditor.TextEditorWithPreview import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity import com.intellij.openapi.vfs.VirtualFileManager +import com.simiacryptus.jopenai.models.ChatModel import com.simiacryptus.skyenet.core.OutputInterceptor import com.simiacryptus.skyenet.core.platform.* -import com.simiacryptus.skyenet.core.platform.ApplicationServicesConfig.isLocked +import com.simiacryptus.skyenet.core.platform.hsql.HSQLUsageManager +import com.simiacryptus.skyenet.core.platform.model.ApplicationServicesConfig +import com.simiacryptus.skyenet.core.platform.model.ApplicationServicesConfig.isLocked +import com.simiacryptus.skyenet.core.platform.model.AuthenticationInterface +import com.simiacryptus.skyenet.core.platform.model.AuthorizationInterface +import com.simiacryptus.skyenet.core.platform.model.User import java.io.File import java.util.concurrent.atomic.AtomicBoolean import kotlin.reflect.full.declaredMembers @@ -25,6 +31,8 @@ class PluginStartupActivity : ProjectActivity { try { currentThread.contextClassLoader = PluginStartupActivity::class.java.classLoader init() + // Add user-supplied models to ChatModel + addUserSuppliedModels(AppSettingsState.instance.userSuppliedModels) } finally { currentThread.contextClassLoader = prevClassLoader } @@ -108,5 +116,18 @@ class PluginStartupActivity : ProjectActivity { companion object { val log = org.slf4j.LoggerFactory.getLogger(PluginStartupActivity::class.java) + + fun addUserSuppliedModels(userModels: List) { + userModels.forEach { model -> + ChatModel.values[model.displayName] = ChatModel( + name = model.displayName, + modelName = model.modelId, + maxTotalTokens = 4096, // Default value, adjust as needed + provider = model.provider, + inputTokenPricePerK = 0.0, // Default value, adjust as needed + outputTokenPricePerK = 0.0 // Default value, adjust as needed + ) + } + } } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/simiacryptus/aicoder/util/UITools.kt b/src/main/kotlin/com/github/simiacryptus/aicoder/util/UITools.kt index 70e05dbd..93255d30 100644 --- a/src/main/kotlin/com/github/simiacryptus/aicoder/util/UITools.kt +++ b/src/main/kotlin/com/github/simiacryptus/aicoder/util/UITools.kt @@ -3,8 +3,8 @@ //import com.github.simiacryptus.aicoder.config.ActionSettingsRegistry import com.github.simiacryptus.aicoder.config.AppSettingsState import com.github.simiacryptus.aicoder.config.Name -import com.google.common.util.concurrent.* import com.github.simiacryptus.aicoder.util.BrowseUtil.browse +import com.google.common.util.concurrent.* import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.actionSystem.PlatformDataKeys @@ -619,7 +619,7 @@ object UITools { fun getSelectedFiles(e: AnActionEvent): List { val dataContext = e.dataContext val data = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext) - if(null != data) return data.toList() + if (null != data) return data.toList() val editor = PlatformDataKeys.EDITOR.getData(dataContext) if (editor != null) { val file = FileDocumentManager.getInstance().getFile(editor.document) diff --git a/src/main/kotlin/icons/MyIcons.kt b/src/main/kotlin/icons/MyIcons.kt index ce754fd4..18155d18 100644 --- a/src/main/kotlin/icons/MyIcons.kt +++ b/src/main/kotlin/icons/MyIcons.kt @@ -4,7 +4,8 @@ import com.intellij.openapi.util.IconLoader object MyIcons { - @JvmField val icon = IconLoader.getIcon("/META-INF/toolbarIcon.svg", javaClass) + @JvmField + val icon = IconLoader.getIcon("/META-INF/toolbarIcon.svg", javaClass) /* IconLoader.findIcon( url = classLoader.getResource("./META-INF/toolbarIcon.svg"), diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index c9d0723a..9ae7c9ed 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -90,7 +90,7 @@ @@ -102,25 +102,25 @@ diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/ActionTestBase.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/ActionTestBase.kt index 470fe5aa..ed46a0da 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/ActionTestBase.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/ActionTestBase.kt @@ -3,8 +3,8 @@ import com.github.simiacryptus.aicoder.actions.FileContextAction 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.test.util.MarkdownProcessor +import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.simiacryptus.jopenai.models.OpenAIModels import com.simiacryptus.jopenai.util.ClientUtil import com.simiacryptus.util.JsonUtil diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CommentsActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CommentsActionTest.kt index 1c7f006c..26da98ec 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CommentsActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CommentsActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.CommentsAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class CommentsActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(CommentsAction(), "/CommentsActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CustomEditActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CustomEditActionTest.kt index b788a239..6fd97c57 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CustomEditActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/CustomEditActionTest.kt @@ -1,18 +1,18 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.code.CustomEditAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage import com.intellij.openapi.project.Project -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class CustomEditActionTest : ActionTestBase() { private val instruction = "Add code comments" -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(object : CustomEditAction() { override fun getConfig(project: Project?): String { diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DescribeActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DescribeActionTest.kt index 1370a7f6..5a1f7c45 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DescribeActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DescribeActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.code.DescribeAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class DescribeActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(DescribeAction(), "/DescribeActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DocActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DocActionTest.kt index 8b8bd217..975079c7 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DocActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/DocActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.DocAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test class DocActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(DocAction(), "/DocActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/ImplementStubActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/ImplementStubActionTest.kt index 28f99eff..28d0206d 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/ImplementStubActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/ImplementStubActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.ImplementStubAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class ImplementStubActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(ImplementStubAction(), "/ImplementStubActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/InsertImplementationActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/InsertImplementationActionTest.kt index 1a4ccfce..23e1395a 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/InsertImplementationActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/InsertImplementationActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.InsertImplementationAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class InsertImplementationActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(InsertImplementationAction(), "/InsertImplementationActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/RenameVariablesActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/RenameVariablesActionTest.kt index 614fe0e1..6585144e 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/RenameVariablesActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/code/RenameVariablesActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.code -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.RenameVariablesAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class RenameVariablesActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(object : RenameVariablesAction() { override fun choose(renameSuggestions: Map): Set { diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AnalogueFileActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AnalogueFileActionTest.kt index 9b048115..a458f037 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AnalogueFileActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AnalogueFileActionTest.kt @@ -2,10 +2,9 @@ import com.github.simiacryptus.aicoder.actions.generic.GenerateRelatedFileAction import com.github.simiacryptus.aicoder.test.actions.ActionTestBase -import org.junit.jupiter.api.Test class AnalogueFileActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_FileContextAction(GenerateRelatedFileAction(), "/AnalogueFileActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AppendActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AppendActionTest.kt index dd775741..ee688d2d 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AppendActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/AppendActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.generic -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.AppendTextWithChatAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class AppendActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(AppendTextWithChatAction(), "/AppendActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/CreateFileActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/CreateFileActionTest.kt index 81c12e2b..18a5d503 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/CreateFileActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/CreateFileActionTest.kt @@ -2,10 +2,9 @@ package com.github.simiacryptus.aicoder.test.actions.generic import com.github.simiacryptus.aicoder.actions.generic.CreateFileFromDescriptionAction import com.github.simiacryptus.aicoder.test.actions.ActionTestBase -import org.junit.jupiter.api.Test class CreateFileActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_FileContextAction(CreateFileFromDescriptionAction(), "/CreateFileActionTest.md") } diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/ReplaceOptionsActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/ReplaceOptionsActionTest.kt index 9c83d153..195ed1e6 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/ReplaceOptionsActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/generic/ReplaceOptionsActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.generic -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.legacy.ReplaceWithSuggestionsAction +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test class ReplaceOptionsActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(object : ReplaceWithSuggestionsAction() { override fun choose(choices: List): String { diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/markdown/MarkdownImplementActionTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/markdown/MarkdownImplementActionTest.kt index 1ea9e951..0fb52a68 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/markdown/MarkdownImplementActionTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/actions/markdown/MarkdownImplementActionTest.kt @@ -1,15 +1,15 @@ package com.github.simiacryptus.aicoder.test.actions.markdown -import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.actions.SelectionAction import com.github.simiacryptus.aicoder.actions.markdown.MarkdownImplementActionGroup +import com.github.simiacryptus.aicoder.test.actions.ActionTestBase import com.github.simiacryptus.aicoder.util.ComputerLanguage import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test class MarkdownImplementActionTest : ActionTestBase() { -// @Test + // @Test fun testProcessing() { testScript_SelectionAction(object : MarkdownImplementActionGroup.MarkdownImplementAction("kotlin") { override fun processSelection(state: SelectionState, config: String?): String { diff --git a/src/test/kotlin/com/github/simiacryptus/aicoder/test/util/DiffMatchPatchTest.kt b/src/test/kotlin/com/github/simiacryptus/aicoder/test/util/DiffMatchPatchTest.kt index 966eb499..ca5f6715 100644 --- a/src/test/kotlin/com/github/simiacryptus/aicoder/test/util/DiffMatchPatchTest.kt +++ b/src/test/kotlin/com/github/simiacryptus/aicoder/test/util/DiffMatchPatchTest.kt @@ -3,8 +3,8 @@ package com.github.simiacryptus.aicoder.test.util import com.simiacryptus.diff.DiffMatchPatch import com.simiacryptus.diff.DiffMatchPatch.Diff import com.simiacryptus.diff.DiffMatchPatch.Operation.* -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test import java.util.* @@ -41,7 +41,7 @@ class DiffMatchPatchTest { Assertions.assertEquals(4, DiffMatchPatch.diff_commonSuffix("1234", "xyz1234")) } -// @Test + // @Test fun testPatchMakeAndApply() { val text1 = "The quick brown fox jumps over the lazy dog." val text2 = "The quick red fox jumps over the tired dog." @@ -55,7 +55,7 @@ class DiffMatchPatchTest { } } -// @Test + // @Test fun testPatchMakeWithDiffs() { val text1 = "The quick brown fox jumps over the lazy dog." val text2 = "That quick brown fox jumped over a lazy dog." diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml index 4bd2e376..e162fb77 100644 --- a/src/test/resources/logback.xml +++ b/src/test/resources/logback.xml @@ -6,6 +6,6 @@ - + \ No newline at end of file