From c26ad267de1d5616fcf1c1b7bbe454ea8bf173d6 Mon Sep 17 00:00:00 2001 From: Andrew Charneski Date: Wed, 22 Nov 2023 02:23:54 -0500 Subject: [PATCH] 1.0.37 (#41) * 1.0.37 * Update ChatSocket.kt * fix * wip * jo-penai updates * reorg * fixes --- README.md | 6 +- core/build.gradle.kts | 2 +- .../skyenet/{ => core}/OutputInterceptor.java | 222 +++--- .../simiacryptus/skyenet/actors/BaseActor.kt | 39 -- .../skyenet/actors/SimpleActor.kt | 23 - .../simiacryptus/skyenet/{ => core}/Brain.kt | 430 ++++++------ .../simiacryptus/skyenet/{ => core}/Ears.kt | 12 +- .../simiacryptus/skyenet/{ => core}/Heart.kt | 78 +-- .../simiacryptus/skyenet/{ => core}/Mouth.kt | 2 +- .../skyenet/{ => core}/actors/ActorSystem.kt | 18 +- .../skyenet/core/actors/BaseActor.kt | 39 ++ .../skyenet/{ => core}/actors/CodingActor.kt | 54 +- .../skyenet/{ => core}/actors/ParsedActor.kt | 16 +- .../{ => core}/actors/ParsedResponse.kt | 2 +- .../skyenet/core/actors/SimpleActor.kt | 22 + .../actors/opt/ActorOptimization.kt | 19 +- .../{ => core}/actors/opt/Expectation.kt | 11 +- .../actors/record/CodingActorInterceptor.kt | 40 +- .../actors/record/ParsedActorInterceptor.kt | 27 +- .../actors/record/SimpleActorInterceptor.kt | 23 +- .../{ => core}/actors/test/ActorTestBase.kt | 8 +- .../actors/test/CodingActorTestBase.kt | 10 +- .../actors/test/ParsedActorTestBase.kt | 8 +- .../platform/ApplicationServices.kt | 7 +- .../platform/AuthenticationManager.kt | 4 +- .../platform/AuthorizationManager.kt | 2 +- .../skyenet/core/platform/ClientManager.kt | 50 ++ .../{ => core}/platform/DataStorage.kt | 66 +- .../skyenet/{ => core}/platform/Session.kt | 4 +- .../{ => core}/platform/UsageManager.kt | 25 +- .../skyenet/core/platform/User.kt | 27 + .../platform/UserSettingsManager.kt | 8 +- .../skyenet/{ => core}/util/AwsUtil.kt | 2 +- .../{ => core}/util/FunctionWrapper.kt | 4 +- .../skyenet/{ => core}/util/HeartTestBase.kt | 4 +- .../{ => core}/util/LoggingInterceptor.kt | 2 +- .../com/simiacryptus/skyenet/platform/User.kt | 24 - .../skyenet/{ => core}/DataStorageTest.kt | 4 +- .../OutputInterceptorThreadedTest.java | 104 +-- .../skyenet/core/actors}/ActorOptTest.kt | 9 +- gradle.properties | 2 +- .../{heart => groovy}/GroovyInterpreter.kt | 86 +-- .../{ => groovy}/GroovyInterpreterTest.kt | 5 +- java/build.gradle.kts | 153 ----- .../{heart => kotlin}/KotlinInterpreter.kt | 4 +- .../{ => kotlin}/KotlinInterpreterTest.kt | 4 +- .../ScalaLocalInterpreter.scala | 6 +- .../ScalaLocalInterpreterTest.scala | 27 +- settings.gradle.kts | 3 +- skyenet.svg | 10 +- webui/build.gradle.kts | 2 +- .../simiacryptus/skyenet/chat/ChatSocket.kt | 89 --- .../skyenet/chat/ChatSocketManager.kt | 71 -- .../skyenet/servlet/SessionListServlet.kt | 56 -- .../application}/ApplicationDirectory.kt | 21 +- .../application}/ApplicationInterface.kt | 3 +- .../application/ApplicationServer.kt} | 57 +- .../application}/ApplicationSocketManager.kt | 33 +- .../skyenet/{ => webui}/chat/ChatServer.kt | 42 +- .../skyenet/webui/chat/ChatSocket.kt | 40 ++ .../skyenet/webui/chat/ChatSocketManager.kt | 72 ++ .../{ => webui}/chat/CodeChatServer.kt | 27 +- .../{ => webui}/servlet/AppInfoServlet.kt | 4 +- .../servlet/AuthenticatedWebsite.kt | 10 +- .../skyenet/{ => webui}/servlet/CorsFilter.kt | 2 +- .../{ => webui}/servlet/FileServlet.kt | 14 +- .../{ => webui}/servlet/NewSessionServlet.kt | 4 +- .../{ => webui}/servlet/ProxyHttpServlet.kt | 2 +- .../webui/servlet/SessionListServlet.kt | 60 ++ .../servlet/SessionSettingsServlet.kt | 14 +- .../{ => webui}/servlet/UsageServlet.kt | 15 +- .../{ => webui}/servlet/UserInfoServlet.kt | 15 +- .../servlet/UserSettingsServlet.kt | 10 +- .../{ => webui}/servlet/WelcomeServlet.kt | 16 +- .../skyenet/{ => webui}/servlet/ZipServlet.kt | 10 +- .../session}/MutableSessionHandler.kt | 5 +- .../{ => webui}/session/SessionMessage.kt | 4 +- .../{ => webui}/session/SocketManager.kt | 4 +- .../{ => webui}/session/SocketManagerBase.kt | 20 +- .../{ => webui}/test/CodingActorTestApp.kt | 28 +- .../{ => webui}/test/ParsedActorTestApp.kt | 28 +- .../{ => webui}/test/SimpleActorTestApp.kt | 25 +- .../{ => webui}/util/ClasspathResource.kt | 2 +- .../{ => webui}/util/EmbeddingVisualizer.kt | 22 +- .../skyenet/{ => webui}/util/MarkdownUtil.kt | 2 +- .../{simpleSession => application}/chat.css | 640 +++++++++--------- .../{simpleSession => application}/chat.js | 140 ++-- .../favicon.svg | 2 +- .../{simpleSession => application}/index.html | 118 ++-- .../{simpleSession => application}/main.js | 6 + webui/src/main/resources/codeChat/favicon.svg | 2 +- webui/src/main/resources/welcome/chat.css | 2 +- webui/src/main/resources/welcome/favicon.svg | 2 +- .../skyenet/{ => webui}/ActorTestAppServer.kt | 32 +- 94 files changed, 1701 insertions(+), 1829 deletions(-) rename core/src/main/java/com/simiacryptus/skyenet/{ => core}/OutputInterceptor.java (96%) delete mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt delete mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/Brain.kt (92%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/Ears.kt (92%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/Heart.kt (94%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/Mouth.kt (98%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/ActorSystem.kt (63%) create mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/BaseActor.kt rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/CodingActor.kt (87%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/ParsedActor.kt (67%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/ParsedResponse.kt (79%) create mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/SimpleActor.kt rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/opt/ActorOptimization.kt (93%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/opt/Expectation.kt (88%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/record/CodingActorInterceptor.kt (65%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/record/ParsedActorInterceptor.kt (59%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/record/SimpleActorInterceptor.kt (53%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/test/ActorTestBase.kt (87%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/test/CodingActorTestBase.kt (65%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/actors/test/ParsedActorTestBase.kt (68%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/ApplicationServices.kt (83%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/AuthenticationManager.kt (86%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/AuthorizationManager.kt (97%) create mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ClientManager.kt rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/DataStorage.kt (78%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/Session.kt (53%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/UsageManager.kt (89%) create mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/User.kt rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/platform/UserSettingsManager.kt (80%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/util/AwsUtil.kt (97%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/util/FunctionWrapper.kt (97%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/util/HeartTestBase.kt (97%) rename core/src/main/kotlin/com/simiacryptus/skyenet/{ => core}/util/LoggingInterceptor.kt (98%) delete mode 100644 core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt rename core/src/test/java/com/simiacryptus/skyenet/{ => core}/DataStorageTest.kt (91%) rename core/src/test/java/com/simiacryptus/skyenet/{ => core}/OutputInterceptorThreadedTest.java (95%) rename {webui/src/test/kotlin/com/simiacryptus/skyenet => core/src/test/java/com/simiacryptus/skyenet/core/actors}/ActorOptTest.kt (91%) rename groovy/src/main/kotlin/com/simiacryptus/skyenet/{heart => groovy}/GroovyInterpreter.kt (89%) rename groovy/src/test/kotlin/com/simiacryptus/skyenet/{ => groovy}/GroovyInterpreterTest.kt (56%) delete mode 100644 java/build.gradle.kts rename kotlin/src/main/kotlin/com/simiacryptus/skyenet/{heart => kotlin}/KotlinInterpreter.kt (99%) rename kotlin/src/test/kotlin/com/simiacryptus/skyenet/{ => kotlin}/KotlinInterpreterTest.kt (90%) rename scala/src/main/scala/com/simiacryptus/skyenet/{heart => scala}/ScalaLocalInterpreter.scala (97%) rename scala/src/test/scala/com/simiacryptus/skyenet/{heart => scala}/ScalaLocalInterpreterTest.scala (51%) delete mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocket.kt delete mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocketManager.kt delete mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui/application}/ApplicationDirectory.kt (86%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{session => webui/application}/ApplicationInterface.kt (83%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ApplicationBase.kt => webui/application/ApplicationServer.kt} (73%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{session => webui/application}/ApplicationSocketManager.kt (74%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/chat/ChatServer.kt (66%) create mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocket.kt create mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocketManager.kt rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/chat/CodeChatServer.kt (70%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/AppInfoServlet.kt (86%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/AuthenticatedWebsite.kt (94%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/CorsFilter.kt (95%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/FileServlet.kt (92%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/NewSessionServlet.kt (81%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/ProxyHttpServlet.kt (98%) create mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionListServlet.kt rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/SessionSettingsServlet.kt (85%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/UsageServlet.kt (88%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/UserInfoServlet.kt (52%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/UserSettingsServlet.kt (86%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/WelcomeServlet.kt (87%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/servlet/ZipServlet.kt (84%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{util => webui/session}/MutableSessionHandler.kt (88%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/session/SessionMessage.kt (64%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/session/SocketManager.kt (66%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/session/SocketManagerBase.kt (90%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/test/CodingActorTestApp.kt (64%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/test/ParsedActorTestApp.kt (58%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/test/SimpleActorTestApp.kt (62%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/util/ClasspathResource.kt (98%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/util/EmbeddingVisualizer.kt (83%) rename webui/src/main/kotlin/com/simiacryptus/skyenet/{ => webui}/util/MarkdownUtil.kt (94%) rename webui/src/main/resources/{simpleSession => application}/chat.css (94%) rename webui/src/main/resources/{simpleSession => application}/chat.js (96%) rename webui/src/main/resources/{simpleSession => application}/favicon.svg (99%) rename webui/src/main/resources/{simpleSession => application}/index.html (97%) rename webui/src/main/resources/{simpleSession => application}/main.js (97%) rename webui/src/test/kotlin/com/simiacryptus/skyenet/{ => webui}/ActorTestAppServer.kt (65%) diff --git a/README.md b/README.md index 8442a3a8..7858c7ee 100644 --- a/README.md +++ b/README.md @@ -76,18 +76,18 @@ Maven: com.simiacryptus skyenet-webui - 1.0.36 + 1.0.37 ``` Gradle: ```groovy -implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.36' +implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.37' ``` ```kotlin -implementation("com.simiacryptus:skyenet:1.0.36") +implementation("com.simiacryptus:skyenet:1.0.37") ``` ### 🌟 To Use diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 653536d1..97fb7303 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -31,7 +31,7 @@ val logback_version = "1.4.11" dependencies { - implementation(group = "com.simiacryptus", name = "joe-penai", version = "1.0.33") + implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.34") 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/core/src/main/java/com/simiacryptus/skyenet/OutputInterceptor.java b/core/src/main/java/com/simiacryptus/skyenet/core/OutputInterceptor.java similarity index 96% rename from core/src/main/java/com/simiacryptus/skyenet/OutputInterceptor.java rename to core/src/main/java/com/simiacryptus/skyenet/core/OutputInterceptor.java index 6fe7ef38..1dac9ad2 100644 --- a/core/src/main/java/com/simiacryptus/skyenet/OutputInterceptor.java +++ b/core/src/main/java/com/simiacryptus/skyenet/core/OutputInterceptor.java @@ -1,111 +1,111 @@ -package com.simiacryptus.skyenet; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - -public class OutputInterceptor { - - private OutputInterceptor() { - // Prevent instantiation of the utility class - } - - private static final PrintStream originalOut = System.out; - private static final PrintStream originalErr = System.err; - private static final AtomicBoolean isSetup = new AtomicBoolean(false); - private static final Object globalStreamLock = new Object(); - - public static void setupInterceptor() { - if (isSetup.getAndSet(true)) return; - System.setOut(new PrintStream(new OutputStreamRouter(originalOut))); - System.setErr(new PrintStream(new OutputStreamRouter(originalErr))); - } - - private static final ByteArrayOutputStream globalStream = new ByteArrayOutputStream(); - - private static final Map threadLocalBuffer = new WeakHashMap<>(); - - private static ByteArrayOutputStream getThreadOutputStream() { - Thread currentThread = Thread.currentThread(); - ByteArrayOutputStream outputStream; - synchronized (threadLocalBuffer) { - if ((outputStream = threadLocalBuffer.get(currentThread)) != null) return outputStream; - outputStream = new ByteArrayOutputStream(); - threadLocalBuffer.put(currentThread, outputStream); - } - return outputStream; - } - - public static String getThreadOutput() { - ByteArrayOutputStream outputStream = getThreadOutputStream(); - try { - outputStream.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return outputStream.toString(); - } - - public static void clearThreadOutput() { - getThreadOutputStream().reset(); - } - - public static String getGlobalOutput() { - synchronized (globalStreamLock) { - return globalStream.toString(); - } - } - - public static void clearGlobalOutput() { - synchronized (globalStreamLock) { - globalStream.reset(); - } - } - - private static class OutputStreamRouter extends ByteArrayOutputStream { - private final PrintStream originalStream; - int maxGlobalBuffer = 8 * 1024 * 1024; - int maxThreadBuffer = 1024 * 1024; - - public OutputStreamRouter(PrintStream originalStream) { - this.originalStream = originalStream; - } - - @Override - public void write(int b) { - originalStream.write(b); - synchronized (globalStreamLock) { - if (globalStream.size() > maxGlobalBuffer) { - globalStream.reset(); - } - globalStream.write(b); - } - ByteArrayOutputStream threadOutputStream = getThreadOutputStream(); - if (threadOutputStream.size() > maxThreadBuffer) { - threadOutputStream.reset(); - } - threadOutputStream.write(b); - } - - @Override - public void write(byte[] b, int off, int len) { - originalStream.write(b, off, len); - synchronized (globalStreamLock) { - if (globalStream.size() > maxGlobalBuffer) { - globalStream.reset(); - } - globalStream.write(b, off, len); - } - ByteArrayOutputStream threadOutputStream = getThreadOutputStream(); - if (threadOutputStream.size() > maxThreadBuffer) { - threadOutputStream.reset(); - } - threadOutputStream.write(b, off, len); - } - } -} - - +package com.simiacryptus.skyenet.core; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +public class OutputInterceptor { + + private OutputInterceptor() { + // Prevent instantiation of the utility class + } + + private static final PrintStream originalOut = System.out; + private static final PrintStream originalErr = System.err; + private static final AtomicBoolean isSetup = new AtomicBoolean(false); + private static final Object globalStreamLock = new Object(); + + public static void setupInterceptor() { + if (isSetup.getAndSet(true)) return; + System.setOut(new PrintStream(new OutputStreamRouter(originalOut))); + System.setErr(new PrintStream(new OutputStreamRouter(originalErr))); + } + + private static final ByteArrayOutputStream globalStream = new ByteArrayOutputStream(); + + private static final Map threadLocalBuffer = new WeakHashMap<>(); + + private static ByteArrayOutputStream getThreadOutputStream() { + Thread currentThread = Thread.currentThread(); + ByteArrayOutputStream outputStream; + synchronized (threadLocalBuffer) { + if ((outputStream = threadLocalBuffer.get(currentThread)) != null) return outputStream; + outputStream = new ByteArrayOutputStream(); + threadLocalBuffer.put(currentThread, outputStream); + } + return outputStream; + } + + public static String getThreadOutput() { + ByteArrayOutputStream outputStream = getThreadOutputStream(); + try { + outputStream.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return outputStream.toString(); + } + + public static void clearThreadOutput() { + getThreadOutputStream().reset(); + } + + public static String getGlobalOutput() { + synchronized (globalStreamLock) { + return globalStream.toString(); + } + } + + public static void clearGlobalOutput() { + synchronized (globalStreamLock) { + globalStream.reset(); + } + } + + private static class OutputStreamRouter extends ByteArrayOutputStream { + private final PrintStream originalStream; + int maxGlobalBuffer = 8 * 1024 * 1024; + int maxThreadBuffer = 1024 * 1024; + + public OutputStreamRouter(PrintStream originalStream) { + this.originalStream = originalStream; + } + + @Override + public void write(int b) { + originalStream.write(b); + synchronized (globalStreamLock) { + if (globalStream.size() > maxGlobalBuffer) { + globalStream.reset(); + } + globalStream.write(b); + } + ByteArrayOutputStream threadOutputStream = getThreadOutputStream(); + if (threadOutputStream.size() > maxThreadBuffer) { + threadOutputStream.reset(); + } + threadOutputStream.write(b); + } + + @Override + public void write(byte[] b, int off, int len) { + originalStream.write(b, off, len); + synchronized (globalStreamLock) { + if (globalStream.size() > maxGlobalBuffer) { + globalStream.reset(); + } + globalStream.write(b, off, len); + } + ByteArrayOutputStream threadOutputStream = getThreadOutputStream(); + if (threadOutputStream.size() > maxThreadBuffer) { + threadOutputStream.reset(); + } + threadOutputStream.write(b, off, len); + } + } +} + + diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt deleted file mode 100644 index 6eb601cd..00000000 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.simiacryptus.skyenet.actors - -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.OpenAIClientBase.Companion.toContentList -import com.simiacryptus.openai.models.OpenAITextModel - -abstract class BaseActor( - open val prompt: String, - val name: String? = null, - val model: OpenAITextModel = ChatModels.GPT35Turbo, - val temperature: Double = 0.3, -) { - abstract fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): T - open fun response(vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel = this.model, api: OpenAIAPI) = (api as OpenAIClient).chat( - OpenAIClient.ChatRequest( - messages = ArrayList(messages.toList()), - temperature = temperature, - model = this.model.modelName, - ), - model = this.model - ) - open fun answer(vararg questions: String, api: OpenAIAPI): T = answer(*chatMessages(*questions), api = api) - - open fun chatMessages(vararg questions: String) = arrayOf( - OpenAIClient.ChatMessage( - role = OpenAIClient.Role.system, - content = prompt.toContentList() - ), - ) + questions.map { - OpenAIClient.ChatMessage( - role = OpenAIClient.Role.user, - content = it.toContentList() - ) - } - -} \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt deleted file mode 100644 index 825143a4..00000000 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.simiacryptus.skyenet.actors - -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.models.OpenAITextModel - -open class SimpleActor( - prompt: String, - name: String? = null, - model: OpenAITextModel = ChatModels.GPT35Turbo, - temperature: Double = 0.3, -) : BaseActor( - prompt = prompt, - name = name, - model = model, - temperature = temperature, -) { - - override fun answer(vararg questions: String, api: OpenAIAPI): String = answer(*chatMessages(*questions), api = api) - - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): String = response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response") -} diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/Brain.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Brain.kt similarity index 92% rename from core/src/main/kotlin/com/simiacryptus/skyenet/Brain.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/Brain.kt index 0e026ef4..dcf10300 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/Brain.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Brain.kt @@ -1,216 +1,216 @@ -@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") - -package com.simiacryptus.skyenet - -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.OpenAIClient.* -import com.simiacryptus.openai.OpenAIClientBase.Companion.toContentList -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.util.JsonUtil.toJson -import com.simiacryptus.util.describe.TypeDescriber -import com.simiacryptus.util.describe.YamlDescriber -import org.intellij.lang.annotations.Language -import java.lang.reflect.Method -import java.lang.reflect.Modifier -import java.util.concurrent.atomic.AtomicInteger - -open class Brain( - val api: OpenAIClient, - val symbols: java.util.Map = java.util.HashMap() as java.util.Map, - val model: OpenAITextModel = ChatModels.GPT35Turbo, - private val verbose: Boolean = false, - val temperature: Double = 0.3, - val describer: TypeDescriber = YamlDescriber(), - val language: String = "Kotlin", - private val moderated: Boolean = true, - private val apiDescription: String = apiDescription(symbols, describer), -) { - private val totalInputLength = AtomicInteger(0) - private val totalOutputLength = AtomicInteger(0) - private val totalApiDescriptionLength: AtomicInteger = AtomicInteger(0) - - open fun implement(vararg prompt: String): String { - if (verbose) log.info("Prompt: \n\t" + prompt.joinToString("\n\t")) - return implement(*(getChatSystemMessages(apiDescription) + - prompt.map { ChatMessage(Role.user, it.toContentList()) }).toTypedArray() - ) - } - - fun implement( - vararg messages: ChatMessage - ): String { - var request = ChatRequest() - request = request.copy(messages = ArrayList(messages.toList())) - totalApiDescriptionLength.addAndGet(apiDescription.length) - return chat(request) - } - - @Language("TEXT") - open fun getChatSystemMessages(apiDescription: String): List = listOf( - ChatMessage( - Role.system, """ - |You will translate natural language instructions into - |an implementation using $language and the script context. - |Use ``` code blocks labeled with $language where appropriate. - |Defined symbols include ${symbols.keySet().joinToString(", ")}. - |The runtime context is described below: - | - |$apiDescription - |""".trimMargin().trim().toContentList() - ) - ) - - fun fixCommand( - previousCode: String, - error: Throwable, - output: String, - vararg promptMessages: ChatMessage - ): Pair>> { - val request = ChatRequest( - messages = ArrayList( - promptMessages.toList() + listOf( - ChatMessage( - Role.assistant, - """ - |```${language.lowercase()} - |${previousCode} - |``` - |""".trimMargin().trim().toContentList() - ), - ChatMessage( - Role.system, - """ - |The previous code failed with the following error: - | - |``` - |${error.message?.trim() ?: ""} - |``` - | - |Output: - |``` - |${output.trim()} - |``` - | - |Correct the code and try again. - |""".trimMargin().trim().toContentList() - ) - )) - ) - totalApiDescriptionLength.addAndGet(apiDescription.length) - val response = chat(request) - val codeBlocks = extractCodeBlocks(response) - return Pair(response, codeBlocks) - } - - private fun chat(_request: ChatRequest): String { - val request = _request.copy(model = model.modelName, temperature = temperature) - val json = toJson(request) - if (moderated) api.moderate(json) - totalInputLength.addAndGet(json.length) - val chatResponse = api.chat(request, model) - var response = chatResponse.choices.first().message?.content.orEmpty() - if (verbose) log.info(response) - totalOutputLength.addAndGet(response.length) - response = response.trim() - return response - } - - companion object { - private val log = org.slf4j.LoggerFactory.getLogger(Brain::class.java) - fun String.indent(indent: String = " ") = this.replace("\n", "\n$indent") - private fun joinYamlList(typeDescriptions: List) = typeDescriptions.joinToString("\n") { - "- " + it.indent() - } - - private fun Method.superMethod(): Method? { - val superMethod = declaringClass.superclasses.flatMap { it.methods.toList() } - .find { it.name == name && it.parameters.size == parameters.size } - return superMethod?.superMethod() ?: superMethod - } - - private val Class.superclasses: List> - get() { - val superclass = superclass - val supers = if (superclass == null) listOf() - else superclass.superclasses + listOf(superclass) - return (interfaces.toList() + supers).distinct() - } - - fun apiDescription(hands: java.util.Map, yamlDescriber: TypeDescriber): String { - val types = ArrayList>() - - val apiobjs = hands.entrySet().map { (name, utilityObj) -> - val clazz = Class.forName(utilityObj.javaClass.typeName) - val methods = clazz.methods - .filter { Modifier.isPublic(it.modifiers) } - .filter { it.declaringClass == clazz } - .filter { !it.isSynthetic } - .map { it.superMethod() ?: it } - .filter { it.declaringClass != Object::class.java } - types.addAll(methods.flatMap { (listOf(it.returnType) + it.parameters.map { it.type }).filter { it != clazz } }) - types.addAll(clazz.declaredClasses.filter { Modifier.isPublic(it.modifiers) }) - """ - |$name: - | operations: - | ${joinYamlList(methods.map { yamlDescriber.describe(it) }).indent().indent()} - |""".trimMargin().trim() - }.toTypedArray() - val typeDescriptions = types - .filter { !it.isPrimitive } - .filter { !it.isSynthetic } - .filter { !it.name.startsWith("java.") } - .filter { !setOf("void").contains(it.name) } - .distinct().map { - """ - |${it.simpleName}: - | ${yamlDescriber.describe(it).indent()} - """.trimMargin().trim() - }.toTypedArray() - return """ - |api_objects: - | ${apiobjs.joinToString("\n").indent()} - |components: - | schemas: - | ${typeDescriptions.joinToString("\n").indent().indent()} - """.trimMargin() - } - - fun extractCodeBlocks(response: String): List> { - val codeBlockRegex = Regex("(?s)```(.*?)\\n(.*?)```") - val languageRegex = Regex("([a-zA-Z0-9-_]+)") - - val result = mutableListOf>() - var startIndex = 0 - - val matches = codeBlockRegex.findAll(response) - if (matches.count() == 0) return listOf(Pair("text", response)) - for (match in matches) { - // Add non-code block before the current match as "text" - if (startIndex < match.range.first) { - result.add(Pair("text", response.substring(startIndex, match.range.first))) - } - - // Extract language and code - val languageMatch = languageRegex.find(match.groupValues[1]) - val language = languageMatch?.groupValues?.get(0) ?: "code" - val code = match.groupValues[2] - - // Add code block to the result - result.add(Pair(language, code)) - - // Update the start index - startIndex = match.range.last + 1 - } - - // Add any remaining non-code text after the last code block as "text" - if (startIndex < response.length) { - result.add(Pair("text", response.substring(startIndex))) - } - - return result - } - - } - +@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") + +package com.simiacryptus.skyenet.core + +import com.simiacryptus.jopenai.ApiModel.* +import com.simiacryptus.jopenai.ClientUtil.toContentList +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.describe.TypeDescriber +import com.simiacryptus.jopenai.describe.YamlDescriber +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.jopenai.util.JsonUtil.toJson +import org.intellij.lang.annotations.Language +import java.lang.reflect.Method +import java.lang.reflect.Modifier +import java.util.concurrent.atomic.AtomicInteger + +open class Brain( + val api: OpenAIClient, + val symbols: java.util.Map = java.util.HashMap() as java.util.Map, + val model: OpenAITextModel = ChatModels.GPT35Turbo, + private val verbose: Boolean = false, + val temperature: Double = 0.3, + val describer: TypeDescriber = YamlDescriber(), + val language: String = "Kotlin", + private val moderated: Boolean = true, + private val apiDescription: String = apiDescription(symbols, describer), +) { + private val totalInputLength = AtomicInteger(0) + private val totalOutputLength = AtomicInteger(0) + private val totalApiDescriptionLength: AtomicInteger = AtomicInteger(0) + + open fun implement(vararg prompt: String): String { + if (verbose) log.info("Prompt: \n\t" + prompt.joinToString("\n\t")) + return implement(*(getChatSystemMessages(apiDescription) + + prompt.map { ChatMessage(Role.user, it.toContentList()) }).toTypedArray() + ) + } + + fun implement( + vararg messages: ChatMessage + ): String { + var request = ChatRequest() + request = request.copy(messages = ArrayList(messages.toList())) + totalApiDescriptionLength.addAndGet(apiDescription.length) + return chat(request) + } + + @Language("TEXT") + open fun getChatSystemMessages(apiDescription: String): List = listOf( + ChatMessage( + Role.system, """ + |You will translate natural language instructions into + |an implementation using $language and the script context. + |Use ``` code blocks labeled with $language where appropriate. + |Defined symbols include ${symbols.keySet().joinToString(", ")}. + |The runtime context is described below: + | + |$apiDescription + |""".trimMargin().trim().toContentList() + ) + ) + + fun fixCommand( + previousCode: String, + error: Throwable, + output: String, + vararg promptMessages: ChatMessage + ): Pair>> { + val request = ChatRequest( + messages = ArrayList( + promptMessages.toList() + listOf( + ChatMessage( + Role.assistant, + """ + |```${language.lowercase()} + |${previousCode} + |``` + |""".trimMargin().trim().toContentList() + ), + ChatMessage( + Role.system, + """ + |The previous code failed with the following error: + | + |``` + |${error.message?.trim() ?: ""} + |``` + | + |Output: + |``` + |${output.trim()} + |``` + | + |Correct the code and try again. + |""".trimMargin().trim().toContentList() + ) + )) + ) + totalApiDescriptionLength.addAndGet(apiDescription.length) + val response = chat(request) + val codeBlocks = extractCodeBlocks(response) + return Pair(response, codeBlocks) + } + + private fun chat(_request: ChatRequest): String { + val request = _request.copy(model = model.modelName, temperature = temperature) + val json = toJson(request) + if (moderated) api.moderate(json) + totalInputLength.addAndGet(json.length) + val chatResponse = api.chat(request, model) + var response = chatResponse.choices.first().message?.content.orEmpty() + if (verbose) log.info(response) + totalOutputLength.addAndGet(response.length) + response = response.trim() + return response + } + + companion object { + private val log = org.slf4j.LoggerFactory.getLogger(Brain::class.java) + fun String.indent(indent: String = " ") = this.replace("\n", "\n$indent") + private fun joinYamlList(typeDescriptions: List) = typeDescriptions.joinToString("\n") { + "- " + it.indent() + } + + private fun Method.superMethod(): Method? { + val superMethod = declaringClass.superclasses.flatMap { it.methods.toList() } + .find { it.name == name && it.parameters.size == parameters.size } + return superMethod?.superMethod() ?: superMethod + } + + private val Class.superclasses: List> + get() { + val superclass = superclass + val supers = if (superclass == null) listOf() + else superclass.superclasses + listOf(superclass) + return (interfaces.toList() + supers).distinct() + } + + fun apiDescription(hands: java.util.Map, yamlDescriber: TypeDescriber): String { + val types = ArrayList>() + + val apiobjs = hands.entrySet().map { (name, utilityObj) -> + val clazz = Class.forName(utilityObj.javaClass.typeName) + val methods = clazz.methods + .filter { Modifier.isPublic(it.modifiers) } + .filter { it.declaringClass == clazz } + .filter { !it.isSynthetic } + .map { it.superMethod() ?: it } + .filter { it.declaringClass != Object::class.java } + types.addAll(methods.flatMap { (listOf(it.returnType) + it.parameters.map { it.type }).filter { it != clazz } }) + types.addAll(clazz.declaredClasses.filter { Modifier.isPublic(it.modifiers) }) + """ + |$name: + | operations: + | ${joinYamlList(methods.map { yamlDescriber.describe(it) }).indent().indent()} + |""".trimMargin().trim() + }.toTypedArray() + val typeDescriptions = types + .filter { !it.isPrimitive } + .filter { !it.isSynthetic } + .filter { !it.name.startsWith("java.") } + .filter { !setOf("void").contains(it.name) } + .distinct().map { + """ + |${it.simpleName}: + | ${yamlDescriber.describe(it).indent()} + """.trimMargin().trim() + }.toTypedArray() + return """ + |api_objects: + | ${apiobjs.joinToString("\n").indent()} + |components: + | schemas: + | ${typeDescriptions.joinToString("\n").indent().indent()} + """.trimMargin() + } + + fun extractCodeBlocks(response: String): List> { + val codeBlockRegex = Regex("(?s)```(.*?)\\n(.*?)```") + val languageRegex = Regex("([a-zA-Z0-9-_]+)") + + val result = mutableListOf>() + var startIndex = 0 + + val matches = codeBlockRegex.findAll(response) + if (matches.count() == 0) return listOf(Pair("text", response)) + for (match in matches) { + // Add non-code block before the current match as "text" + if (startIndex < match.range.first) { + result.add(Pair("text", response.substring(startIndex, match.range.first))) + } + + // Extract language and code + val languageMatch = languageRegex.find(match.groupValues[1]) + val language = languageMatch?.groupValues?.get(0) ?: "code" + val code = match.groupValues[2] + + // Add code block to the result + result.add(Pair(language, code)) + + // Update the start index + startIndex = match.range.last + 1 + } + + // Add any remaining non-code text after the last code block as "text" + if (startIndex < response.length) { + result.add(Pair("text", response.substring(startIndex))) + } + + return result + } + + } + } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/Ears.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Ears.kt similarity index 92% rename from core/src/main/kotlin/com/simiacryptus/skyenet/Ears.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/Ears.kt index 6b671950..680b455b 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/Ears.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Ears.kt @@ -1,10 +1,10 @@ -package com.simiacryptus.skyenet +package com.simiacryptus.skyenet.core -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.proxy.ChatProxy -import com.simiacryptus.util.audio.AudioRecorder -import com.simiacryptus.util.audio.LookbackLoudnessWindowBuffer -import com.simiacryptus.util.audio.TranscriptionProcessor +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.audio.AudioRecorder +import com.simiacryptus.jopenai.audio.LookbackLoudnessWindowBuffer +import com.simiacryptus.jopenai.audio.TranscriptionProcessor +import com.simiacryptus.jopenai.proxy.ChatProxy import org.slf4j.LoggerFactory import java.util.* import java.util.concurrent.ConcurrentLinkedDeque diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/Heart.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Heart.kt similarity index 94% rename from core/src/main/kotlin/com/simiacryptus/skyenet/Heart.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/Heart.kt index 21713d03..68877dc4 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/Heart.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Heart.kt @@ -1,40 +1,40 @@ -package com.simiacryptus.skyenet - -interface Heart { - - fun getLanguage(): String - fun run(code: String): Any? - fun validate(code: String): Throwable? - - fun wrapCode(code: String): String = code - fun wrapExecution(fn: java.util.function.Supplier): T? = fn.get() - - companion object { - private class TestObject { - @Suppress("unused") - fun square(x: Int): Int = x * x - } - private interface TestInterface { - fun square(x: Int): Int - } - @JvmStatic - fun test(factory: java.util.function.Function, Heart>) { - val testImpl = object : TestInterface { - override fun square(x: Int): Int = x * x - } - with(factory.apply(mapOf("message" to "hello"))) { - test("hello", run("message")) - } - with(factory.apply(mapOf("function" to TestObject()))) { - test(25, run("function.square(5)")) - } - with(factory.apply(mapOf("function" to testImpl))) { - test(25, run("function.square(5)")) - } - } - - private fun test(expected: T, actual: T?) { - require(expected == actual) { actual.toString() } - } - } +package com.simiacryptus.skyenet.core + +interface Heart { + + fun getLanguage(): String + fun run(code: String): Any? + fun validate(code: String): Throwable? + + fun wrapCode(code: String): String = code + fun wrapExecution(fn: java.util.function.Supplier): T? = fn.get() + + companion object { + private class TestObject { + @Suppress("unused") + fun square(x: Int): Int = x * x + } + private interface TestInterface { + fun square(x: Int): Int + } + @JvmStatic + fun test(factory: java.util.function.Function, Heart>) { + val testImpl = object : TestInterface { + override fun square(x: Int): Int = x * x + } + with(factory.apply(mapOf("message" to "hello"))) { + test("hello", run("message")) + } + with(factory.apply(mapOf("function" to TestObject()))) { + test(25, run("function.square(5)")) + } + with(factory.apply(mapOf("function" to testImpl))) { + test(25, run("function.square(5)")) + } + } + + private fun test(expected: T, actual: T?) { + require(expected == actual) { actual.toString() } + } + } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/Mouth.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Mouth.kt similarity index 98% rename from core/src/main/kotlin/com/simiacryptus/skyenet/Mouth.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/Mouth.kt index 4218ea99..e1b9d6d9 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/Mouth.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/Mouth.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet +package com.simiacryptus.skyenet.core import com.google.auth.oauth2.GoogleCredentials import com.google.cloud.texttospeech.v1.* diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ActorSystem.kt similarity index 63% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ActorSystem.kt index a579f63c..6bd1a647 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ActorSystem.kt @@ -1,16 +1,18 @@ -package com.simiacryptus.skyenet.actors +package com.simiacryptus.skyenet.core.actors -import com.simiacryptus.skyenet.actors.record.* -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.util.FunctionWrapper -import com.simiacryptus.skyenet.util.JsonFunctionRecorder +import com.simiacryptus.skyenet.core.actors.record.CodingActorInterceptor +import com.simiacryptus.skyenet.core.actors.record.ParsedActorInterceptor +import com.simiacryptus.skyenet.core.actors.record.SimpleActorInterceptor +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.core.util.FunctionWrapper +import com.simiacryptus.skyenet.core.util.JsonFunctionRecorder import java.io.File open class ActorSystem>( private val actors: Map>, - dataStorage: DataStorage, + val dataStorage: DataStorage, val userId: User?, val sessionId: Session ) { diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/BaseActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/BaseActor.kt new file mode 100644 index 00000000..c3785710 --- /dev/null +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/BaseActor.kt @@ -0,0 +1,39 @@ +package com.simiacryptus.skyenet.core.actors + +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.ClientUtil.toContentList +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAIModel +import com.simiacryptus.jopenai.models.OpenAITextModel + +abstract class BaseActor( + open val prompt: String, + val name: String? = null, + val model: OpenAITextModel = ChatModels.GPT35Turbo, + val temperature: Double = 0.3, +) { + abstract fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): T + open fun response(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, model: OpenAIModel = this.model, api: API) = (api as OpenAIClient).chat( + com.simiacryptus.jopenai.ApiModel.ChatRequest( + messages = ArrayList(messages.toList()), + temperature = temperature, + model = this.model.modelName, + ), + model = this.model + ) + open fun answer(vararg questions: String, api: API): T = answer(*chatMessages(*questions), api = api) + + open fun chatMessages(vararg questions: String) = arrayOf( + com.simiacryptus.jopenai.ApiModel.ChatMessage( + role = com.simiacryptus.jopenai.ApiModel.Role.system, + content = prompt.toContentList() + ), + ) + questions.map { + com.simiacryptus.jopenai.ApiModel.ChatMessage( + role = com.simiacryptus.jopenai.ApiModel.Role.user, + content = it.toContentList() + ) + } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/CodingActor.kt similarity index 87% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/CodingActor.kt index f8b8e1bf..943cbff0 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/CodingActor.kt @@ -1,17 +1,17 @@ -package com.simiacryptus.skyenet.actors +package com.simiacryptus.skyenet.core.actors import com.fasterxml.jackson.annotation.JsonIgnore -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.OpenAIClientBase.Companion.toContentList -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.skyenet.Brain -import com.simiacryptus.skyenet.Brain.Companion.indent -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.OutputInterceptor -import com.simiacryptus.util.describe.AbbrevWhitelistYamlDescriber -import com.simiacryptus.util.describe.TypeDescriber +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.ClientUtil.toContentList +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.describe.AbbrevWhitelistYamlDescriber +import com.simiacryptus.jopenai.describe.TypeDescriber +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.skyenet.core.Brain +import com.simiacryptus.skyenet.core.Brain.Companion.indent +import com.simiacryptus.skyenet.core.Heart +import com.simiacryptus.skyenet.core.OutputInterceptor import kotlin.reflect.KClass @Suppress("unused", "MemberVisibilityCanBePrivate") @@ -67,31 +67,31 @@ open class CodingActor( open val interpreter by lazy { interpreterClass.java.getConstructor(Map::class.java).newInstance(symbols) } - override fun answer(vararg questions: String, api: OpenAIAPI): CodeResult = + override fun answer(vararg questions: String, api: API): CodeResult = if (!autoEvaluate) answer(*chatMessages(*questions), api = api) else answerWithAutoEval(*chatMessages(*questions), api = api).first - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): CodeResult = + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): CodeResult = if (!autoEvaluate) CodeResultImpl(*messages, api = (api as OpenAIClient)) else answerWithAutoEval(*messages, api = api).first open fun answerWithPrefix( codePrefix: String, - vararg messages: OpenAIClient.ChatMessage, - api: OpenAIAPI + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, + api: API ): CodeResult = if (!autoEvaluate) CodeResultImpl(*injectCodePrefix(messages, codePrefix), api = (api as OpenAIClient)) else answerWithAutoEval(*injectCodePrefix(messages, codePrefix), api = api).first open fun answerWithAutoEval( vararg messages: String, - api: OpenAIAPI, + api: API, codePrefix: String = "" ) = answerWithAutoEval(*injectCodePrefix(chatMessages(*messages), codePrefix), api = api) open fun answerWithAutoEval( - vararg messages: OpenAIClient.ChatMessage, - api: OpenAIAPI + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, + api: API ): Pair { var result = CodeResultImpl(*messages, api = (api as OpenAIClient)) var lastError: Throwable? = null @@ -117,18 +117,18 @@ open class CodingActor( } private fun injectCodePrefix( - messages: Array, + messages: Array, codePrefix: String ) = (messages.dropLast(1) + if (codePrefix.isBlank()) listOf() else listOf( - OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, codePrefix.toContentList()) + com.simiacryptus.jopenai.ApiModel.ChatMessage(com.simiacryptus.jopenai.ApiModel.Role.assistant, codePrefix.toContentList()) ) + messages.last()).toTypedArray() private fun fix( api: OpenAIClient, - messages: Array, - result: CodingActor.CodeResultImpl, + messages: Array, + result: CodeResultImpl, ex: Throwable - ): CodingActor.CodeResultImpl { + ): CodeResultImpl { val respondWithCode = brain(api, model).fixCommand(result.getCode(), ex, "", *messages) val renderedResponse = getRenderedResponse(respondWithCode.second) val codedInstruction = getCode(interpreter.getLanguage(), respondWithCode.second) @@ -147,7 +147,7 @@ open class CodingActor( ) private inner class CodeResultImpl( - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, codePrefix: String = "", api: OpenAIClient, ) : CodeResult { @@ -175,7 +175,7 @@ open class CodingActor( fun implement( brain: Brain, - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, codePrefix: String = "", ): String { val response = brain.implement(*messages) @@ -194,7 +194,7 @@ open class CodingActor( brain: Brain, codePrefix: String, initialCode: String, - messages: Array + messages: Array ): String? { var workingCode = initialCode for (fixAttempt in 0..fixIterations) { diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedActor.kt similarity index 67% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedActor.kt index 1ac6097b..85449fb9 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedActor.kt @@ -1,10 +1,10 @@ -package com.simiacryptus.skyenet.actors +package com.simiacryptus.skyenet.core.actors -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.openai.proxy.ChatProxy +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.jopenai.proxy.ChatProxy import java.util.function.Function open class ParsedActor( @@ -21,7 +21,7 @@ open class ParsedActor( ) { val resultClass: Class by lazy { parserClass.getMethod("apply", String::class.java).returnType as Class } - private inner class ParsedResponseImpl(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI) : ParsedResponse(resultClass) { + private inner class ParsedResponseImpl(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API) : ParsedResponse(resultClass) { private val parser: Function = ChatProxy( clazz = parserClass, api = (api as OpenAIClient), @@ -34,7 +34,7 @@ open class ParsedActor( override fun getObj(clazz: Class): T = _obj } - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): ParsedResponse { + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): ParsedResponse { return ParsedResponseImpl(*messages, api = api) } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedResponse.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedResponse.kt similarity index 79% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedResponse.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedResponse.kt index fb19ebc8..a3eef2ae 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedResponse.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/ParsedResponse.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.actors +package com.simiacryptus.skyenet.core.actors abstract class ParsedResponse(val clazz: Class) { abstract fun getText(): String diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/SimpleActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/SimpleActor.kt new file mode 100644 index 00000000..cb4b786e --- /dev/null +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/SimpleActor.kt @@ -0,0 +1,22 @@ +package com.simiacryptus.skyenet.core.actors + +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel + +open class SimpleActor( + prompt: String, + name: String? = null, + model: OpenAITextModel = ChatModels.GPT35Turbo, + temperature: Double = 0.3, +) : BaseActor( + prompt = prompt, + name = name, + model = model, + temperature = temperature, +) { + + override fun answer(vararg questions: String, api: API): String = answer(*chatMessages(*questions), api = api) + + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): String = response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response") +} diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/ActorOptimization.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/ActorOptimization.kt similarity index 93% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/ActorOptimization.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/ActorOptimization.kt index 49eb36aa..da515d3b 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/ActorOptimization.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/ActorOptimization.kt @@ -1,13 +1,12 @@ -package com.simiacryptus.skyenet.actors.opt - -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.skyenet.actors.opt.ActorOptimization.GeneticApi.Prompt -import com.simiacryptus.openai.proxy.ChatProxy -import com.simiacryptus.skyenet.actors.BaseActor -import com.simiacryptus.util.describe.Description +package com.simiacryptus.skyenet.core.actors.opt + +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.describe.Description +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.jopenai.proxy.ChatProxy +import com.simiacryptus.skyenet.core.actors.BaseActor +import com.simiacryptus.skyenet.core.actors.opt.ActorOptimization.GeneticApi.Prompt import org.slf4j.LoggerFactory import kotlin.math.ceil import kotlin.math.ln diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/Expectation.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/Expectation.kt similarity index 88% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/Expectation.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/Expectation.kt index 6e4e6ef6..655f039d 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/opt/Expectation.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/opt/Expectation.kt @@ -1,9 +1,8 @@ -package com.simiacryptus.skyenet.actors.opt +package com.simiacryptus.skyenet.core.actors.opt -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.EmbeddingModels -import com.simiacryptus.openai.opt.DistanceType +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.EmbeddingModels +import com.simiacryptus.jopenai.opt.DistanceType import org.slf4j.LoggerFactory abstract class Expectation { @@ -30,7 +29,7 @@ abstract class Expectation { } private fun createEmbedding(api: OpenAIClient, str: String) = api.createEmbedding( - OpenAIClient.EmbeddingRequest( + com.simiacryptus.jopenai.ApiModel.EmbeddingRequest( model = EmbeddingModels.AdaEmbedding.modelName, input = str ) ).data.first().embedding!! diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/CodingActorInterceptor.kt similarity index 65% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/CodingActorInterceptor.kt index ea52e26d..975f83e2 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/CodingActorInterceptor.kt @@ -1,11 +1,11 @@ -package com.simiacryptus.skyenet.actors.record +package com.simiacryptus.skyenet.core.actors.record -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.skyenet.actors.CodeResult -import com.simiacryptus.skyenet.actors.CodingActor -import com.simiacryptus.skyenet.util.FunctionWrapper +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.OpenAIModel +import com.simiacryptus.skyenet.core.actors.CodeResult +import com.simiacryptus.skyenet.core.actors.CodingActor +import com.simiacryptus.skyenet.core.util.FunctionWrapper class CodingActorInterceptor( val inner: CodingActor, @@ -21,15 +21,15 @@ class CodingActorInterceptor( temperature = inner.temperature, autoEvaluate = inner.autoEvaluate, ) { - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): CodeResult { + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): CodeResult { return functionInterceptor.wrap(messages.toList().toTypedArray()) { - messages: Array -> + messages: Array -> CodingResultInterceptor(*messages, api = (api as OpenAIClient), inner = inner.answer(*messages, api = api)) } } private inner class CodingResultInterceptor( - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, private val inner: CodeResult, api: OpenAIClient, ) : CodeResult { @@ -40,11 +40,11 @@ class CodingActorInterceptor( } override fun response( - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, model: OpenAIModel, - api: OpenAIAPI + api: API ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { - messages: Array, + messages: Array, model: OpenAIModel -> inner.response(*messages, model = model, api = api) } @@ -53,23 +53,23 @@ class CodingActorInterceptor( inner.chatMessages(*it) } - override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: API) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } override fun answerWithPrefix( codePrefix: String, - vararg messages: OpenAIClient.ChatMessage, - api: OpenAIAPI + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, + api: API ) = functionInterceptor.wrap(messages.toList().toTypedArray(), codePrefix) { - messages: Array, + messages: Array, codePrefix: String -> inner.answerWithPrefix(codePrefix, *messages, api = api) } override fun answerWithAutoEval( vararg messages: String, - api: OpenAIAPI, + api: API, codePrefix: String ) = functionInterceptor.wrap(messages.toList().toTypedArray(), codePrefix) { messages: Array, @@ -78,8 +78,8 @@ class CodingActorInterceptor( } override fun answerWithAutoEval( - vararg messages: OpenAIClient.ChatMessage, - api: OpenAIAPI + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, + api: API ) = functionInterceptor.wrap(messages.toList().toTypedArray()) { inner.answerWithAutoEval(*messages, api = api) } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/ParsedActorInterceptor.kt similarity index 59% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/ParsedActorInterceptor.kt index d3619907..004f223a 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/ParsedActorInterceptor.kt @@ -1,11 +1,10 @@ -package com.simiacryptus.skyenet.actors.record +package com.simiacryptus.skyenet.core.actors.record -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.skyenet.actors.ParsedActor -import com.simiacryptus.skyenet.actors.ParsedResponse -import com.simiacryptus.skyenet.util.FunctionWrapper +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.models.OpenAIModel +import com.simiacryptus.skyenet.core.actors.ParsedActor +import com.simiacryptus.skyenet.core.actors.ParsedResponse +import com.simiacryptus.skyenet.core.util.FunctionWrapper class ParsedActorInterceptor( val inner: ParsedActor, @@ -17,30 +16,30 @@ class ParsedActorInterceptor( model = inner.model, temperature = inner.temperature, ) { - private inner class ParsedResponseInterceptor(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI, private val inner: ParsedResponse) : + private inner class ParsedResponseInterceptor(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API, private val inner: ParsedResponse) : ParsedResponse(this@ParsedActorInterceptor.inner.resultClass) { override fun getText() = functionInterceptor.wrap { inner.getText() } override fun getObj(clazz: Class) = functionInterceptor.intercept(clazz) { inner.getObj(clazz) } // <-- Cannot use 'T' as reified type parameter. Use a class instead. } - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): ParsedResponse { + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API): ParsedResponse { return functionInterceptor.wrap(messages.toList().toTypedArray()) { - messages: Array -> + messages: Array -> ParsedResponseInterceptor(*messages, api = api, inner = inner.answer(*messages, api = api)) } } override fun response( - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, model: OpenAIModel, - api: OpenAIAPI + api: API ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { - messages: Array, + messages: Array, model: OpenAIModel -> inner.response(*messages, model = model, api = api) } - override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: API) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/SimpleActorInterceptor.kt similarity index 53% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/SimpleActorInterceptor.kt index 4e90f18e..dca8af85 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/record/SimpleActorInterceptor.kt @@ -1,10 +1,9 @@ -package com.simiacryptus.skyenet.actors.record +package com.simiacryptus.skyenet.core.actors.record -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.skyenet.actors.SimpleActor -import com.simiacryptus.skyenet.util.FunctionWrapper +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.models.OpenAIModel +import com.simiacryptus.skyenet.core.actors.SimpleActor +import com.simiacryptus.skyenet.core.util.FunctionWrapper class SimpleActorInterceptor( val inner: SimpleActor, @@ -16,18 +15,18 @@ class SimpleActorInterceptor( temperature = inner.temperature, ) { - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI) = + override fun answer(vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, api: API) = functionInterceptor.wrap(messages.toList().toTypedArray()) { - messages: Array -> + messages: Array -> inner.answer(*messages, api = api) } override fun response( - vararg messages: OpenAIClient.ChatMessage, + vararg messages: com.simiacryptus.jopenai.ApiModel.ChatMessage, model: OpenAIModel, - api: OpenAIAPI + api: API ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { - messages: Array, + messages: Array, model: OpenAIModel -> inner.response(*messages, model = model, api = api) } @@ -36,7 +35,7 @@ class SimpleActorInterceptor( inner.chatMessages(*it) } - override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: API) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ActorTestBase.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ActorTestBase.kt similarity index 87% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ActorTestBase.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ActorTestBase.kt index 2475b24e..d1182000 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ActorTestBase.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ActorTestBase.kt @@ -1,8 +1,8 @@ -package com.simiacryptus.skyenet.actors.test +package com.simiacryptus.skyenet.core.actors.test -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.skyenet.actors.BaseActor -import com.simiacryptus.skyenet.actors.opt.ActorOptimization +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.skyenet.core.actors.BaseActor +import com.simiacryptus.skyenet.core.actors.opt.ActorOptimization import org.slf4j.LoggerFactory import org.slf4j.event.Level diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/CodingActorTestBase.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/CodingActorTestBase.kt similarity index 65% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/CodingActorTestBase.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/CodingActorTestBase.kt index 33392132..41c6cdba 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/CodingActorTestBase.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/CodingActorTestBase.kt @@ -1,9 +1,9 @@ -package com.simiacryptus.skyenet.actors.test +package com.simiacryptus.skyenet.core.actors.test -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.actors.BaseActor -import com.simiacryptus.skyenet.actors.CodeResult -import com.simiacryptus.skyenet.actors.CodingActor +import com.simiacryptus.skyenet.core.Heart +import com.simiacryptus.skyenet.core.actors.BaseActor +import com.simiacryptus.skyenet.core.actors.CodeResult +import com.simiacryptus.skyenet.core.actors.CodingActor import kotlin.reflect.KClass abstract class CodingActorTestBase : ActorTestBase() { diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ParsedActorTestBase.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ParsedActorTestBase.kt similarity index 68% rename from core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ParsedActorTestBase.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ParsedActorTestBase.kt index f271fd7d..a6ed1558 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/test/ParsedActorTestBase.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/actors/test/ParsedActorTestBase.kt @@ -1,8 +1,8 @@ -package com.simiacryptus.skyenet.actors.test +package com.simiacryptus.skyenet.core.actors.test -import com.simiacryptus.skyenet.actors.BaseActor -import com.simiacryptus.skyenet.actors.ParsedActor -import com.simiacryptus.skyenet.actors.ParsedResponse +import com.simiacryptus.skyenet.core.actors.BaseActor +import com.simiacryptus.skyenet.core.actors.ParsedActor +import com.simiacryptus.skyenet.core.actors.ParsedResponse import java.util.function.Function abstract class ParsedActorTestBase( diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/ApplicationServices.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ApplicationServices.kt similarity index 83% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/ApplicationServices.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ApplicationServices.kt index 3ae1357e..7fdd863d 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/ApplicationServices.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ApplicationServices.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform import java.io.File @@ -33,5 +33,10 @@ object ApplicationServices { require(!isLocked) { "ApplicationServices is locked" } field = value } + var clientManager: ClientManager = ClientManager() + set(value) { + require(!isLocked) { "ApplicationServices is locked" } + field = value + } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthenticationManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthenticationManager.kt similarity index 86% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthenticationManager.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthenticationManager.kt index 7c3df51f..6ff7b109 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthenticationManager.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthenticationManager.kt @@ -1,6 +1,4 @@ -package com.simiacryptus.skyenet.platform - -import java.util.HashMap +package com.simiacryptus.skyenet.core.platform open class AuthenticationManager { diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthorizationManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthorizationManager.kt similarity index 97% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthorizationManager.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthorizationManager.kt index a89723e8..0e5d8b58 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/AuthorizationManager.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/AuthorizationManager.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform import java.util.* diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ClientManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ClientManager.kt new file mode 100644 index 00000000..398fdb41 --- /dev/null +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/ClientManager.kt @@ -0,0 +1,50 @@ +package com.simiacryptus.skyenet.core.platform + +import com.simiacryptus.jopenai.ApiModel +import com.simiacryptus.jopenai.ClientUtil +import com.simiacryptus.jopenai.OpenAIClient + +import com.simiacryptus.jopenai.models.OpenAIModel +import org.slf4j.event.Level +import java.io.File + +open class ClientManager { + + open fun createClient( + session: Session, + user: User?, + dataStorage: DataStorage, + ): OpenAIClient { + if (user != null) { + val userSettings = ApplicationServices.userSettingsManager.getUserSettings(user) + val logfile = dataStorage.getSessionDir(user, session).resolve(".sys/openai.log") + logfile.parentFile?.mkdirs() + val userApi = createClient(session, user, logfile, userSettings.apiKey) + if (userApi != null) return userApi + } + val canUseGlobalKey = ApplicationServices.authorizationManager.isAuthorized( + null, user, AuthorizationManager.OperationType.GlobalKey + ) + if (!canUseGlobalKey) throw RuntimeException("No API key") + val logfile = dataStorage.getSessionDir(user, session).resolve(".sys/openai.log") + logfile.parentFile?.mkdirs() + return createClient(session, user, logfile)!! + } + + protected open fun createClient( + session: Session, user: User?, logfile: File, key: String? = ClientUtil.keyTxt + ): OpenAIClient? = if (key.isNullOrBlank()) null else object : OpenAIClient( + key = key, + logLevel = Level.DEBUG, + logStreams = mutableListOf( + logfile.outputStream()?.buffered() + ).filterNotNull().toMutableList(), + ) { + override fun incrementTokens(model: OpenAIModel?, tokens: ApiModel.Usage) { + ApplicationServices.usageManager.incrementUsage(session, user, model!!, tokens) + super.incrementTokens(model, tokens) + } + } + + private val log = org.slf4j.LoggerFactory.getLogger(ClientManager::class.java) +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/DataStorage.kt similarity index 78% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/DataStorage.kt index e966adf5..18f52c75 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/DataStorage.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil import java.io.File import java.util.* @@ -77,25 +77,7 @@ open class DataStorage( session: Session ): String { validateSessionId(session) - val userMessage = File(this.getSessionDir(user, session), MESSAGE_DIR).listFiles() - ?.filter { file -> file.isFile } - ?.sortedBy { file -> file.lastModified() } - ?.map { messageFile -> - val fileText = messageFile.readText() - val split = fileText.split("

") - if (split.size < 2) { - log.debug("Session {}: No messages", session) - "" - } else { - val stringList = split[1].split("

") - if (stringList.isEmpty()) { - log.debug("Session {}: No messages", session) - "" - } else { - stringList.first() - } - } - }?.firstOrNull { it.isNotEmpty() } + val userMessage = messages(user, session).entries.minByOrNull { it.key.lastModified() }?.value return if (null != userMessage) { log.debug("Session {}: {}", session, userMessage) userMessage @@ -105,6 +87,42 @@ open class DataStorage( } } + open fun getSessionTime( + user: User?, + session: Session + ): Date? { + validateSessionId(session) + val file = messages(user, session).entries.minByOrNull { it.key.lastModified() }?.key + return if (null != file) { + Date(file.lastModified()) + } else { + log.debug("Session {}: No messages", session) + null + } + } + + private fun messages( + user: User?, + session: Session + ) = File(this.getSessionDir(user, session), MESSAGE_DIR).listFiles() + ?.filter { file -> file.isFile } + ?.map { messageFile -> + val fileText = messageFile.readText() + val split = fileText.split("

") + if (split.size < 2) { + log.debug("Session {}: No messages", session) + messageFile to "" + } else { + val stringList = split[1].split("

") + if (stringList.isEmpty()) { + log.debug("Session {}: No messages", session) + messageFile to "" + } else { + messageFile to stringList.first() + } + } + }?.filter { it.second.isNotEmpty() }?.toList()?.toMap() ?: mapOf() + open fun listSessions( user: User? ): List { @@ -146,9 +164,9 @@ open class DataStorage( val listFiles = operationDir.listFiles()?.filter { it.isFile && !it.name.startsWith("aaa") } (listFiles?.size ?: 0) > 0 } - } - log.debug("Sessions: {}", files?.map { it.parentFile.name + "-" + it.name }) - return files?.map { it.parentFile.name + "-" + it.name } ?: listOf() + }?.sortedBy { it.lastModified() } ?: listOf() + log.debug("Sessions: {}", files.map { it.parentFile.name + "-" + it.name }) + return files.map { it.parentFile.name + "-" + it.name } } private fun userRoot(user: User?) = File( diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/Session.kt similarity index 53% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/Session.kt index 871f7645..ec2e1bce 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/Session.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform -import com.simiacryptus.skyenet.platform.DataStorage.Companion.validateSessionId +import com.simiacryptus.skyenet.core.platform.DataStorage.Companion.validateSessionId data class Session( internal val sessionId: String diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UsageManager.kt similarity index 89% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UsageManager.kt index 99c663c5..a51147f2 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UsageManager.kt @@ -1,8 +1,7 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.* -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.models.* +import com.simiacryptus.jopenai.util.JsonUtil import java.io.File import java.io.FileWriter import java.util.concurrent.ConcurrentHashMap @@ -44,14 +43,14 @@ open class UsageManager { Session(sessionId), User(email=user), modelEnum, - OpenAIClient.Usage(prompt_tokens = tokens.toInt()) + com.simiacryptus.jopenai.ApiModel.Usage(prompt_tokens = tokens.toInt()) ) "output" -> incrementUsage( Session(sessionId), User(email=user), modelEnum, - OpenAIClient.Usage(completion_tokens = tokens.toInt()) + com.simiacryptus.jopenai.ApiModel.Usage(completion_tokens = tokens.toInt()) ) else -> throw RuntimeException("Unknown direction $direction") @@ -108,7 +107,7 @@ open class UsageManager { File(".skyenet/usage/counters.json").writeText(JsonUtil.toJson(usagePerSession)) } - open fun incrementUsage(session: Session, user: User?, model: OpenAIModel, tokens: OpenAIClient.Usage) { + open fun incrementUsage(session: Session, user: User?, model: OpenAIModel, tokens: com.simiacryptus.jopenai.ApiModel.Usage) { @Suppress("NAME_SHADOWING") val user = if (null == user) null else User(email = user.email) // Hack usagePerSession.computeIfAbsent(session) { UsageCounters() } .tokensPerModel.computeIfAbsent(UsageKey(session, user, model)) { UsageValues() } @@ -130,7 +129,7 @@ open class UsageManager { } } - open fun getUserUsageSummary(user: User): Map { + open fun getUserUsageSummary(user: User): Map { @Suppress("NAME_SHADOWING") val user = if(null == user) null else User(email= user.email) // Hack return sessionsByUser[user]?.flatMap { sessionId -> val usage = usagePerSession[sessionId] @@ -139,7 +138,7 @@ open class UsageManager { } ?: emptyList() }?.groupBy { it.first }?.mapValues { it.value.map { it.second }.reduce { a, b -> - OpenAIClient.Usage( + com.simiacryptus.jopenai.ApiModel.Usage( prompt_tokens = a.prompt_tokens + b.prompt_tokens, completion_tokens = a.completion_tokens + b.completion_tokens ) @@ -147,11 +146,11 @@ open class UsageManager { } ?: emptyMap() } - open fun getSessionUsageSummary(session: Session): Map = + open fun getSessionUsageSummary(session: Session): Map = usagePerSession[session]?.tokensPerModel?.entries?.map { (model, counter) -> model.model to counter.toUsage() }?.groupBy { it.first }?.mapValues { it.value.map { it.second }.reduce { a, b -> - OpenAIClient.Usage( + com.simiacryptus.jopenai.ApiModel.Usage( prompt_tokens = a.prompt_tokens + b.prompt_tokens, completion_tokens = a.completion_tokens + b.completion_tokens ) @@ -167,12 +166,12 @@ open class UsageManager { val inputTokens: AtomicInteger = AtomicInteger(), val outputTokens: AtomicInteger = AtomicInteger(), ) { - fun addAndGet(tokens: OpenAIClient.Usage) { + fun addAndGet(tokens: com.simiacryptus.jopenai.ApiModel.Usage) { inputTokens.addAndGet(tokens.prompt_tokens) outputTokens.addAndGet(tokens.completion_tokens) } - fun toUsage() = OpenAIClient.Usage( + fun toUsage() = com.simiacryptus.jopenai.ApiModel.Usage( prompt_tokens = inputTokens.get(), completion_tokens = outputTokens.get() ) diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/User.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/User.kt new file mode 100644 index 00000000..a4dfeb9a --- /dev/null +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/User.kt @@ -0,0 +1,27 @@ +package com.simiacryptus.skyenet.core.platform + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.annotation.JsonProperty + +data class User( + @get:JsonProperty("email") internal val email: String, + @get:JsonProperty("name") internal val name: String? = null, + @get:JsonProperty("id") internal val id: String? = null, + @get:JsonProperty("picture") internal val picture: String? = null, +) { + override fun toString() = email + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as User + + return email == other.email + } + + override fun hashCode(): Int { + return email.hashCode() + } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UserSettingsManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UserSettingsManager.kt similarity index 80% rename from core/src/main/kotlin/com/simiacryptus/skyenet/platform/UserSettingsManager.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UserSettingsManager.kt index e15a8054..47423e07 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UserSettingsManager.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/platform/UserSettingsManager.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.platform +package com.simiacryptus.skyenet.core.platform -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil import java.io.File open class UserSettingsManager { @@ -15,10 +15,10 @@ open class UserSettingsManager { return userSettings.getOrPut(user) { val file = File(userConfigDirectory, "$user.json") if (file.exists()) { - Companion.log.info("Loading user settings for $user from $file") + log.info("Loading user settings for $user from $file") JsonUtil.fromJson(file.readText(), UserSettings::class.java) } else { - Companion.log.info("Creating new user settings for $user at $file") + log.info("Creating new user settings for $user at $file") UserSettings() } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/util/AwsUtil.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/AwsUtil.kt similarity index 97% rename from core/src/main/kotlin/com/simiacryptus/skyenet/util/AwsUtil.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/util/AwsUtil.kt index 1e068cdc..67c5505a 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/util/AwsUtil.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/AwsUtil.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.core.util import com.amazonaws.services.kms.AWSKMSClientBuilder import com.amazonaws.services.kms.model.DecryptRequest diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/FunctionWrapper.kt similarity index 97% rename from core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/util/FunctionWrapper.kt index 1bbfe387..ba0d3c3c 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/FunctionWrapper.kt @@ -1,8 +1,8 @@ @file:Suppress("unused") -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.core.util -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil import java.io.Closeable import java.io.File import java.util.concurrent.atomic.AtomicInteger diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/util/HeartTestBase.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/HeartTestBase.kt similarity index 97% rename from core/src/main/kotlin/com/simiacryptus/skyenet/util/HeartTestBase.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/util/HeartTestBase.kt index a0a4209c..9c5cf44d 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/util/HeartTestBase.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/HeartTestBase.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.core.util -import com.simiacryptus.skyenet.Heart +import com.simiacryptus.skyenet.core.Heart import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/util/LoggingInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/LoggingInterceptor.kt similarity index 98% rename from core/src/main/kotlin/com/simiacryptus/skyenet/util/LoggingInterceptor.kt rename to core/src/main/kotlin/com/simiacryptus/skyenet/core/util/LoggingInterceptor.kt index f7bd634e..37310c00 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/util/LoggingInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/core/util/LoggingInterceptor.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.core.util import ch.qos.logback.classic.Logger import ch.qos.logback.classic.LoggerContext diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt deleted file mode 100644 index 1b2d4d8a..00000000 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.simiacryptus.skyenet.platform - -data class User( - internal val email: String, - internal val name: String? = null, - internal val id: String? = null, - internal val picture: String? = null, -) { - override fun toString() = email - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as User - - return email == other.email - } - - override fun hashCode(): Int { - return email.hashCode() - } - -} \ No newline at end of file diff --git a/core/src/test/java/com/simiacryptus/skyenet/DataStorageTest.kt b/core/src/test/java/com/simiacryptus/skyenet/core/DataStorageTest.kt similarity index 91% rename from core/src/test/java/com/simiacryptus/skyenet/DataStorageTest.kt rename to core/src/test/java/com/simiacryptus/skyenet/core/DataStorageTest.kt index 3e663e4e..b9e2d228 100644 --- a/core/src/test/java/com/simiacryptus/skyenet/DataStorageTest.kt +++ b/core/src/test/java/com/simiacryptus/skyenet/core/DataStorageTest.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet +package com.simiacryptus.skyenet.core -import com.simiacryptus.skyenet.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.DataStorage import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue diff --git a/core/src/test/java/com/simiacryptus/skyenet/OutputInterceptorThreadedTest.java b/core/src/test/java/com/simiacryptus/skyenet/core/OutputInterceptorThreadedTest.java similarity index 95% rename from core/src/test/java/com/simiacryptus/skyenet/OutputInterceptorThreadedTest.java rename to core/src/test/java/com/simiacryptus/skyenet/core/OutputInterceptorThreadedTest.java index 2ae5bd5d..85e451cc 100644 --- a/core/src/test/java/com/simiacryptus/skyenet/OutputInterceptorThreadedTest.java +++ b/core/src/test/java/com/simiacryptus/skyenet/core/OutputInterceptorThreadedTest.java @@ -1,52 +1,52 @@ -package com.simiacryptus.skyenet; - -import org.junit.jupiter.api.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class OutputInterceptorThreadedTest { - - @Test - public void testThreadedInterceptor() throws InterruptedException { - OutputInterceptor.setupInterceptor(); - AtomicInteger successCounter = new AtomicInteger(0); - ExecutorService executorService = Executors.newFixedThreadPool(5); - Object lock = new Object(); - Runnable task = () -> { - OutputInterceptor.clearThreadOutput(); - String threadName = Thread.currentThread().getName(); - System.out.println("Thread: " + threadName + " output"); - System.err.println("Thread: " + threadName + " error"); - try { - Thread.sleep(1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - String expectedOutput = ("Thread: " + threadName + " output\nThread: " + threadName + " error\n").trim(); - String threadOutput = OutputInterceptor.getThreadOutput().replace("\r", "").trim(); - if (threadOutput.trim().equals(expectedOutput.trim())) { - successCounter.incrementAndGet(); - } else { - synchronized (lock) { - System.out.println("Expected:\n " + expectedOutput.replaceAll("\n", "\n ")); - System.out.println("Actual:\n " + threadOutput.replaceAll("\n", "\n ")); - System.out.flush(); - } - } - }; - - for (int i = 0; i < 10; i++) { - executorService.submit(task); - } - - executorService.shutdown(); - executorService.awaitTermination(10, TimeUnit.SECONDS); - - assertEquals(10, successCounter.get()); - } -} +package com.simiacryptus.skyenet.core; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class OutputInterceptorThreadedTest { + + @Test + public void testThreadedInterceptor() throws InterruptedException { + OutputInterceptor.setupInterceptor(); + AtomicInteger successCounter = new AtomicInteger(0); + ExecutorService executorService = Executors.newFixedThreadPool(5); + Object lock = new Object(); + Runnable task = () -> { + OutputInterceptor.clearThreadOutput(); + String threadName = Thread.currentThread().getName(); + System.out.println("Thread: " + threadName + " output"); + System.err.println("Thread: " + threadName + " error"); + try { + Thread.sleep(1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + String expectedOutput = ("Thread: " + threadName + " output\nThread: " + threadName + " error\n").trim(); + String threadOutput = OutputInterceptor.getThreadOutput().replace("\r", "").trim(); + if (threadOutput.trim().equals(expectedOutput.trim())) { + successCounter.incrementAndGet(); + } else { + synchronized (lock) { + System.out.println("Expected:\n " + expectedOutput.replaceAll("\n", "\n ")); + System.out.println("Actual:\n " + threadOutput.replaceAll("\n", "\n ")); + System.out.flush(); + } + } + }; + + for (int i = 0; i < 10; i++) { + executorService.submit(task); + } + + executorService.shutdown(); + executorService.awaitTermination(10, TimeUnit.SECONDS); + + assertEquals(10, successCounter.get()); + } +} diff --git a/webui/src/test/kotlin/com/simiacryptus/skyenet/ActorOptTest.kt b/core/src/test/java/com/simiacryptus/skyenet/core/actors/ActorOptTest.kt similarity index 91% rename from webui/src/test/kotlin/com/simiacryptus/skyenet/ActorOptTest.kt rename to core/src/test/java/com/simiacryptus/skyenet/core/actors/ActorOptTest.kt index eba9a7b3..81dc424d 100644 --- a/webui/src/test/kotlin/com/simiacryptus/skyenet/ActorOptTest.kt +++ b/core/src/test/java/com/simiacryptus/skyenet/core/actors/ActorOptTest.kt @@ -1,9 +1,8 @@ -package com.simiacryptus.skyenet +package com.simiacryptus.skyenet.core.actors -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.skyenet.actors.SimpleActor -import com.simiacryptus.skyenet.actors.opt.ActorOptimization -import com.simiacryptus.skyenet.actors.opt.Expectation +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.skyenet.core.actors.opt.ActorOptimization +import com.simiacryptus.skyenet.core.actors.opt.Expectation import org.slf4j.LoggerFactory import org.slf4j.event.Level import kotlin.system.exitProcess diff --git a/gradle.properties b/gradle.properties index 536076d2..4ab4ef01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Gradle Releases -> https://github.com/gradle/gradle/releases libraryGroup = com.simiacryptus.skyenet -libraryVersion = 1.0.36 +libraryVersion = 1.0.37 gradleVersion = 7.6.1 # Opt-out flag for bundling Kotlin standard library -> https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library diff --git a/groovy/src/main/kotlin/com/simiacryptus/skyenet/heart/GroovyInterpreter.kt b/groovy/src/main/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreter.kt similarity index 89% rename from groovy/src/main/kotlin/com/simiacryptus/skyenet/heart/GroovyInterpreter.kt rename to groovy/src/main/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreter.kt index 9e51d5f2..1b897667 100644 --- a/groovy/src/main/kotlin/com/simiacryptus/skyenet/heart/GroovyInterpreter.kt +++ b/groovy/src/main/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreter.kt @@ -1,43 +1,43 @@ -package com.simiacryptus.skyenet.heart - -import com.simiacryptus.skyenet.Heart -import groovy.lang.GroovyShell -import groovy.lang.Script -import org.codehaus.groovy.control.CompilationFailedException -import org.codehaus.groovy.control.CompilerConfiguration - -open class GroovyInterpreter(defs: java.util.Map) : Heart { - - private val shell: GroovyShell - - init { - val compilerConfiguration = CompilerConfiguration() - shell = GroovyShell(compilerConfiguration) - defs.forEach { key, value -> - shell.setVariable(key, value) - } - } - - override fun getLanguage(): String { - return "groovy" - } - - - override fun run(code: String): Any? { - val wrapExecution = wrapExecution { - try { - val script: Script = shell.parse(wrapCode(code)) - script.run() - } catch (e: CompilationFailedException) { - throw e - } - } - return wrapExecution - } - - override fun validate(code: String): Exception? { - shell.parse(wrapCode(code)) - return null - } -} - +package com.simiacryptus.skyenet.groovy + +import com.simiacryptus.skyenet.core.Heart +import groovy.lang.GroovyShell +import groovy.lang.Script +import org.codehaus.groovy.control.CompilationFailedException +import org.codehaus.groovy.control.CompilerConfiguration + +open class GroovyInterpreter(defs: java.util.Map) : Heart { + + private val shell: GroovyShell + + init { + val compilerConfiguration = CompilerConfiguration() + shell = GroovyShell(compilerConfiguration) + defs.forEach { key, value -> + shell.setVariable(key, value) + } + } + + override fun getLanguage(): String { + return "groovy" + } + + + override fun run(code: String): Any? { + val wrapExecution = wrapExecution { + try { + val script: Script = shell.parse(wrapCode(code)) + script.run() + } catch (e: CompilationFailedException) { + throw e + } + } + return wrapExecution + } + + override fun validate(code: String): Exception? { + shell.parse(wrapCode(code)) + return null + } +} + diff --git a/groovy/src/test/kotlin/com/simiacryptus/skyenet/GroovyInterpreterTest.kt b/groovy/src/test/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreterTest.kt similarity index 56% rename from groovy/src/test/kotlin/com/simiacryptus/skyenet/GroovyInterpreterTest.kt rename to groovy/src/test/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreterTest.kt index e394f18f..a2e38cdc 100644 --- a/groovy/src/test/kotlin/com/simiacryptus/skyenet/GroovyInterpreterTest.kt +++ b/groovy/src/test/kotlin/com/simiacryptus/skyenet/groovy/GroovyInterpreterTest.kt @@ -1,9 +1,8 @@ @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") -package com.simiacryptus.skyenet.heart.test +package com.simiacryptus.skyenet.groovy -import com.simiacryptus.skyenet.util.HeartTestBase -import com.simiacryptus.skyenet.heart.GroovyInterpreter +import com.simiacryptus.skyenet.core.util.HeartTestBase class GroovyInterpreterTest : HeartTestBase() { override fun newInterpreter(map: java.util.Map) = GroovyInterpreter(map) diff --git a/java/build.gradle.kts b/java/build.gradle.kts deleted file mode 100644 index 973244a3..00000000 --- a/java/build.gradle.kts +++ /dev/null @@ -1,153 +0,0 @@ -import org.gradle.api.tasks.testing.logging.TestLogEvent -import java.net.URI - -fun properties(key: String) = project.findProperty(key).toString() -group = properties("libraryGroup") -version = properties("libraryVersion") - -plugins { - java - `java-library` - id("org.jetbrains.kotlin.jvm") version "1.9.20" - `maven-publish` - id("signing") -} - -repositories { - mavenCentral { - metadataSources { - mavenPom() - artifact() - } - } -} - -kotlin { - jvmToolchain(11) -} - -val kotlin_version = "1.9.20" -dependencies { - - implementation(project(":core")) - - implementation(group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version = "1.7.3") - implementation(kotlin("stdlib-jdk8")) - - implementation(group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version = kotlin_version) - implementation(group = "org.slf4j", name = "slf4j-api", version = "2.0.9") - implementation(group = "commons-io", name = "commons-io", version = "2.15.0") - - testImplementation(group = "org.junit.jupiter", name = "junit-jupiter-api", version = "5.10.1") - testRuntimeOnly(group = "org.junit.jupiter", name = "junit-jupiter-engine", version = "5.10.1") - testImplementation(group = "org.jetbrains.kotlin", name = "kotlin-script-runtime", version = kotlin_version) - -} - -tasks { - - compileKotlin { - kotlinOptions { - javaParameters = true - } - } - compileTestKotlin { - kotlinOptions { - javaParameters = true - } - } - test { - useJUnitPlatform() - systemProperty("surefire.useManifestOnlyJar", "false") - testLogging { - events(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) - exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - } - jvmArgs( - "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", - "--add-opens", "java.base/java.util=ALL-UNNAMED", - "--add-opens", "java.base/java.lang=ALL-UNNAMED" - ) - } -} - - - -val javadocJar by tasks.registering(Jar::class) { - archiveClassifier.set("javadoc") - from(tasks.javadoc) -} - -val sourcesJar by tasks.registering(Jar::class) { - archiveClassifier.set("sources") - from(sourceSets.main.get().allSource) -} - -publishing { - - publications { - create("mavenJava") { - artifactId = "java" - from(components["java"]) - artifact(sourcesJar.get()) - artifact(javadocJar.get()) - versionMapping { - usage("java-api") { - fromResolutionOf("runtimeClasspath") - } - usage("java-runtime") { - fromResolutionResult() - } - } - pom { - name.set("SkyeNet Java Interpreter") - description.set("A very helpful puppy") - url.set("https://github.com/SimiaCryptus/SkyeNet") - licenses { - license { - name.set("The Apache License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - developers { - developer { - id.set("acharneski") - name.set("Andrew Charneski") - email.set("acharneski@gmail.com") - } - } - scm { - connection.set("scm:git:git://git@github.com/SimiaCryptus/SkyeNet.git") - developerConnection.set("scm:git:ssh://git@github.com/SimiaCryptus/SkyeNet.git") - url.set("https://github.com/SimiaCryptus/SkyeNet") - } - } - } - } - repositories { - maven { - val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - val snapshotsRepoUrl = "https://oss.sonatype.org/mask/repositories/snapshots" - url = URI(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl) - credentials { - username = System.getenv("OSSRH_USERNAME") ?: System.getProperty("ossrhUsername") - ?: properties("ossrhUsername") - password = System.getenv("OSSRH_PASSWORD") ?: System.getProperty("ossrhPassword") - ?: properties("ossrhPassword") - } - } - } - if (System.getenv("GPG_PRIVATE_KEY") != null && System.getenv("GPG_PASSPHRASE") != null) afterEvaluate { - signing { - sign(publications["mavenJava"]) - } - } -} - -if (System.getenv("GPG_PRIVATE_KEY") != null && System.getenv("GPG_PASSPHRASE") != null) { - apply() - configure { - useInMemoryPgpKeys(System.getenv("GPG_PRIVATE_KEY"), System.getenv("GPG_PASSPHRASE")) - sign(configurations.archives.get()) - } -} diff --git a/kotlin/src/main/kotlin/com/simiacryptus/skyenet/heart/KotlinInterpreter.kt b/kotlin/src/main/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreter.kt similarity index 99% rename from kotlin/src/main/kotlin/com/simiacryptus/skyenet/heart/KotlinInterpreter.kt rename to kotlin/src/main/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreter.kt index ac634bf5..edd94d26 100644 --- a/kotlin/src/main/kotlin/com/simiacryptus/skyenet/heart/KotlinInterpreter.kt +++ b/kotlin/src/main/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreter.kt @@ -1,8 +1,8 @@ @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") -package com.simiacryptus.skyenet.heart +package com.simiacryptus.skyenet.kotlin -import com.simiacryptus.skyenet.Heart +import com.simiacryptus.skyenet.core.Heart import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity diff --git a/kotlin/src/test/kotlin/com/simiacryptus/skyenet/KotlinInterpreterTest.kt b/kotlin/src/test/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreterTest.kt similarity index 90% rename from kotlin/src/test/kotlin/com/simiacryptus/skyenet/KotlinInterpreterTest.kt rename to kotlin/src/test/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreterTest.kt index 4f44a3cf..8272e748 100644 --- a/kotlin/src/test/kotlin/com/simiacryptus/skyenet/KotlinInterpreterTest.kt +++ b/kotlin/src/test/kotlin/com/simiacryptus/skyenet/kotlin/KotlinInterpreterTest.kt @@ -1,8 +1,8 @@ @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") -package com.simiacryptus.skyenet.heart +package com.simiacryptus.skyenet.kotlin -import com.simiacryptus.skyenet.util.HeartTestBase +import com.simiacryptus.skyenet.core.util.HeartTestBase import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import java.util.Map diff --git a/scala/src/main/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreter.scala b/scala/src/main/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreter.scala similarity index 97% rename from scala/src/main/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreter.scala rename to scala/src/main/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreter.scala index 2f00613c..535e47a7 100644 --- a/scala/src/main/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreter.scala +++ b/scala/src/main/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreter.scala @@ -1,7 +1,7 @@ -package com.simiacryptus.skyenet.heart +package com.simiacryptus.skyenet.scala -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.heart.ScalaLocalInterpreter.log +import com.simiacryptus.skyenet.core.Heart +import com.simiacryptus.skyenet.scala.ScalaLocalInterpreter.log import java.nio.file.Paths import java.util.function.Supplier diff --git a/scala/src/test/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreterTest.scala b/scala/src/test/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreterTest.scala similarity index 51% rename from scala/src/test/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreterTest.scala rename to scala/src/test/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreterTest.scala index f425c2a1..443afb6c 100644 --- a/scala/src/test/scala/com/simiacryptus/skyenet/heart/ScalaLocalInterpreterTest.scala +++ b/scala/src/test/scala/com/simiacryptus/skyenet/scala/ScalaLocalInterpreterTest.scala @@ -1,14 +1,13 @@ -package com.test - -import com.simiacryptus.skyenet.heart.ScalaLocalInterpreter -import com.simiacryptus.skyenet.Heart -import com.simiacryptus.skyenet.util.HeartTestBase - -import java.util - - -class ScalaLocalInterpreterTest extends HeartTestBase { - override def newInterpreter(map: util.Map[String, AnyRef]): Heart = { - new ScalaLocalInterpreter(map) - } -} +package com.simiacryptus.skyenet.scala + +import com.simiacryptus.skyenet.core.Heart +import com.simiacryptus.skyenet.core.util.HeartTestBase + +import java.util + + +class ScalaLocalInterpreterTest extends HeartTestBase { + override def newInterpreter(map: util.Map[String, AnyRef]): Heart = { + new ScalaLocalInterpreter(map) + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index cce729ee..ff8d96db 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,10 +2,9 @@ rootProject.name = "SkyeNet" include("core") include("groovy") -include("java") include("scala") include("kotlin") include("webui") //include("util") -//includeBuild("../joe-penai/") +//includeBuild("../jo-penai/") diff --git a/skyenet.svg b/skyenet.svg index c252e0ad..52fa3b90 100644 --- a/skyenet.svg +++ b/skyenet.svg @@ -1,10 +1,10 @@ -
${MarkdownUtil.renderMarkdown(userInterfacePrompt)}
""") - } - } - - protected val messages by lazy { - val list = listOf( - OpenAIClient.ChatMessage(OpenAIClient.Role.system, systemPrompt.toContentList()), - ).toMutableList() - if(initialAssistantPrompt.isNotBlank()) list += OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, initialAssistantPrompt.toContentList()) - list - } - - @Synchronized - override fun onRun(userMessage: String, socket: ChatSocket) { - var responseContents = divInitializer(cancelable = false) - responseContents += """
${renderResponse(userMessage)}
""" - send("""$responseContents
${ApplicationBase.spinner}
""") - val response = handleMessage(userMessage, responseContents) - if(null != response) { - responseContents += """
${renderResponse(response)}
""" - send(responseContents) - onResponse(response, responseContents) - } - } - - open fun handleMessage(userMessage: String, responseContents: String): String? { - messages += OpenAIClient.ChatMessage(OpenAIClient.Role.user, userMessage.toContentList()) - val response = getResponse() - messages += OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, response.toContentList()) - return response - } - - open fun getResponse() = api.chat(newChatRequest, model).choices.first().message?.content.orEmpty() - - open fun renderResponse(response: String) = """
${MarkdownUtil.renderMarkdown(response)}
""" - - open fun onResponse(response: String, responseContents: String) {} - - open val newChatRequest: OpenAIClient.ChatRequest - get() = OpenAIClient.ChatRequest( - messages = ArrayList(messages), - temperature = temperature, - model = model.modelName, - ) - -} \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt deleted file mode 100644 index da47032d..00000000 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.simiacryptus.skyenet.servlet - -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session -import jakarta.servlet.http.HttpServlet -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse - -class SessionListServlet( - private val dataStorage: DataStorage, - private val prefix: String -) : HttpServlet() { - override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { - resp.contentType = "text/html" - resp.status = HttpServletResponse.SC_OK - val sessions = dataStorage.listSessions(ApplicationServices.authenticationManager.getUser(req.getCookie())) - - resp.writer.write( - """ - - - Sessions - - - - - - - - ${sessions.joinToString("") { session -> - """ - - - - """.trimIndent() - }} -
Session Name
${sessionName(req, session)}
- - - """.trimIndent() - ) - } - - private fun sessionName(req: HttpServletRequest, session: Session) = dataStorage.getSessionName( - ApplicationServices.authenticationManager.getUser(req.getCookie()), session - ) -} \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationDirectory.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationDirectory.kt similarity index 86% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationDirectory.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationDirectory.kt index e355ffb3..882d2284 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationDirectory.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationDirectory.kt @@ -1,11 +1,12 @@ -package com.simiacryptus.skyenet +package com.simiacryptus.skyenet.webui.application -import com.simiacryptus.openai.OpenAIClientBase -import com.simiacryptus.skyenet.chat.ChatServer -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.servlet.* -import com.simiacryptus.skyenet.util.AwsUtil.decryptResource +import com.simiacryptus.jopenai.ClientUtil +import com.simiacryptus.skyenet.core.OutputInterceptor +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.util.AwsUtil.decryptResource +import com.simiacryptus.skyenet.webui.chat.ChatServer +import com.simiacryptus.skyenet.webui.servlet.* import jakarta.servlet.DispatcherType import jakarta.servlet.Servlet import org.eclipse.jetty.server.* @@ -28,7 +29,7 @@ abstract class ApplicationDirectory( ) { var domainName: String = "" // Resolved in _main private set - abstract val childWebApps: List + abstract val childWebApps: List data class ChildWebApp( val path: String, @@ -54,7 +55,7 @@ abstract class ApplicationDirectory( protected open fun _main(args: Array) { try { init(args.contains("--server")) - OpenAIClientBase.keyTxt = decryptResource("openai.key.kms", javaClass.classLoader) + ClientUtil.keyTxt = decryptResource("openai.key.kms", javaClass.classLoader) ApplicationServices.isLocked = true val welcomeContext = newWebAppContext("/", welcomeResources, welcomeServlet) val server = start( @@ -85,7 +86,7 @@ abstract class ApplicationDirectory( } } - open fun init(isServer: Boolean): ApplicationDirectory { + open fun init(isServer: Boolean): com.simiacryptus.skyenet.webui.application.ApplicationDirectory { OutputInterceptor.setupInterceptor() domainName = domainName(isServer) return this @@ -151,7 +152,7 @@ abstract class ApplicationDirectory( companion object { - private val log = LoggerFactory.getLogger(ApplicationDirectory::class.java) + private val log = LoggerFactory.getLogger(com.simiacryptus.skyenet.webui.application.ApplicationDirectory::class.java) } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt similarity index 83% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt index 8c2e49e2..3bb9419e 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationInterface.kt @@ -1,5 +1,6 @@ -package com.simiacryptus.skyenet.session +package com.simiacryptus.skyenet.webui.application +import com.simiacryptus.skyenet.webui.session.SessionMessage import java.util.function.Consumer class ApplicationInterface(private val inner: ApplicationSocketManager) { diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationServer.kt similarity index 73% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationServer.kt index 81077f9f..e87b2db5 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationServer.kt @@ -1,21 +1,17 @@ -package com.simiacryptus.skyenet - -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.skyenet.servlet.AppInfoServlet -import com.simiacryptus.skyenet.chat.ChatServer -import com.simiacryptus.skyenet.platform.ApplicationServices.authenticationManager -import com.simiacryptus.skyenet.platform.ApplicationServices.authorizationManager -import com.simiacryptus.skyenet.platform.ApplicationServices.dataStorageFactory -import com.simiacryptus.skyenet.servlet.* -import com.simiacryptus.skyenet.platform.AuthenticationManager.Companion.AUTH_COOKIE -import com.simiacryptus.skyenet.session.SessionMessage -import com.simiacryptus.skyenet.session.SocketManager -import com.simiacryptus.skyenet.platform.AuthorizationManager -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.session.ApplicationInterface -import com.simiacryptus.skyenet.session.ApplicationSocketManager +package com.simiacryptus.skyenet.webui.application + +import com.simiacryptus.jopenai.API +import com.simiacryptus.skyenet.core.platform.ApplicationServices.authenticationManager +import com.simiacryptus.skyenet.core.platform.ApplicationServices.authorizationManager +import com.simiacryptus.skyenet.core.platform.ApplicationServices.dataStorageFactory +import com.simiacryptus.skyenet.core.platform.AuthenticationManager.Companion.AUTH_COOKIE +import com.simiacryptus.skyenet.core.platform.AuthorizationManager +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.chat.ChatServer +import com.simiacryptus.skyenet.webui.servlet.* +import com.simiacryptus.skyenet.webui.session.SocketManager import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.eclipse.jetty.servlet.FilterHolder @@ -24,9 +20,9 @@ import org.eclipse.jetty.webapp.WebAppContext import org.slf4j.LoggerFactory import java.io.File -abstract class ApplicationBase( +abstract class ApplicationServer( final override val applicationName: String, - resourceBase: String = "simpleSession", + resourceBase: String = "application", val temperature: Double = 0.1, ) : ChatServer(resourceBase) { @@ -41,23 +37,21 @@ abstract class ApplicationBase( override fun newSession(user: User?, session: Session): SocketManager { return object : ApplicationSocketManager( session = session, - userId = user, + user = user, dataStorage = dataStorage, - applicationClass = this@ApplicationBase::class.java, + applicationClass = this@ApplicationServer::class.java, ) { override fun newSession( session: Session, user: User?, userMessage: String, socketManager: ApplicationSocketManager, - sessionMessage: SessionMessage, - api: OpenAIAPI - ) = this@ApplicationBase.newSession( + api: API + ) = this@ApplicationServer.newSession( session = session, user = user, userMessage = userMessage, - socketManager = socketManager.applicationInterface, - sessionMessage = sessionMessage, + ui = socketManager.applicationInterface, api = api ) } @@ -67,9 +61,8 @@ abstract class ApplicationBase( session: Session, user: User?, userMessage: String, - socketManager: ApplicationInterface, - sessionMessage: SessionMessage, - api: OpenAIAPI + ui: ApplicationInterface, + api: API ) open val settingsClass: Class<*> get() = Map::class.java @@ -97,7 +90,7 @@ abstract class ApplicationBase( FilterHolder { request, response, chain -> val user = authenticationManager.getUser((request as HttpServletRequest).getCookie()) val canRead = authorizationManager.isAuthorized( - applicationClass = this@ApplicationBase.javaClass, + applicationClass = this@ApplicationServer.javaClass, user = user, operationType = AuthorizationManager.OperationType.Read ) @@ -120,7 +113,7 @@ abstract class ApplicationBase( } companion object { - private val log = LoggerFactory.getLogger(ApplicationBase::class.java) + private val log = LoggerFactory.getLogger(ApplicationServer::class.java) val spinner = """
Loading...
""" diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationSocketManager.kt similarity index 74% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationSocketManager.kt index 4dc20b49..83585133 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/application/ApplicationSocketManager.kt @@ -1,22 +1,23 @@ -package com.simiacryptus.skyenet.session +package com.simiacryptus.skyenet.webui.application -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.chat.ChatSocket -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User +import com.simiacryptus.jopenai.API +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.chat.ChatSocket +import com.simiacryptus.skyenet.webui.session.SocketManagerBase import java.util.function.Consumer abstract class ApplicationSocketManager( session: Session, - userId: User?, + user: User?, dataStorage: DataStorage?, applicationClass: Class<*>, ) : SocketManagerBase( session = session, dataStorage = dataStorage, - userId = userId, + user = user, applicationClass = applicationClass, ) { private val threads = mutableMapOf() @@ -25,9 +26,14 @@ abstract class ApplicationSocketManager( override fun onRun(userMessage: String, socket: ChatSocket) { val operationID = randomID() - val sessionDiv = newMessage(operationID, spinner, true) threads[operationID] = Thread.currentThread() - newSession(session, user = userId, userMessage, this, sessionDiv, socket.api) + newSession( + session, user = user, userMessage, this, ApplicationServices.clientManager.createClient( + session, + user, + dataStorage ?: throw IllegalStateException("No data storage") + ) + ) } val applicationInterface by lazy { ApplicationInterface(this) } @@ -65,12 +71,11 @@ abstract class ApplicationSocketManager( user: User?, userMessage: String, socketManager: ApplicationSocketManager, - sessionMessage: SessionMessage, - api: OpenAIAPI + api: API ) companion object { - val spinner: String get() = """
${ApplicationBase.spinner}
""" + val spinner: String get() = """
${ApplicationServer.spinner}
""" // val playButton: String get() = """""" // val cancelButton: String get() = """""" // val regenButton: String get() = """""" diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatServer.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatServer.kt similarity index 66% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatServer.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatServer.kt index b3621438..0e2dffbe 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatServer.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatServer.kt @@ -1,10 +1,12 @@ -package com.simiacryptus.skyenet.chat +package com.simiacryptus.skyenet.webui.chat -import com.simiacryptus.skyenet.platform.* -import com.simiacryptus.skyenet.platform.ApplicationServices.authenticationManager -import com.simiacryptus.skyenet.platform.AuthenticationManager.Companion.AUTH_COOKIE -import com.simiacryptus.skyenet.servlet.NewSessionServlet -import com.simiacryptus.skyenet.session.SocketManager +import com.simiacryptus.skyenet.core.platform.ApplicationServices.authenticationManager +import com.simiacryptus.skyenet.core.platform.AuthenticationManager.Companion.AUTH_COOKIE +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.servlet.NewSessionServlet +import com.simiacryptus.skyenet.webui.session.SocketManager import org.eclipse.jetty.servlet.DefaultServlet import org.eclipse.jetty.servlet.ServletHolder import org.eclipse.jetty.util.resource.Resource @@ -23,32 +25,26 @@ abstract class ChatServer(val resourceBase: String) { override fun configure(factory: JettyWebSocketServletFactory) { factory.setCreator { req, resp -> try { - val authId = req.getCookie(AUTH_COOKIE) return@setCreator if (!req.parameterMap.containsKey("sessionId")) { - null + throw IllegalArgumentException("sessionId is required") } else { val session = Session(req.parameterMap["sessionId"]?.first()!!) - val sessionState: SocketManager = getSession(session, req) - val user = authenticationManager.getUser(authId) - ChatSocket(session, sessionState, dataStorage, user) + ChatSocket( + if (stateCache.containsKey(session)) { + stateCache[session]!! + } else { + val user = authenticationManager.getUser(req.getCookie(AUTH_COOKIE)) + val sessionState = newSession(user, session) + stateCache[session] = sessionState + sessionState + } + ) } } catch (e: Exception) { log.warn("Error configuring websocket", e) } } } - - private fun getSession( - session: Session, - req: JettyServerUpgradeRequest - ) = if (stateCache.containsKey(session)) { - stateCache[session]!! - } else { - val user = authenticationManager.getUser(req.getCookie(AUTH_COOKIE)) - val sessionState = newSession(user, session) - stateCache[session] = sessionState - sessionState - } } abstract fun newSession(user: User?, session: Session): SocketManager diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocket.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocket.kt new file mode 100644 index 00000000..dca9ba38 --- /dev/null +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocket.kt @@ -0,0 +1,40 @@ +package com.simiacryptus.skyenet.webui.chat + +import com.simiacryptus.skyenet.webui.session.SocketManager +import org.eclipse.jetty.websocket.api.Session +import org.eclipse.jetty.websocket.api.WebSocketAdapter + +class ChatSocket( + private val sessionState: SocketManager, +) : WebSocketAdapter() { + + + override fun onWebSocketConnect(session: Session) { + super.onWebSocketConnect(session) + log.debug("{} - Socket connected: {}", session, session.remote) + sessionState.addSocket(this) + sessionState.getReplay().forEach { + try { + remote.sendString(it) + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + override fun onWebSocketText(message: String) { + super.onWebSocketText(message) + sessionState.onWebSocketText(this, message) + } + + override fun onWebSocketClose(statusCode: Int, reason: String?) { + super.onWebSocketClose(statusCode, reason) + sessionState.removeSocket(this) + } + + companion object { + private val log = org.slf4j.LoggerFactory.getLogger(ChatSocket::class.java) + } +} + + diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocketManager.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocketManager.kt new file mode 100644 index 00000000..4df72ab5 --- /dev/null +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/ChatSocketManager.kt @@ -0,0 +1,72 @@ +package com.simiacryptus.skyenet.webui.chat + +import com.simiacryptus.jopenai.ApiModel +import com.simiacryptus.jopenai.ClientUtil.toContentList +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.session.SocketManagerBase +import com.simiacryptus.skyenet.webui.util.MarkdownUtil + +open class ChatSocketManager( + val parent: ChatServer, + session: Session, + val model: OpenAITextModel = ChatModels.GPT35Turbo, + val userInterfacePrompt: String, + private val initialAssistantPrompt: String = "", + val systemPrompt: String, + val api: OpenAIClient, + val temperature: Double = 0.3, + applicationClass: Class, +) : SocketManagerBase(session, parent.dataStorage, user = null, applicationClass = applicationClass) { + + init { + if (userInterfacePrompt.isNotBlank()) { + send("""aaa,
${MarkdownUtil.renderMarkdown(userInterfacePrompt)}
""") + } + } + + protected val messages by lazy { + val list = listOf( + ApiModel.ChatMessage(ApiModel.Role.system, systemPrompt.toContentList()), + ).toMutableList() + if (initialAssistantPrompt.isNotBlank()) list += + ApiModel.ChatMessage(ApiModel.Role.assistant, initialAssistantPrompt.toContentList()) + list + } + + @Synchronized + override fun onRun(userMessage: String, socket: ChatSocket) { + var responseContents = divInitializer(cancelable = false) + responseContents += """
${renderResponse(userMessage)}
""" + send("""$responseContents
${ApplicationServer.spinner}
""") + messages += ApiModel.ChatMessage(ApiModel.Role.user, userMessage.toContentList()) + try { + val response = api.chat( + ApiModel.ChatRequest( + messages = messages, + temperature = temperature, + model = model.modelName, + ), model + ).choices.first().message?.content.orEmpty() + messages += ApiModel.ChatMessage(ApiModel.Role.assistant, response.toContentList()) + responseContents += """
${renderResponse(response)}
""" + send(responseContents) + onResponse(response, responseContents) + } catch (e: Exception) { + log.info("Error in chat", e) + responseContents += """
${e.message}
""" + send(responseContents) + } + } + + open fun renderResponse(response: String) = """
${MarkdownUtil.renderMarkdown(response)}
""" + + open fun onResponse(response: String, responseContents: String) {} + + companion object { + private val log = org.slf4j.LoggerFactory.getLogger(ChatSocketManager::class.java) + } +} \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/CodeChatServer.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/CodeChatServer.kt similarity index 70% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/chat/CodeChatServer.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/CodeChatServer.kt index 42b053aa..aa5563e7 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/CodeChatServer.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/chat/CodeChatServer.kt @@ -1,13 +1,13 @@ -package com.simiacryptus.skyenet.chat +package com.simiacryptus.skyenet.webui.chat -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.ChatModels -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.servlet.AppInfoServlet -import com.simiacryptus.skyenet.util.ClasspathResource +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.ChatModels +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.servlet.AppInfoServlet +import com.simiacryptus.skyenet.webui.util.ClasspathResource import org.eclipse.jetty.servlet.ServletHolder import org.eclipse.jetty.util.resource.Resource import org.eclipse.jetty.webapp.WebAppContext @@ -47,7 +47,7 @@ class CodeChatServer( | |Responses may use markdown formatting. """.trimMargin(), - applicationClass = ApplicationBase::class.java, + applicationClass = ApplicationServer::class.java, ) { override fun canWrite(user: User?): Boolean = true } @@ -61,11 +61,6 @@ class CodeChatServer( } companion object { - fun htmlEscape(html: String) = html - .replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace("\"", """) - .replace("'", "'") + val log = org.slf4j.LoggerFactory.getLogger(CodeChatServer::class.java) } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AppInfoServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AppInfoServlet.kt similarity index 86% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AppInfoServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AppInfoServlet.kt index 0a6a690f..0c3b8205 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AppInfoServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AppInfoServlet.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AuthenticatedWebsite.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AuthenticatedWebsite.kt similarity index 94% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AuthenticatedWebsite.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AuthenticatedWebsite.kt index a2d4b731..b808c70e 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/AuthenticatedWebsite.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/AuthenticatedWebsite.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl @@ -7,10 +7,10 @@ import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport import com.google.api.client.json.gson.GsonFactory import com.google.api.services.oauth2.Oauth2 import com.google.api.services.oauth2.model.Userinfo -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.AuthenticationManager.Companion.AUTH_COOKIE -import com.simiacryptus.skyenet.platform.User +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.AuthenticationManager.Companion.AUTH_COOKIE +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.* import jakarta.servlet.http.Cookie import jakarta.servlet.http.HttpServlet diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/CorsFilter.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/CorsFilter.kt similarity index 95% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/CorsFilter.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/CorsFilter.kt index d3c7908b..d8dd76a0 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/CorsFilter.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/CorsFilter.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet import jakarta.servlet.* import jakarta.servlet.annotation.WebFilter diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/FileServlet.kt similarity index 92% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/FileServlet.kt index 1a763c62..8bf59072 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/FileServlet.kt @@ -1,10 +1,10 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -20,7 +20,7 @@ class FileServlet(val dataStorage: DataStorage) : HttpServlet() { val file = File(sessionDir, filePath) if (file.isFile) { val filename = file.name - resp.contentType = ApplicationBase.getMimeType(filename) + resp.contentType = ApplicationServer.getMimeType(filename) resp.status = HttpServletResponse.SC_OK file.inputStream().use { inputStream -> resp.outputStream.use { outputStream -> diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/NewSessionServlet.kt similarity index 81% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/NewSessionServlet.kt index 19d86a56..5ce2b952 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/NewSessionServlet.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.DataStorage import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ProxyHttpServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ProxyHttpServlet.kt similarity index 98% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ProxyHttpServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ProxyHttpServlet.kt index 61137d60..b0582fbf 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ProxyHttpServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ProxyHttpServlet.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionListServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionListServlet.kt new file mode 100644 index 00000000..5bc16507 --- /dev/null +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionListServlet.kt @@ -0,0 +1,60 @@ +package com.simiacryptus.skyenet.webui.servlet + +import com.simiacryptus.skyenet.core.Brain.Companion.indent +import com.simiacryptus.skyenet.core.platform.ApplicationServices.authenticationManager +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie +import jakarta.servlet.http.HttpServlet +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import java.text.SimpleDateFormat + +class SessionListServlet( + private val dataStorage: DataStorage, + private val prefix: String +) : HttpServlet() { + override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { + resp.contentType = "text/html" + resp.status = HttpServletResponse.SC_OK + val user = authenticationManager.getUser(req.getCookie()) + val sessions = dataStorage.listSessions(user) + val sessionRows = sessions.joinToString("") { session -> + val sessionName = dataStorage.getSessionName(user, session) + val sessionTime = dataStorage.getSessionTime(user, session) + val sessionTimeStr = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(sessionTime) + """ + + $sessionName + $sessionTimeStr + + """.trimIndent() + } + resp.writer.write( + """ + + + Sessions + + + + + + + + + ${sessionRows.indent(" ")} +
Session NameCreated
+ + + """.trimIndent() + ) + } + +} \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionSettingsServlet.kt similarity index 85% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionSettingsServlet.kt index daf1a631..b08f27e5 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/SessionSettingsServlet.kt @@ -1,16 +1,16 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse class SessionSettingsServlet( - private val server: ApplicationBase, + private val server: ApplicationServer, ) : HttpServlet() { override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { resp.contentType = "text/html" diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UsageServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UsageServlet.kt similarity index 88% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UsageServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UsageServlet.kt index 9a69a607..9c26dbfe 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UsageServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UsageServlet.kt @@ -1,11 +1,10 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.OpenAIModel -import com.simiacryptus.openai.models.OpenAITextModel -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.Session +import com.simiacryptus.jopenai.models.OpenAIModel +import com.simiacryptus.jopenai.models.OpenAITextModel +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -31,7 +30,7 @@ class UsageServlet : HttpServlet() { private fun serve( resp: HttpServletResponse, - usage: Map + usage: Map ) { val totalPromptTokens = usage.values.sumOf { it.prompt_tokens } val totalCompletionTokens = usage.values.sumOf { it.completion_tokens } diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserInfoServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserInfoServlet.kt similarity index 52% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserInfoServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserInfoServlet.kt index 6352e82a..67395ea8 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserInfoServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserInfoServlet.kt @@ -1,8 +1,9 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -11,11 +12,11 @@ class UserInfoServlet : HttpServlet() { public override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { resp.contentType = "text/json" resp.status = HttpServletResponse.SC_OK - val userinfo = ApplicationServices.authenticationManager.getUser(req.getCookie()) - if (null == userinfo) { + val user: User? = ApplicationServices.authenticationManager.getUser(req.getCookie()) + if (null == user) { resp.writer.write("{}") } else { - resp.writer.write(JsonUtil.objectMapper().writeValueAsString(userinfo)) + resp.writer.write(JsonUtil.objectMapper().writeValueAsString(user)) } } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserSettingsServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserSettingsServlet.kt similarity index 86% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserSettingsServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserSettingsServlet.kt index c18df3f2..871f7f4d 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/UserSettingsServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/UserSettingsServlet.kt @@ -1,9 +1,9 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.UserSettingsManager.UserSettings -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.util.JsonUtil +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.UserSettingsManager.UserSettings +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/WelcomeServlet.kt similarity index 87% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/WelcomeServlet.kt index 01a1b5a4..ad6f29fa 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/WelcomeServlet.kt @@ -1,22 +1,24 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.ApplicationDirectory -import com.simiacryptus.skyenet.platform.* +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.AuthorizationManager +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.intellij.lang.annotations.Language import java.nio.file.NoSuchFileException -open class WelcomeServlet(private val parent : ApplicationDirectory) : HttpServlet() { +open class WelcomeServlet(private val parent : com.simiacryptus.skyenet.webui.application.ApplicationDirectory) : HttpServlet() { override fun doGet(req: HttpServletRequest?, resp: HttpServletResponse?) { val user = ApplicationServices.authenticationManager.getUser(req!!.getCookie()) val requestURI = req.requestURI ?: "/" resp?.contentType = when (requestURI) { "/" -> "text/html" - else -> ApplicationBase.getMimeType(requestURI) + else -> ApplicationServer.getMimeType(requestURI) } when { requestURI == "/" -> resp?.writer?.write(homepage(user).trimIndent()) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ZipServlet.kt similarity index 84% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ZipServlet.kt index 91dcff6b..59f6a9ce 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/servlet/ZipServlet.kt @@ -1,9 +1,9 @@ -package com.simiacryptus.skyenet.servlet +package com.simiacryptus.skyenet.webui.servlet -import com.simiacryptus.skyenet.ApplicationBase.Companion.getCookie -import com.simiacryptus.skyenet.platform.ApplicationServices -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.webui.application.ApplicationServer.Companion.getCookie import jakarta.servlet.http.HttpServlet import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/MutableSessionHandler.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/MutableSessionHandler.kt similarity index 88% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/util/MutableSessionHandler.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/MutableSessionHandler.kt index 0b6e1304..e73f1522 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/MutableSessionHandler.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/MutableSessionHandler.kt @@ -1,7 +1,6 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.webui.session -import com.simiacryptus.skyenet.chat.ChatSocket -import com.simiacryptus.skyenet.session.SocketManager +import com.simiacryptus.skyenet.webui.chat.ChatSocket class MutableSessionHandler(initialDelegate: SocketManager?) : SocketManager { private var priorDelegates: MutableList = mutableListOf() diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SessionMessage.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionMessage.kt similarity index 64% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/session/SessionMessage.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionMessage.kt index bf280b11..1cc0da5e 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SessionMessage.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SessionMessage.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.session +package com.simiacryptus.skyenet.webui.session -import com.simiacryptus.skyenet.platform.Session +import com.simiacryptus.skyenet.core.platform.Session abstract class SessionMessage { abstract fun append(htmlToAppend: String, showSpinner: Boolean) : Unit diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManager.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManager.kt similarity index 66% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManager.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManager.kt index a3693d10..e5ede7c2 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManager.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManager.kt @@ -1,6 +1,6 @@ -package com.simiacryptus.skyenet.session +package com.simiacryptus.skyenet.webui.session -import com.simiacryptus.skyenet.chat.ChatSocket +import com.simiacryptus.skyenet.webui.chat.ChatSocket interface SocketManager { fun removeSocket(socket: ChatSocket) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManagerBase.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt similarity index 90% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManagerBase.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt index 95957a11..260c139d 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/SocketManagerBase.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/session/SocketManagerBase.kt @@ -1,19 +1,19 @@ -package com.simiacryptus.skyenet.session +package com.simiacryptus.skyenet.webui.session import com.google.common.util.concurrent.MoreExecutors -import com.simiacryptus.skyenet.chat.ChatServer -import com.simiacryptus.skyenet.chat.ChatSocket -import com.simiacryptus.skyenet.platform.* -import com.simiacryptus.skyenet.util.MarkdownUtil +import com.simiacryptus.skyenet.core.platform.* +import com.simiacryptus.skyenet.webui.chat.ChatServer +import com.simiacryptus.skyenet.webui.chat.ChatSocket +import com.simiacryptus.skyenet.webui.util.MarkdownUtil import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicInteger abstract class SocketManagerBase( protected val session: Session, - private val dataStorage: DataStorage?, - protected val userId: User? = null, + protected val dataStorage: DataStorage?, + protected val user: User? = null, private val messageStates: LinkedHashMap = dataStorage?.getMessages( - userId, session + user, session ) ?: LinkedHashMap(), private val applicationClass: Class<*>, ) : SocketManager { @@ -85,13 +85,13 @@ abstract class SocketManagerBase( private fun setMessage(key: String, value: String): Int { if (messageStates.containsKey(key) && messageStates[key] == value) return -1 - dataStorage?.updateMessage(userId, session, key, value) + dataStorage?.updateMessage(user, session, key, value) messageStates.put(key, value) return messageVersions.computeIfAbsent(key) { AtomicInteger(0) }.incrementAndGet() } final override fun onWebSocketText(socket: ChatSocket, message: String) { - if (canWrite(userId)) pool.submit { + if (canWrite(user)) pool.submit { log.debug("$session - Received message: $message") try { val opCmdPattern = """![a-z]{3,7},.*""".toRegex() diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt similarity index 64% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt index ef8e9e49..3ee391bf 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/CodingActorTestApp.kt @@ -1,11 +1,15 @@ -package com.simiacryptus.skyenet.test +package com.simiacryptus.skyenet.webui.test -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.actors.CodingActor -import com.simiacryptus.skyenet.platform.* -import com.simiacryptus.skyenet.session.* -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown +import com.simiacryptus.jopenai.API +import com.simiacryptus.skyenet.core.actors.CodingActor +import com.simiacryptus.skyenet.core.platform.ApplicationServices +import com.simiacryptus.skyenet.core.platform.AuthorizationManager +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationInterface +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.session.SocketManagerBase +import com.simiacryptus.skyenet.webui.util.MarkdownUtil.renderMarkdown import org.slf4j.LoggerFactory import java.util.* @@ -13,7 +17,7 @@ open class CodingActorTestApp( private val actor: CodingActor, applicationName: String = "CodingActorTest_" + actor.interpreter.javaClass.simpleName, temperature: Double = 0.3, -) : ApplicationBase( +) : ApplicationServer( applicationName = applicationName, temperature = temperature, ) { @@ -21,10 +25,10 @@ open class CodingActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationInterface, - sessionMessage: SessionMessage, - api: OpenAIAPI + ui: ApplicationInterface, + api: API ) { + val sessionMessage = ui.newMessage(SocketManagerBase.randomID(), spinner, false) sessionMessage.append("""
${renderMarkdown(userMessage)}
""", true) val response = actor.answer(userMessage, api = api) val canPlay = ApplicationServices.authorizationManager.isAuthorized( @@ -33,7 +37,7 @@ open class CodingActorTestApp( AuthorizationManager.OperationType.Execute ) val playLink = if(!canPlay) "" else { - socketManager.hrefLink("â–¶", "href-link play-button") { + ui.hrefLink("â–¶", "href-link play-button") { sessionMessage.append("""
Running...
""", true) val result = response.run() sessionMessage.append( diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/ParsedActorTestApp.kt similarity index 58% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/ParsedActorTestApp.kt index a21fddd2..d5aa378d 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/ParsedActorTestApp.kt @@ -1,21 +1,21 @@ -package com.simiacryptus.skyenet.test +package com.simiacryptus.skyenet.webui.test -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.actors.ParsedActor -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.session.ApplicationInterface -import com.simiacryptus.skyenet.session.SessionMessage -import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.util.JsonUtil +import com.simiacryptus.skyenet.core.actors.ParsedActor +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationInterface +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.session.SocketManagerBase +import com.simiacryptus.skyenet.webui.util.MarkdownUtil.renderMarkdown import org.slf4j.LoggerFactory open class ParsedActorTestApp( private val actor: ParsedActor, applicationName: String = "ParsedActorTest_" + actor.parserClass.simpleName, temperature: Double = 0.3, -) : ApplicationBase( +) : ApplicationServer( applicationName = applicationName, temperature = temperature, ) { @@ -23,10 +23,10 @@ open class ParsedActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationInterface, - sessionMessage: SessionMessage, - api: OpenAIAPI + ui: ApplicationInterface, + api: API ) { + val sessionMessage = ui.newMessage(SocketManagerBase.randomID(), spinner, false) sessionMessage.append("""
${renderMarkdown(userMessage)}
""", true) val response = actor.answer(userMessage, api = api) sessionMessage.append( diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/SimpleActorTestApp.kt similarity index 62% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/SimpleActorTestApp.kt index f551ec67..d0602026 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/test/SimpleActorTestApp.kt @@ -1,19 +1,20 @@ -package com.simiacryptus.skyenet.test +package com.simiacryptus.skyenet.webui.test -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.actors.SimpleActor -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.session.* -import com.simiacryptus.skyenet.util.MarkdownUtil +import com.simiacryptus.jopenai.API +import com.simiacryptus.skyenet.core.actors.SimpleActor +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationInterface +import com.simiacryptus.skyenet.webui.application.ApplicationServer +import com.simiacryptus.skyenet.webui.session.SocketManagerBase +import com.simiacryptus.skyenet.webui.util.MarkdownUtil import org.slf4j.LoggerFactory open class SimpleActorTestApp( private val actor: SimpleActor, applicationName: String = "SimpleActorTest_" + actor.javaClass.simpleName, temperature: Double = 0.3, -) : ApplicationBase( +) : ApplicationServer( applicationName = applicationName, temperature = temperature, ) { @@ -28,10 +29,10 @@ open class SimpleActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationInterface, - sessionMessage: SessionMessage, - api: OpenAIAPI + ui: ApplicationInterface, + api: API ) { + val sessionMessage = ui.newMessage(SocketManagerBase.randomID(), spinner, false) val actor = getSettings(session, user)?.actor ?: actor sessionMessage.append("""
${MarkdownUtil.renderMarkdown(userMessage)}
""", true) val moderatorResponse = actor.answer(userMessage, api = api) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/ClasspathResource.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/ClasspathResource.kt similarity index 98% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/util/ClasspathResource.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/ClasspathResource.kt index 355f8ec0..0426adea 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/ClasspathResource.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/ClasspathResource.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.webui.util import org.eclipse.jetty.util.URIUtil import org.eclipse.jetty.util.resource.Resource diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/EmbeddingVisualizer.kt similarity index 83% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/EmbeddingVisualizer.kt index 84bf5cc4..b1acad43 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/EmbeddingVisualizer.kt @@ -1,16 +1,16 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.webui.util -import com.simiacryptus.openai.OpenAIAPI -import com.simiacryptus.openai.OpenAIClient -import com.simiacryptus.openai.models.EmbeddingModels -import com.simiacryptus.skyenet.platform.DataStorage -import com.simiacryptus.skyenet.platform.Session -import com.simiacryptus.skyenet.platform.User -import com.simiacryptus.skyenet.session.ApplicationInterface -import com.simiacryptus.util.JsonUtil +import com.simiacryptus.jopenai.API +import com.simiacryptus.jopenai.OpenAIClient +import com.simiacryptus.jopenai.models.EmbeddingModels +import com.simiacryptus.jopenai.util.JsonUtil +import com.simiacryptus.skyenet.core.platform.DataStorage +import com.simiacryptus.skyenet.core.platform.Session +import com.simiacryptus.skyenet.core.platform.User +import com.simiacryptus.skyenet.webui.application.ApplicationInterface class EmbeddingVisualizer( - val api: OpenAIAPI, + val api: API, val dataStorage: DataStorage, val sessionID: Session, val appPath: String, @@ -22,7 +22,7 @@ class EmbeddingVisualizer( private fun toVectorMap(vararg words: String): Map { val vectors = words.map {word -> word to (api as OpenAIClient).createEmbedding( - OpenAIClient.EmbeddingRequest( + com.simiacryptus.jopenai.ApiModel.EmbeddingRequest( model = EmbeddingModels.AdaEmbedding.modelName, input = word, ) diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/MarkdownUtil.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/MarkdownUtil.kt similarity index 94% rename from webui/src/main/kotlin/com/simiacryptus/skyenet/util/MarkdownUtil.kt rename to webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/MarkdownUtil.kt index 5686f0b4..34e3f6b8 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/MarkdownUtil.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/webui/util/MarkdownUtil.kt @@ -1,4 +1,4 @@ -package com.simiacryptus.skyenet.util +package com.simiacryptus.skyenet.webui.util import com.vladsch.flexmark.ext.tables.TablesExtension import com.vladsch.flexmark.html.HtmlRenderer diff --git a/webui/src/main/resources/simpleSession/chat.css b/webui/src/main/resources/application/chat.css similarity index 94% rename from webui/src/main/resources/simpleSession/chat.css rename to webui/src/main/resources/application/chat.css index 9cfd5154..b7f3994a 100644 --- a/webui/src/main/resources/simpleSession/chat.css +++ b/webui/src/main/resources/application/chat.css @@ -1,320 +1,320 @@ -:root { - --primary-bg-color: #f7f7f7; - --secondary-bg-color: #ffffff; - --primary-text-color: #333; - --secondary-text-color: #555; - --link-color: #0066cc; - --link-hover-color: #0044aa; - --border-radius: 4px; - --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - --transition-speed: 0.3s; -} - -body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - color: var(--primary-text-color); - background-color: var(--primary-bg-color); - margin: 0; - padding: 0 0 50px; -} - -#messages { - position: relative; - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 10px 10px 10px; - flex-grow: 1; - flex-shrink: 1; - background-color: var(--secondary-bg-color); - box-shadow: var(--box-shadow); -} - -.chat-input { - background-color: var(--secondary-bg-color); - border-radius: var(--border-radius); - padding: 10px; - margin-bottom: 10px; - overflow: auto; - resize: vertical; - flex: 1; - border: 1px solid #ddd; - box-shadow: var(--box-shadow); -} - -#main-input { - position: relative; - align-items: flex-start; - left: 0; - right: 0; - top: 0; - display: flex; - margin: 0; - padding: 5px; - flex-shrink: 0; - background-color: var(--primary-bg-color); -} - -#session { - display: flex; - flex-direction: column; - height: 100vh; - padding-top: 40px; -} - -.reply-form { - width: 100%; -} - -.reply-input { - resize: vertical; -} - -.href-link { - text-decoration: none; - color: var(--link-color); - transition: color var(--transition-speed); -} - -.href-link:hover { - color: var(--link-hover-color); - text-decoration: underline; -} - -#message { - flex-grow: 1; - margin-right: 5px; -} - -.message-container { - position: relative; -} - -#disconnected-overlay { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); - z-index: 50; - justify-content: center; - align-items: center; - color: white; - font-size: 24px; -} - -#disconnected-overlay p { - font-size: 3rem; - line-height: 1.5; - margin-bottom: 20px; - animation: bounce var(--transition-speed) infinite alternate; - left: 10%; - position: relative; - color: firebrick; -} - -.spinner-border { - display: block; - width: 40px; - height: 40px; - border: 4px solid rgba(0, 0, 0, 0.1); - border-left-color: var(--link-color); - border-radius: 50%; - animation: spin 1s linear infinite; -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; -} - -#toolbar, #namebar { - background-color: var(--secondary-bg-color); - padding: 5px; - position: fixed; - top: 0; - text-align: left; - box-shadow: var(--box-shadow); -} - - -#toolbar { - width: 100%; - z-index: 2; -} - - -#namebar { - z-index: 3; - right: 0; -} - -#toolbar a, #namebar a { - color: var(--primary-text-color); - text-decoration: none; - padding: 5px; - transition: background-color var(--transition-speed); -} - -#toolbar a:hover, #namebar a:hover { - background-color: var(--secondary-text-color); - color: var(--secondary-bg-color); -} - -.modal { - display: none; - position: fixed; - z-index: 100; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(0, 0, 0, 0.4); -} - -.modal-content { - background-color: var(--secondary-bg-color); - margin: 15% auto; - padding: 20px; - border: 1px solid #888; - width: 80%; - position: relative; - border-radius: var(--border-radius); - box-shadow: var(--box-shadow); -} - -.close { - color: var(--secondary-text-color); - float: right; - font-size: 28px; - font-weight: bold; - cursor: pointer; -} - -.close:hover, -.close:focus { - color: var(--primary-text-color); -} - -pre { - white-space: pre-wrap; -} - -.play-button, .cancel-button { - font-size: 48px; - font-weight: bold; - border: none; - background: transparent; - cursor: pointer; - transition: transform var(--transition-speed); - text-decoration: none; -} - -.cancel-button { - right: 0; - position: absolute; -} - -.play-button:focus, .cancel-button:focus { - outline: none; -} - -.play-button:active, .cancel-button:active { - transform: scale(0.9); -} - -.error { - color: red; -} - -.verbose { - display: block; -} - -.verbose-hidden { - display: none; -} - - -@keyframes bounce { - 0% { - transform: translateY(0); - } - 100% { - transform: translateY(-10px); - } -} - - - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -/* Styling for user and response messages */ -.user-message, .response-message { - padding: 10px; - margin-bottom: 10px; - border-radius: 4px; -} - -.user-message { - background-color: #e7f4ff; - border: 1px solid #d0eaff; -} - -.response-message { - background-color: #fff; - border: 1px solid #eee; -} - -/* Styling for code blocks */ -pre.verbose, pre.response-message { - background-color: #f5f5f5; - border: 1px solid #e1e1e1; - border-radius: 4px; - padding: 15px; - overflow-x: auto; - font-family: 'Courier New', Courier, monospace; -} - -/* Styling for headers within the response */ -.response-header { - font-weight: bold; - margin-top: 20px; - margin-bottom: 10px; -} - -#footer { - position: fixed; - bottom: 0; - width: 100%; - text-align: right; - z-index: 1000; -} - -#footer a { - color: darkgray; - text-decoration: none; - font-weight: bold; -} - -#footer a:hover { - text-decoration: underline; -} +:root { + --primary-bg-color: #f7f7f7; + --secondary-bg-color: #ffffff; + --primary-text-color: #333; + --secondary-text-color: #555; + --link-color: #0066cc; + --link-hover-color: #0044aa; + --border-radius: 4px; + --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + --transition-speed: 0.3s; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + color: var(--primary-text-color); + background-color: var(--primary-bg-color); + margin: 0; + padding: 0 0 50px; +} + +#messages { + position: relative; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding: 10px 10px 10px; + flex-grow: 1; + flex-shrink: 1; + background-color: var(--secondary-bg-color); + box-shadow: var(--box-shadow); +} + +.chat-input { + background-color: var(--secondary-bg-color); + border-radius: var(--border-radius); + padding: 10px; + margin-bottom: 10px; + overflow: auto; + resize: vertical; + flex: 1; + border: 1px solid #ddd; + box-shadow: var(--box-shadow); +} + +#main-input { + position: relative; + align-items: flex-start; + left: 0; + right: 0; + top: 0; + display: flex; + margin: 0; + padding: 5px; + flex-shrink: 0; + background-color: var(--primary-bg-color); +} + +#session { + display: flex; + flex-direction: column; + height: 100vh; + padding-top: 40px; +} + +.reply-form { + width: 100%; +} + +.reply-input { + resize: vertical; +} + +.href-link { + text-decoration: none; + color: var(--link-color); + transition: color var(--transition-speed); +} + +.href-link:hover { + color: var(--link-hover-color); + text-decoration: underline; +} + +#message { + flex-grow: 1; + margin-right: 5px; +} + +.message-container { + position: relative; +} + +#disconnected-overlay { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 50; + justify-content: center; + align-items: center; + color: white; + font-size: 24px; +} + +#disconnected-overlay p { + font-size: 3rem; + line-height: 1.5; + margin-bottom: 20px; + animation: bounce var(--transition-speed) infinite alternate; + left: 10%; + position: relative; + color: firebrick; +} + +.spinner-border { + display: block; + width: 40px; + height: 40px; + border: 4px solid rgba(0, 0, 0, 0.1); + border-left-color: var(--link-color); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +#toolbar, #namebar { + background-color: var(--secondary-bg-color); + padding: 5px; + position: fixed; + top: 0; + text-align: left; + box-shadow: var(--box-shadow); +} + + +#toolbar { + width: 100%; + z-index: 2; +} + + +#namebar { + z-index: 3; + right: 0; +} + +#toolbar a, #namebar a { + color: var(--primary-text-color); + text-decoration: none; + padding: 5px; + transition: background-color var(--transition-speed); +} + +#toolbar a:hover, #namebar a:hover { + background-color: var(--secondary-text-color); + color: var(--secondary-bg-color); +} + +.modal { + display: none; + position: fixed; + z-index: 100; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0, 0, 0, 0.4); +} + +.modal-content { + background-color: var(--secondary-bg-color); + margin: 15% auto; + padding: 20px; + border: 1px solid #888; + width: 80%; + position: relative; + border-radius: var(--border-radius); + box-shadow: var(--box-shadow); +} + +.close { + color: var(--secondary-text-color); + float: right; + font-size: 28px; + font-weight: bold; + cursor: pointer; +} + +.close:hover, +.close:focus { + color: var(--primary-text-color); +} + +pre { + white-space: pre-wrap; +} + +.play-button, .cancel-button { + font-size: 48px; + font-weight: bold; + border: none; + background: transparent; + cursor: pointer; + transition: transform var(--transition-speed); + text-decoration: none; +} + +.cancel-button { + right: 0; + position: absolute; +} + +.play-button:focus, .cancel-button:focus { + outline: none; +} + +.play-button:active, .cancel-button:active { + transform: scale(0.9); +} + +.error { + color: red; +} + +.verbose { + display: block; +} + +.verbose-hidden { + display: none; +} + + +@keyframes bounce { + 0% { + transform: translateY(0); + } + 100% { + transform: translateY(-10px); + } +} + + + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +/* Styling for user and response messages */ +.user-message, .response-message { + padding: 10px; + margin-bottom: 10px; + border-radius: 4px; +} + +.user-message { + background-color: #e7f4ff; + border: 1px solid #d0eaff; +} + +.response-message { + background-color: #fff; + border: 1px solid #eee; +} + +/* Styling for code blocks */ +pre.verbose, pre.response-message { + background-color: #f5f5f5; + border: 1px solid #e1e1e1; + border-radius: 4px; + padding: 15px; + overflow-x: auto; + font-family: 'Courier New', Courier, monospace; +} + +/* Styling for headers within the response */ +.response-header { + font-weight: bold; + margin-top: 20px; + margin-bottom: 10px; +} + +#footer { + position: fixed; + bottom: 0; + width: 100%; + text-align: right; + z-index: 1000; +} + +#footer a { + color: darkgray; + text-decoration: none; + font-weight: bold; +} + +#footer a:hover { + text-decoration: underline; +} diff --git a/webui/src/main/resources/simpleSession/chat.js b/webui/src/main/resources/application/chat.js similarity index 96% rename from webui/src/main/resources/simpleSession/chat.js rename to webui/src/main/resources/application/chat.js index 3c328750..f4d1571a 100644 --- a/webui/src/main/resources/simpleSession/chat.js +++ b/webui/src/main/resources/application/chat.js @@ -1,70 +1,70 @@ - -let socket; - -function getSessionId() { - if (!window.location.hash) { - fetch('newSession') - .then(response => { - if (response.ok) { - return response.text(); - } else { - throw new Error('Failed to get new session ID'); - } - }) - .then(sessionId => { - window.location.hash = sessionId; - connect(sessionId); - }); - } else { - return window.location.hash.substring(1); - } -} - -function send(message) { - console.log('Sending message:', message); - if (socket.readyState !== 1) { - throw new Error('WebSocket is not open'); - } - socket.send(message); -} - -function connect(sessionId, customReceiveFunction) { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const host = window.location.hostname; - const port = window.location.port; - let path = window.location.pathname; - let strings = path.split('/'); - if(strings.length >= 2 && strings[1] !== '' && strings[1] !== 'index.html') { - path = '/' + strings[1] + '/'; - } else { - path = '/'; - } - - socket = new WebSocket(`${protocol}//${host}:${port}${path}ws?sessionId=${sessionId}`); - - socket.addEventListener('open', (event) => { - console.log('WebSocket connected:', event); - showDisconnectedOverlay(false); - }); - - socket.addEventListener('message', customReceiveFunction || onWebSocketText); - - socket.addEventListener('close', (event) => { - console.log('WebSocket closed:', event); - showDisconnectedOverlay(true); - setTimeout(() => { - connect(getSessionId(), customReceiveFunction); - }, 3000); - }); - - socket.addEventListener('error', (event) => { - console.error('WebSocket error:', event); - }); -} - -function showDisconnectedOverlay(show) { - const elements = document.getElementsByClassName('ws-control'); - for (let i = 0; i < elements.length; i++) { - elements[i].disabled = show; - } -} + +let socket; + +function getSessionId() { + if (!window.location.hash) { + fetch('newSession') + .then(response => { + if (response.ok) { + return response.text(); + } else { + throw new Error('Failed to get new session ID'); + } + }) + .then(sessionId => { + window.location.hash = sessionId; + connect(sessionId); + }); + } else { + return window.location.hash.substring(1); + } +} + +function send(message) { + console.log('Sending message:', message); + if (socket.readyState !== 1) { + throw new Error('WebSocket is not open'); + } + socket.send(message); +} + +function connect(sessionId, customReceiveFunction) { + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + const host = window.location.hostname; + const port = window.location.port; + let path = window.location.pathname; + let strings = path.split('/'); + if(strings.length >= 2 && strings[1] !== '' && strings[1] !== 'index.html') { + path = '/' + strings[1] + '/'; + } else { + path = '/'; + } + + socket = new WebSocket(`${protocol}//${host}:${port}${path}ws?sessionId=${sessionId}`); + + socket.addEventListener('open', (event) => { + console.log('WebSocket connected:', event); + showDisconnectedOverlay(false); + }); + + socket.addEventListener('message', customReceiveFunction || onWebSocketText); + + socket.addEventListener('close', (event) => { + console.log('WebSocket closed:', event); + showDisconnectedOverlay(true); + setTimeout(() => { + connect(getSessionId(), customReceiveFunction); + }, 3000); + }); + + socket.addEventListener('error', (event) => { + console.error('WebSocket error:', event); + }); +} + +function showDisconnectedOverlay(show) { + const elements = document.getElementsByClassName('ws-control'); + for (let i = 0; i < elements.length; i++) { + elements[i].disabled = show; + } +} diff --git a/webui/src/main/resources/simpleSession/favicon.svg b/webui/src/main/resources/application/favicon.svg similarity index 99% rename from webui/src/main/resources/simpleSession/favicon.svg rename to webui/src/main/resources/application/favicon.svg index 2cbd9fdb..6a09be9f 100644 --- a/webui/src/main/resources/simpleSession/favicon.svg +++ b/webui/src/main/resources/application/favicon.svg @@ -1,5 +1,5 @@  - - - WebSocket Client - - - - - - - - - - - - - - - - - - - - - -
- Login -
- -
-
- - -
-
-
- - - - - - - - + + + + + WebSocket Client + + + + + + + + + + + + + + + + + + + + + +
+ Login +
+ +
+
+ + +
+
+
+ + + + + + + + diff --git a/webui/src/main/resources/simpleSession/main.js b/webui/src/main/resources/application/main.js similarity index 97% rename from webui/src/main/resources/simpleSession/main.js rename to webui/src/main/resources/application/main.js index 7b99f772..1ef3f0c6 100644 --- a/webui/src/main/resources/simpleSession/main.js +++ b/webui/src/main/resources/application/main.js @@ -50,6 +50,12 @@ function onWebSocketText(event) { messageDiv.id = messageId; messageDiv.innerHTML = messageContent; messagesDiv.appendChild(messageDiv); + const mainInput = document.getElementById('main-input'); + if (mainInput) { + mainInput.style.display = 'none'; + } else { + console.log("Error: Could not find .main-input"); + } } messagesDiv.scrollTop = messagesDiv.scrollHeight; diff --git a/webui/src/main/resources/codeChat/favicon.svg b/webui/src/main/resources/codeChat/favicon.svg index 2cbd9fdb..6a09be9f 100644 --- a/webui/src/main/resources/codeChat/favicon.svg +++ b/webui/src/main/resources/codeChat/favicon.svg @@ -1,5 +1,5 @@  -