ddd9d076c1
ci / JVM build + tests (push) Failing after 1m25s
Закрывает разрыв между :proto и UI-композицией: TuiBackend маршрутизирует
onUserMessage → Conversation.send и Event → AppState.
Изменения:
- agentik-tui/.../TuiBackend.kt — новый commonMain-файл (138 строк):
инкапсулирует Agent-общение, авто-создание первого диалога,
подписку на Conversation.events, диспетчеризацию Event в AppState.
- agentik-tui/.../Main.kt — обязательный health-check GET {baseUrl}/health
ДО старта UI: понятная ошибка и exit 1 при недоступном сервере,
понятное сообщение при не-200/не-'ok'. JVM-only API (java.net.*,
ktor.*Timeout) обёрнуты в catch (Exception) — commonMain собирается
под все desktop-native.
- agentik-tui/.../AppState.kt — добавлены attachBackend/setConversation/
newConversation/postSystem; submitInput теперь не пишет AssistantStreaming
сам (его рисует TuiBackend по Event.AppendText).
- agentik-tui/.../TuiApp.kt — TuiBackend монтируется в LaunchedEffect,
делит scope с recomposer'ом.
- agentik-tui/.../Platform.jvm.kt — expect/actual platformEnv + platformCreateAgent.
- agentik-tui/.../Platform.native.kt — stub actual.
- agentik-tui/build.gradle.kts — kotlinx-coroutines-test в commonTest.
- agentik-cli/build.gradle.kts — binaries.executable entryPoint для native
(тот же фикс, что прошёл для agentik-tui в предыдущем коммите).
- TuiBackend.dispatch: Event.End теперь зовёт finishAssistant()
(конвертирует streaming-чанк в финальный Assistant), Interrupted —
finishAssistant + 'прервано' system message. Раньше оба только
выключали streaming, и последний чанк висел как AssistantStreaming
с курсором.
Тесты: agentik-tui/src/commonTest/.../TuiBackendTest.kt — 10 кейсов
против FakeAgent/FakeConversation: auto-create, переиспользование,
AppendText-coalesce, End finalize, Interrupted system, ToolCall/ToolResult
visibility, Error handling, exception path, StartReasoning, connect
message. Используется runTest.backgroundScope + runCurrent — backgroundScope
не двигается через advanceUntilIdle (документированное поведение).
Сборка: jvm + linuxX64 + linuxArm64 + macosX64 + macosArm64 + mingwX64,
10/10 jvmTest green, full project jvmTest не задет.
33 lines
1.1 KiB
Kotlin
33 lines
1.1 KiB
Kotlin
package pw.binom.agentik.tui
|
|
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.remember
|
|
import com.jakewharton.mosaic.runMosaicBlocking
|
|
import kotlinx.coroutines.launch
|
|
import pw.binom.agentik.proto.Agent
|
|
|
|
/**
|
|
* Корневая точка запуска UI. Стартует Mosaic-рантайм, монтирует [TuiBackend] в
|
|
* его coroutine-scope и ждёт завершения приложения.
|
|
*
|
|
* Бэкенд — единый singleton на процесс: UI-композиция, сетевые подписки и
|
|
* coroutine job'ы делят scope [runMosaicBlocking] (через [LaunchedEffect]).
|
|
*/
|
|
internal class TuiApp(
|
|
private val config: TuiConfig,
|
|
private val agent: Agent,
|
|
) {
|
|
fun run() {
|
|
runMosaicBlocking {
|
|
val state = remember { AppState(config) }
|
|
val backend = remember { TuiBackend(state = state, agent = agent) }
|
|
LaunchedEffect(backend) {
|
|
backend.start(this)
|
|
}
|
|
state.attachBackend(backend)
|
|
App(state = state)
|
|
}
|
|
}
|
|
}
|