diff --git a/README.md b/README.md index 6c2a43e7..68ae8c95 100644 --- a/README.md +++ b/README.md @@ -76,18 +76,18 @@ Maven: com.simiacryptus skyenet-webui - 1.0.52 + 1.0.53 ``` Gradle: ```groovy -implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.52' +implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.53' ``` ```kotlin -implementation("com.simiacryptus:skyenet:1.0.52") +implementation("com.simiacryptus:skyenet:1.0.53") ``` ### 🌟 To Use diff --git a/core/build.gradle.kts b/core/build.gradle.kts index aefea7c5..f1afca3e 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -32,7 +32,7 @@ val jackson_version = "2.15.3" dependencies { - implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.48") + implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.49") implementation(group = "org.slf4j", name = "slf4j-api", version = "2.0.9") implementation(group = "commons-io", name = "commons-io", version = "2.15.0") diff --git a/gradle.properties b/gradle.properties index b5c64033..3ffac14e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ # Gradle Releases -> https://github.com/gradle/gradle/releases libraryGroup = com.simiacryptus.skyenet -libraryVersion = 1.0.52 +libraryVersion = 1.0.53 gradleVersion = 7.6.1 diff --git a/webui/build.gradle.kts b/webui/build.gradle.kts index 2dc9ba7e..2f9b919f 100644 --- a/webui/build.gradle.kts +++ b/webui/build.gradle.kts @@ -35,7 +35,7 @@ val jetty_version = "11.0.18" val jackson_version = "2.15.3" dependencies { - implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.48") + implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.49") implementation(project(":core")) implementation(project(":kotlin")) diff --git a/webui/src/main/kotlin/com/github/simiacryptus/aicoder/util/SimpleDiffUtil.kt b/webui/src/main/kotlin/com/github/simiacryptus/aicoder/util/SimpleDiffUtil.kt index c40d77bc..53737cf0 100644 --- a/webui/src/main/kotlin/com/github/simiacryptus/aicoder/util/SimpleDiffUtil.kt +++ b/webui/src/main/kotlin/com/github/simiacryptus/aicoder/util/SimpleDiffUtil.kt @@ -169,12 +169,13 @@ fun SocketManagerBase.addSaveLinks( response: String, handle: (String, String) -> Unit ): String { - val diffPattern = """(?s)(? val filename = diffBlock.groupValues[1] +// val language = diffBlock.groupValues[2] val codeValue = diffBlock.groupValues[2] - val hrefLink = hrefLink("Apply Diff") { + val hrefLink = hrefLink("Save File") { try { handle(filename, codeValue) send(SocketManagerBase.divInitializer(cancelable = false) + """
Saved ${filename}
""") diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/AgentPatterns.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/AgentPatterns.kt index 8f1f703b..798c5ec2 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/AgentPatterns.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/AgentPatterns.kt @@ -2,146 +2,252 @@ package com.simiacryptus.skyenet import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.ApiModel +import com.simiacryptus.jopenai.ApiModel.Role import com.simiacryptus.jopenai.util.ClientUtil.toContentList import com.simiacryptus.skyenet.core.actors.BaseActor import com.simiacryptus.skyenet.webui.application.ApplicationInterface import com.simiacryptus.skyenet.webui.session.SessionTask import com.simiacryptus.skyenet.webui.util.MarkdownUtil.renderMarkdown +import java.util.concurrent.Callable import java.util.concurrent.Semaphore import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference object AgentPatterns { - fun retryable( - ui: ApplicationInterface, - task: SessionTask = ui.newTask(), - process: () -> String, - ): String { + fun displayMapInTabs( + map: Map, + ) = """ +
+
${ + map.keys.joinToString("\n") { key -> + """""" + } + }
+ ${ + map.entries.withIndex().joinToString("\n") { (idx, t) -> + val (key, value) = t + """
"" + } + }" data-tab="$key">$value
""" + } + } +
+ """.trimIndent() + + open class Retryable( + val ui: ApplicationInterface, + val task: SessionTask, + open val process: (StringBuilder) -> String, + ) { val container = task.add("
") val history = mutableListOf() - return object { - fun newHTML(ui: ApplicationInterface): String = """ -
-
- ${ - history.withIndex().joinToString("\n") { (index, _) -> - val tabId = "$index" - """""" - } - } - ${ - ui.hrefLink("â™»") { - val idx = history.size - history.add("Retrying...") - container?.clear() - container?.append(newHTML(ui)) - task.add("") - val newResult = process() - history.removeAt(idx) - addTab(ui, newResult, idx) - } - } -
- ${ - history.withIndex().joinToString("\n") { (index, content) -> - """ -
- $content -
- """.trimIndent() - } + fun newHTML(ui: ApplicationInterface): String = """ +
+
+ ${ + history.withIndex().joinToString("\n") { (index, _) -> + val tabId = "$index" + """""" } -
- """.trimIndent() - - fun addTab(ui: ApplicationInterface, content: String, idx: Int = history.size): String { - history.add(idx, content) + } + ${ + ui.hrefLink("â™»") { + val idx = history.size + history.add("Retrying...") container?.clear() container?.append(newHTML(ui)) - task.complete() - return content + task.add("") + val newResult = process(container!!) + history.removeAt(idx) + addTab(ui, newResult, idx) + } + } +
+ ${ + history.withIndex().joinToString("\n") { (index, content) -> + """ +
+ $content +
+ """.trimIndent() } - }.addTab(ui, process()) + } +
+ """.trimIndent() + + fun addTab(ui: ApplicationInterface, content: String, idx: Int = history.size): String { + history.add(idx, content) + container?.clear() + container?.append(newHTML(ui)) + task.complete() + return content + } } - private fun List, ApiModel.Role>>.toMessageList(): Array = - this.map { (content, role) -> - ApiModel.ChatMessage( - role = role, - content = content - ) - }.toTypedArray() + fun retryable( + ui: ApplicationInterface, + task: SessionTask = ui.newTask(), + process: (StringBuilder) -> String, + ) = object : Retryable(ui, task, process){ + init { + addTab(ui, process(container!!)) + } + } + private fun List, Role>>.toMessageList(): Array = + this.map { (content, role) -> ApiModel.ChatMessage(role = role, content = content) }.toTypedArray() fun iterate( ui: ApplicationInterface, userMessage: String, heading: String = renderMarkdown(userMessage), initialResponse: (String) -> T, - reviseResponse: (String, T, String) -> T, - outputFn: (SessionTask, T) -> Unit = { task, design -> task.add(renderMarkdown(design.toString())) }, + reviseResponse: (List>) -> T, + outputFn: (T) -> String = { design -> renderMarkdown(design.toString()) }, + task: SessionTask = ui.newTask() ): T { - val task = ui.newTask() - fun main(): T = try { - task.echo(heading) - var design = initialResponse(userMessage) - outputFn(task, design) - var textInputHandle: StringBuilder? = null - val onAccept = Semaphore(0) - var textInput: String? = null - var acceptLink: String? = null - var retryLink: String? = null - val feedbackGuard = AtomicBoolean(false) + val atomicRef = AtomicReference() + val semaphore = Semaphore(0) + return object : Callable { + val tabs = mutableListOf() + val options = mutableListOf() + val tabContainer = task.add("
") val acceptGuard = AtomicBoolean(false) - val retryGuard = AtomicBoolean(false) - fun feedbackForm() = """ - |
- |${acceptLink!!} - |${retryLink!!} - |
- |${textInput!!} - """.trimMargin() - textInput = ui.textInput { userResponse -> - if (feedbackGuard.getAndSet(true)) return@textInput - textInputHandle?.clear() - task.echo(renderMarkdown(userResponse)) - design = reviseResponse(userMessage, design, userResponse) - outputFn(task, design) - textInputHandle = task.complete(feedbackForm(), className = "reply-message") - feedbackGuard.set(false) + val feedbackGuard = AtomicBoolean(false) + + fun main(tabIndex: Int = tabs.size) { + try { + val history = mutableListOf>() + history.add(userMessage to Role.user) + var design = initialResponse(userMessage) + options.add(design) + history.add(outputFn(design) to Role.assistant) + var textInput: String? = null + var acceptLink: String? = null + fun feedbackForm() = """ + |
+ |${acceptLink!!} + |
+ |${textInput!!} + """.trimMargin() + textInput = ui.textInput { userResponse -> + if (feedbackGuard.getAndSet(true)) return@textInput + val markdown = renderMarkdown(userResponse) + history.add(markdown to Role.user) + task.complete() + design = reviseResponse(history + listOf(userResponse to Role.user)) + if (tabs.size > tabIndex) tabs[tabIndex].append(markdown + "\n" + outputFn(design) + "\n" + feedbackForm()) + else tabs.add(StringBuilder(markdown + "\n" + outputFn(design) + "\n" + feedbackForm())) + tabContainer?.clear() + tabContainer?.append(newHTML(tabIndex).trimIndent()) + task.complete() + feedbackGuard.set(false) + } + val idx = tabs.size + acceptLink = "" + + ui.hrefLink("\uD83D\uDC4D") { + val tab = tabs[tabIndex] + val prevTab = tab.toString() + tab.clear() + tab.append( + prevTab.substringBefore("") + "" + prevTab.substringAfter( + "" + ) + ) + tabContainer?.clear() + tabContainer?.append(newHTML(tabIndex).trimIndent()) + task.complete() + accept(acceptGuard, design, idx) + } + "" + if (tabs.size > tabIndex) tabs[tabIndex].append(outputFn(design) + "\n" + feedbackForm()) + else tabs.add(StringBuilder(outputFn(design) + "\n" + feedbackForm())) + tabContainer?.clear() + tabContainer?.append(newHTML(idx).trimIndent()) + task.complete() + } catch (e: Throwable) { + task.error(ui, e) + task.complete(ui.hrefLink("🔄 Retry") { + main() + }) + } + } + + // Adjust the logic to handle the replaceTabIndex parameter properly + private fun newHTML(idx: Int = tabs.size - 1, replaceTabIndex: Int? = null): String { + replaceTabIndex?.let { tabs.removeAt(it) } + return """ +
+
+ ${ + tabs.withIndex().joinToString("\n") { (index, _) -> + """""" + } + } + ${ + ui.hrefLink("â™»") { + val idx = tabs.size + tabs.add(StringBuilder("Retrying...")) + tabContainer?.clear() + tabContainer?.append(newHTML(idx)) + task.add("") + main(idx) + } + } +
+ ${ + tabs.withIndex().joinToString("\n") { (index, content) -> + """ +
+ $content +
+ """.trimIndent() + } + } +
+ """ } - acceptLink = ui.hrefLink("\uD83D\uDC4D") { - if (acceptGuard.getAndSet(true)) return@hrefLink - textInputHandle?.clear() + + private fun accept( + acceptGuard: AtomicBoolean, design: T, idx: Int + ) { + if (acceptGuard.getAndSet(true)) return + tabContainer?.clear() + tabContainer?.append( + """ +
+
${ + tabs.indices.joinToString(separator = "\n") { index -> + "" + } + }
${ + tabs.withIndex().joinToString(separator = "\n") { (index, content) -> + "
" active" + else -> "" + } + }\" data-tab=\"$index\">$content
" + } + } +
+ """.trimIndent()) task.complete() - onAccept.release() + atomicRef.set(design) + semaphore.release() } - retryLink = ui.hrefLink("♻") { - if (retryGuard.getAndSet(true)) return@hrefLink - textInputHandle?.clear() + + override fun call(): T { task.echo(heading) - design = initialResponse(userMessage) - outputFn(task, design) - textInputHandle = task.complete(feedbackForm(), className = "reply-message") - feedbackGuard.set(false) - acceptGuard.set(false) - retryGuard.set(false) + main() + semaphore.acquire() + return atomicRef.get() } - textInputHandle = task.complete(feedbackForm(), className = "reply-message") - onAccept.acquire() - design - } catch (e: Throwable) { - val atomicRef = AtomicReference() - val semaphore = Semaphore(0) - task.error(ui, e) - task.complete(ui.hrefLink("🔄 Retry") { - atomicRef.set(main()) - semaphore.release() - }) - semaphore.acquire() - atomicRef.get() - } - return main() + + }.call() + } @@ -152,25 +258,22 @@ object AgentPatterns { toInput: (String) -> I, api: API, ui: ApplicationInterface, - outputFn: (SessionTask, T) -> Unit = { task, design -> task.add(renderMarkdown(design.toString())) } + outputFn: (T) -> String = { design -> renderMarkdown(design.toString()) }, + task: SessionTask = ui.newTask() ) = iterate( ui = ui, userMessage = input, heading = heading, initialResponse = { actor.answer(toInput(it), api = api) }, - reviseResponse = { userMessage: String, design: T, userResponse: String -> - val input = toInput(userMessage) + reviseResponse = { userMessages: List> -> actor.respond( - messages = actor.chatMessages(input) + - listOf( - design.toString().toContentList() to ApiModel.Role.assistant, - userResponse.toContentList() to ApiModel.Role.user - ).toMessageList(), - input = input, + messages = (userMessages.map { ApiModel.ChatMessage(it.second, it.first.toContentList()) }.toTypedArray()), + input = toInput(input), api = api ) }, - outputFn = outputFn + outputFn = outputFn, + task = task ) } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/CodingAgent.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/CodingAgent.kt index e6a312f7..7a1fd876 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/CodingAgent.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/CodingAgent.kt @@ -90,7 +90,7 @@ open class CodingAgent( log.warn("Error", e) val error = task.error(ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(ui.hrefLink("♻", "href-link regen-button") { + regenButton = task.complete(ui.hrefLink("♻", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") displayCode(task, codeRequest) @@ -176,7 +176,7 @@ open class CodingAgent( request: CodingActor.CodeRequest, formText: StringBuilder, formHandle: () -> StringBuilder - ) = ui.hrefLink("♻", "href-link regen-button") { + ) = ui.hrefLink("♻", "href-link regen-button"){ responseAction(task, "Regenerating...", formHandle(), formText) { displayCode( ui.newTask(), @@ -192,7 +192,7 @@ open class CodingAgent( formText: StringBuilder, formHandle: () -> StringBuilder ) = if (!canPlay) "" else - ui.hrefLink("▶", "href-link play-button") { + ui.hrefLink("▶", "href-link play-button"){ responseAction(task, "Running...", formHandle(), formText) { execute(ui.newTask(), response, request) } @@ -221,7 +221,7 @@ open class CodingAgent( formText: StringBuilder ): StringBuilder? { var revertButton: StringBuilder? = null - revertButton = task.complete(ui.hrefLink("↩", "href-link regen-button") { + revertButton = task.complete(ui.hrefLink("↩", "href-link regen-button"){ revertButton?.clear() formHandle?.append(formText) task.complete() diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ShellToolAgent.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ShellToolAgent.kt index a2f92af5..3539e4c6 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ShellToolAgent.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ShellToolAgent.kt @@ -4,7 +4,6 @@ import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.ApiModel import com.simiacryptus.jopenai.OpenAIClient import com.simiacryptus.jopenai.describe.AbbrevWhitelistYamlDescriber -import com.simiacryptus.jopenai.describe.Description import com.simiacryptus.jopenai.describe.TypeDescriber import com.simiacryptus.jopenai.models.ChatModels import com.simiacryptus.jopenai.util.JsonUtil @@ -31,7 +30,6 @@ import org.openapitools.codegen.OpenAPIGenerator import org.openapitools.codegen.SpecValidationException import org.slf4j.LoggerFactory import java.io.File -import java.util.function.Function import kotlin.reflect.KClass private val String.escapeQuotedString: String @@ -72,7 +70,7 @@ abstract class ShellToolAgent( |
|${ if (!super.canPlay) "" else - super.ui.hrefLink("â–¶", "href-link play-button") { + super.ui.hrefLink("â–¶", "href-link play-button"){ super.responseAction(task, "Running...", formHandle!!, formText) { super.execute(super.ui.newTask(), response, request) } @@ -115,7 +113,7 @@ abstract class ShellToolAgent( response: CodeResult, formText: StringBuilder, formHandle: () -> StringBuilder - ) = ui.hrefLink("\uD83D\uDCE4", "href-link regen-button") { + ) = ui.hrefLink("\uD83D\uDCE4", "href-link regen-button"){ val task = ui.newTask() responseAction(task, "Exporting...", formHandle(), formText) { displayCodeFeedback( @@ -136,26 +134,26 @@ abstract class ShellToolAgent( val cwd = actor.symbols.get("workingDir")?.toString()?.let { java.io.File(it) } ?: java.io.File(".") val env = actor.symbols.get("env")?.let { env -> (env as Map) } ?: mapOf() val codePrefix = """ - fun execute() : Pair { - val command = "${command.joinToString(" ").escapeQuotedString}".split(" ") - val cwd = java.io.File("${cwd.absolutePath.escapeQuotedString}") - val env = mapOf(${env.entries.joinToString(",") { "\"${it.key.escapeQuotedString}\" to \"${it.value.escapeQuotedString}\"" }}) - val processBuilder = ProcessBuilder(*command.toTypedArray()).directory(cwd) - processBuilder.environment().putAll(env) - val process = processBuilder.start() - process.outputStream.write("${response.code.escapeQuotedString}".toByteArray()) - process.outputStream.close() - val output = process.inputStream.bufferedReader().readText() - val error = process.errorStream.bufferedReader().readText() - val waitFor = process.waitFor(5, java.util.concurrent.TimeUnit.MINUTES) - if (!waitFor) { - process.destroy() - throw RuntimeException("Timeout; output: " + output + "; error: " + error) - } else { - return Pair(output, error) + fun execute() : Pair { + val command = "${command.joinToString(" ").escapeQuotedString}".split(" ") + val cwd = java.io.File("${cwd.absolutePath.escapeQuotedString}") + val env = mapOf(${env.entries.joinToString(",") { "\"${it.key.escapeQuotedString}\" to \"${it.value.escapeQuotedString}\"" }}) + val processBuilder = ProcessBuilder(*command.toTypedArray()).directory(cwd) + processBuilder.environment().putAll(env) + val process = processBuilder.start() + process.outputStream.write("${response.code.escapeQuotedString}".toByteArray()) + process.outputStream.close() + val output = process.inputStream.bufferedReader().readText() + val error = process.errorStream.bufferedReader().readText() + val waitFor = process.waitFor(5, java.util.concurrent.TimeUnit.MINUTES) + if (!waitFor) { + process.destroy() + throw RuntimeException("Timeout; output: " + output + "; error: " + error) + } else { + return Pair(output, error) + } } - } - """.trimIndent() + """.trimIndent() val messages = listOf( "Shell Code: \n```${actor.language}\n${response.code}\n```" to ApiModel.Role.assistant, ) + (lastResult?.let { listOf( @@ -175,7 +173,7 @@ abstract class ShellToolAgent( messages = listOf( (codePrefix + "\n\n" + parsedCode) to ApiModel.Role.assistant, "Reprocess this code prototype into a servlet. " + - "The last line should instantiate the new servlet class and return it via the returnBuffer collection." to ApiModel.Role.user + "The last line should instantiate the new servlet class and return it via the returnBuffer collection." to ApiModel.Role.user ), codePrefix = schemaCode ) @@ -206,10 +204,10 @@ abstract class ShellToolAgent( break; } catch (e: SpecValidationException) { val error = """ - |${e.message} - |${e.errors.joinToString("\n") { "ERROR:" + it.toString() }} - |${e.warnings.joinToString("\n") { "WARN:" + it.toString() }} - """.trimIndent() + |${e.message} + |${e.errors.joinToString("\n") { "ERROR:" + it.toString() }} + |${e.warnings.joinToString("\n") { "WARN:" + it.toString() }} + """.trimIndent() task.hideable(ui, renderMarkdown("```\n${error}\n```")) openAPI = openAPIParsedActor().answer( listOf( @@ -333,7 +331,7 @@ abstract class ShellToolAgent( """ |
|${ - super.ui.hrefLink("\uD83D\uDC4D", "href-link play-button") { + super.ui.hrefLink("\uD83D\uDC4D", "href-link play-button"){ super.responseAction(task, "Accepted...", formHandle!!, formText) { onComplete(response.code) } @@ -341,12 +339,12 @@ abstract class ShellToolAgent( } |${ if (!super.canPlay) "" else - ui.hrefLink("â–¶", "href-link play-button") { + ui.hrefLink("â–¶", "href-link play-button"){ execute(ui.newTask(), response) } } |${ - super.ui.hrefLink("â™»", "href-link regen-button") { + super.ui.hrefLink("â™»", "href-link regen-button"){ super.responseAction(task, "Regenerating...", formHandle!!, formText) { //val task = super.ui.newTask() val codeRequest = @@ -369,7 +367,7 @@ abstract class ShellToolAgent( log.warn("Error", e) val error = task.error(super.ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button") { + regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") super.displayCode(task, codeRequest) @@ -412,7 +410,7 @@ abstract class ShellToolAgent( log.warn("Error", e) val error = task.error(super.ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button") { + regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") super.displayCode(task, codeRequest) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ToolAgent.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ToolAgent.kt index c61a9e07..2f568a93 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ToolAgent.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/coding/ToolAgent.kt @@ -4,7 +4,6 @@ import com.simiacryptus.jopenai.API import com.simiacryptus.jopenai.ApiModel import com.simiacryptus.jopenai.OpenAIClient import com.simiacryptus.jopenai.describe.AbbrevWhitelistYamlDescriber -import com.simiacryptus.jopenai.describe.Description import com.simiacryptus.jopenai.describe.TypeDescriber import com.simiacryptus.jopenai.models.ChatModels import com.simiacryptus.jopenai.util.JsonUtil @@ -31,7 +30,6 @@ import org.openapitools.codegen.OpenAPIGenerator import org.openapitools.codegen.SpecValidationException import org.slf4j.LoggerFactory import java.io.File -import java.util.function.Function import kotlin.reflect.KClass abstract class ToolAgent( @@ -79,7 +77,7 @@ abstract class ToolAgent( response: CodeResult, formText: StringBuilder, formHandle: () -> StringBuilder - ) = ui.hrefLink("\uD83D\uDCE4", "href-link regen-button") { + ) = ui.hrefLink("\uD83D\uDCE4", "href-link regen-button"){ val task = ui.newTask() responseAction(task, "Exporting...", formHandle(), formText) { displayCodeFeedback( @@ -126,10 +124,10 @@ abstract class ToolAgent( break; } catch (e: SpecValidationException) { val error = """ - |${e.message} - |${e.errors.joinToString("\n") { "ERROR:" + it.toString() }} - |${e.warnings.joinToString("\n") { "WARN:" + it.toString() }} - """.trimIndent() + |${e.message} + |${e.errors.joinToString("\n") { "ERROR:" + it.toString() }} + |${e.warnings.joinToString("\n") { "WARN:" + it.toString() }} + """.trimIndent() task.hideable(ui, renderMarkdown("```\n${error}\n```")) openAPI = openAPIParsedActor().answer( listOf( @@ -239,14 +237,14 @@ abstract class ToolAgent( |
|${ if (!super.canPlay) "" else - super.ui.hrefLink("\uD83D\uDC4D", "href-link play-button") { + super.ui.hrefLink("\uD83D\uDC4D", "href-link play-button"){ super.responseAction(task, "Accepted...", formHandle!!, formText) { onComplete(response.code) } } } |${ - super.ui.hrefLink("â™»", "href-link regen-button") { + super.ui.hrefLink("â™»", "href-link regen-button"){ super.responseAction(task, "Regenerating...", formHandle!!, formText) { //val task = super.ui.newTask() val codeRequest = @@ -269,7 +267,7 @@ abstract class ToolAgent( log.warn("Error", e) val error = task.error(super.ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button") { + regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") super.displayCode(task, codeRequest) @@ -312,7 +310,7 @@ abstract class ToolAgent( log.warn("Error", e) val error = task.error(super.ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button") { + regenButton = task.complete(super.ui.hrefLink("â™»", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") super.displayCode(task, codeRequest) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/general/WebDevApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/general/WebDevApp.kt index 976828d7..0be2a6a0 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/general/WebDevApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/apps/general/WebDevApp.kt @@ -159,8 +159,8 @@ class WebDevAgent( toInput = { listOf(it) }, api = api, ui = ui, - outputFn = { task, design -> - task.add(renderMarkdown("${design.text}\n\n```json\n${JsonUtil.toJson(design.obj)}\n```")) + outputFn = { design -> + renderMarkdown("${design.text}\n\n```json\n${JsonUtil.toJson(design.obj)}\n```") } ) @@ -308,7 +308,7 @@ class WebDevAgent( """ |
|${ - ui.hrefLink("â™»", "href-link regen-button") { + ui.hrefLink("â™»", "href-link regen-button"){ val task = ui.newTask() responseAction(task, "Regenerating...", formHandle!!, formText) { draftResourceCode( @@ -358,7 +358,7 @@ class WebDevAgent( log.warn("Error", e) val error = task.error(ui, e) var regenButton: StringBuilder? = null - regenButton = task.complete(ui.hrefLink("â™»", "href-link regen-button") { + regenButton = task.complete(ui.hrefLink("â™»", "href-link regen-button"){ regenButton?.clear() val header = task.header("Regenerating...") draftResourceCode(task, request, actor, path, *languages) @@ -383,7 +383,7 @@ class WebDevAgent( } finally { header?.clear() var revertButton: StringBuilder? = null - revertButton = task.complete(ui.hrefLink("↩", "href-link regen-button") { + revertButton = task.complete(ui.hrefLink("↩", "href-link regen-button"){ revertButton?.clear() formHandle?.append(formText) task.complete() diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt index ff87475b..24290718 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt @@ -13,9 +13,11 @@ open class ApplicationInterface(val socketManager: SocketManagerBase) { linkText: String, @Description("The css class to apply to the link") classname: String = """href-link""", + @Description("The id to apply to the link") + id: String? = null, @Description("The handler to trigger when the link is clicked") - handler: Consumer - ) = socketManager.hrefLink(linkText, classname, oneAtATime(handler)) + handler: Consumer, + ) = socketManager.hrefLink(linkText, classname, id, oneAtATime(handler)) @Description("Returns html for a text input form that will trigger the given handler when submitted.") open fun textInput( diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionTask.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionTask.kt index 111f89c7..182135d2 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionTask.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionTask.kt @@ -69,7 +69,7 @@ abstract class SessionTask( ): StringBuilder? { var windowBuffer: StringBuilder? = null val closeButton = """${ - ui.hrefLink("×", "close-button href-link") { + ui.hrefLink("×", "close-button href-link"){ windowBuffer?.clear() send() } diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt index 26c22f14..f619af00 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt @@ -169,10 +169,13 @@ abstract class SocketManagerBase( } } - fun hrefLink(linkText: String, classname: String = """href-link""", handler: Consumer): String { + fun hrefLink(linkText: String, classname: String = """href-link""", id: String? = null, handler: Consumer): String { val operationID = randomID() linkTriggers[operationID] = handler - return """$linkText""" + return """ """ id="$id"""" + else -> "" + }}>$linkText""" } fun textInput(handler: Consumer): String { diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt index 423b0b30..5f0ff0a0 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt @@ -40,15 +40,15 @@ open class CodingActorTestApp( OperationType.Execute ) val playLink = if (!canPlay) "" else { - ui.hrefLink("â–¶", "href-link play-button") { - message.add("Running...") - val result = response.result - message.complete( - """ - |
${result.resultValue}
- |
${result.resultOutput}
- """.trimMargin() - ) + ui.hrefLink("â–¶", "href-link play-button"){ + message.add("Running...") + val result = response.result + message.complete( + """ + |
${result.resultValue}
+ |
${result.resultOutput}
+ """.trimMargin() + ) } } message.complete(