prepare linuxX64: switch to kotlin.uuid.Uuid and ktor-server-cio
1. UUID: java.util.UUID.randomUUID() → commonMain helper Ids.new(prefix)
wrapping kotlin.uuid.Uuid.random(). kotlin.uuid is stdlib (KMP: jvm +
all native targets), so the call sites (ChatAgent, ChatConversation,
SqliteWorkingMemoryStore) are now ready for native builds. Format kept:
'<prefix>-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.
2. HTTP engine: ktor-server-netty → ktor-server-cio. Netty is JVM-only;
CIO is KMP (jvm, linuxX64, ios, etc.) and feature-complete for our
needs (POST + SSE). standalone/build.gradle.kts drops netty and adds
cio; Main.kt imports io.ktor.server.cio.CIO and calls
embeddedServer(CIO, port = port).
Netty is left in libs.versions.toml (catalog entry kept) in case anyone
needs to fall back; only :standalone stopped depending on it.
E2E verified end-to-end against litellm local/codding: standalone-1.0.0
tarball starts on AGENTIK_PORT, GET /health -> 'ok', POST
/agentik/conversations -> 201 with new UUID-format id, POST .../messages
returns real LLM answer ('Ассистент'). 44/44 unit tests green.
This commit is contained in:
@@ -36,9 +36,10 @@ sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sq
|
|||||||
sqldelight-sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
sqldelight-sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
||||||
sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
|
sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
|
||||||
|
|
||||||
# --- Ktor (сервер, JVM) ---
|
# --- Ktor (сервер) ---
|
||||||
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
|
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
|
||||||
ktor-server-sse = { module = "io.ktor:ktor-server-sse", version.ref = "ktor" }
|
ktor-server-sse = { module = "io.ktor:ktor-server-sse", version.ref = "ktor" }
|
||||||
|
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
|
||||||
ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
|
ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
|
||||||
ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
|
ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
|
||||||
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
|
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
|
||||||
|
|||||||
@@ -48,9 +48,11 @@ kotlin {
|
|||||||
implementation(libs.sqldelight.sqlite.driver)
|
implementation(libs.sqldelight.sqlite.driver)
|
||||||
|
|
||||||
// Ktor server (для :server facade + a2aServer)
|
// Ktor server (для :server facade + a2aServer)
|
||||||
|
// Используем CIO вместо Netty — он KMP (jvm + linuxX64/ios/...), нам нужен
|
||||||
|
// для будущей native-сборки; на JVM работает идентично для нашего сценария.
|
||||||
implementation(libs.ktor.server.core)
|
implementation(libs.ktor.server.core)
|
||||||
implementation(libs.ktor.server.sse)
|
implementation(libs.ktor.server.sse)
|
||||||
implementation(libs.ktor.server.netty)
|
implementation(libs.ktor.server.cio)
|
||||||
implementation(libs.ktor.server.content.negotiation)
|
implementation(libs.ktor.server.content.negotiation)
|
||||||
implementation(libs.ktor.serialization.kotlinx.json)
|
implementation(libs.ktor.serialization.kotlinx.json)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package pw.binom.agentik.standalone.persistence
|
||||||
|
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генератор id. Использует `kotlin.uuid.Uuid` из stdlib (KMP: jvm + native),
|
||||||
|
* чтобы не зависеть от `java.util.UUID` и подготовить код к linuxX64-сборке.
|
||||||
|
*
|
||||||
|
* Сохраняет формат `<prefix>-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` —
|
||||||
|
* `:server` его парсит как opaque string, без знания внутренней структуры.
|
||||||
|
*/
|
||||||
|
object Ids {
|
||||||
|
fun new(prefix: String): String = "$prefix-${Uuid.random()}"
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package pw.binom.agentik.standalone
|
package pw.binom.agentik.standalone
|
||||||
|
|
||||||
|
import io.ktor.server.cio.CIO
|
||||||
import io.ktor.server.engine.embeddedServer
|
import io.ktor.server.engine.embeddedServer
|
||||||
import io.ktor.server.netty.Netty
|
|
||||||
import io.ktor.server.response.respondText
|
import io.ktor.server.response.respondText
|
||||||
import io.ktor.server.routing.get
|
import io.ktor.server.routing.get
|
||||||
import io.ktor.server.routing.routing
|
import io.ktor.server.routing.routing
|
||||||
@@ -13,7 +13,7 @@ import pw.binom.agentik.standalone.mcp.McpRegistry
|
|||||||
import pw.binom.agentik.standalone.persistence.sqlite.SqliteStores
|
import pw.binom.agentik.standalone.persistence.sqlite.SqliteStores
|
||||||
/**
|
/**
|
||||||
* standalone-контейнер agentik:
|
* standalone-контейнер agentik:
|
||||||
* - :server (proto): встраиваемый Ktor (Netty), порт AGENTIK_PORT (default 8080)
|
* - :server (proto): встраиваемый Ktor (CIO), порт AGENTIK_PORT (default 8080)
|
||||||
* POST /agentik/conversations -> ConversationSnapshot (201)
|
* POST /agentik/conversations -> ConversationSnapshot (201)
|
||||||
* GET /agentik/conversations -> [ConversationSnapshot]
|
* GET /agentik/conversations -> [ConversationSnapshot]
|
||||||
* GET /agentik/conversations/{id} -> ConversationSnapshot
|
* GET /agentik/conversations/{id} -> ConversationSnapshot
|
||||||
@@ -49,7 +49,7 @@ fun main() {
|
|||||||
tools = mcpRegistry.namedTools,
|
tools = mcpRegistry.namedTools,
|
||||||
)
|
)
|
||||||
|
|
||||||
val server = embeddedServer(Netty, port = port) {
|
val server = embeddedServer(CIO, port = port) {
|
||||||
routing {
|
routing {
|
||||||
get("/health") { call.respondText("ok") }
|
get("/health") { call.respondText("ok") }
|
||||||
agentikAgent(agent, path = "/agentik")
|
agentikAgent(agent, path = "/agentik")
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class ChatAgent(
|
|||||||
|
|
||||||
override fun createConversation(temp: Boolean): ProtoConversation {
|
override fun createConversation(temp: Boolean): ProtoConversation {
|
||||||
val now = now()
|
val now = now()
|
||||||
val id = "conv-${java.util.UUID.randomUUID()}"
|
val id = pw.binom.agentik.standalone.persistence.Ids.new("conv")
|
||||||
val rec = ConversationRecord(
|
val rec = ConversationRecord(
|
||||||
id = id,
|
id = id,
|
||||||
title = null,
|
title = null,
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ class ChatConversation(
|
|||||||
private fun now(): Instant =
|
private fun now(): Instant =
|
||||||
Instant.fromEpochMilliseconds(System.currentTimeMillis())
|
Instant.fromEpochMilliseconds(System.currentTimeMillis())
|
||||||
|
|
||||||
private fun newId(prefix: String): String = "$prefix-${java.util.UUID.randomUUID()}"
|
private fun newId(prefix: String): String = pw.binom.agentik.standalone.persistence.Ids.new(prefix)
|
||||||
|
|
||||||
private fun encodeArgsJson(arguments: Map<String, Any?>): String {
|
private fun encodeArgsJson(arguments: Map<String, Any?>): String {
|
||||||
val el = kotlinx.serialization.json.JsonElement.serializer()
|
val el = kotlinx.serialization.json.JsonElement.serializer()
|
||||||
|
|||||||
+1
-1
@@ -67,4 +67,4 @@ private fun Working_memory.toRow(): WorkingMemoryRow {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newId(): String = "wm-${java.util.UUID.randomUUID()}"
|
private fun newId(): String = pw.binom.agentik.standalone.persistence.Ids.new("wm")
|
||||||
|
|||||||
Reference in New Issue
Block a user