feat: история общения (SQLite) + Koog LLM-клиент в app-phone
SQLite (голый SQLiteOpenHelper, без ORM — как решили): - sessions (id, title, created_at, updated_at) + messages (role, content, tool_call_id, tool_calls JSON, attachments JSON, created_at) по утверждённой схеме; FK-каскад; CHECK на роли. - ChatDb + ChatDao (createSession/listSessions/rename/touch/delete, addMessage, messagesForSession), доступ через PhoneApp.chatDao. - Unit: ModelsTest (роли, JSON tool_calls/attachments). androidTest: ChatDaoTest — CRUD-круг + каскад — OK (3 tests) на эмуляторе. Koog (JetBrains) — базовый LLM-клиент, без агентного слоя: - ai.koog:prompt-executor-openai-client:1.1.1 + http-client-okhttp - LlmClient: OpenAILLMClient(apiKey, baseUrl=llm.binom.pw) → chat(история) - BuildConfig LLM_API_KEY/LLM_MODEL из local.properties (вне git); llm_debug smoke (--ez llm_debug true) — проверен на эмуляторе: реальный ответ от llm.binom.pw (deepseek-v4-flash). - ЗАГЛУШКА Coroutines_jvmKt: дефект публикации Koog 1.1.1 — utils-android не включает jvm-класс, который зовёт OkHttpKoogHttpClient (без неё NoClassDefFoundError на первом вызове). Сигнатура сверена с utils-jvm. Убрать после фикса JetBrains.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package pw.binom.viewmate.phone.agent
|
||||
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class ModelsTest {
|
||||
|
||||
@Test
|
||||
fun chatRoleWireRoundTrip() {
|
||||
ChatRole.entries.forEach { role ->
|
||||
assertEquals(role, ChatRole.fromWire(role.wire))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun chatRoleFromWireUnknownThrows() {
|
||||
assertFailsWith<IllegalArgumentException> { ChatRole.fromWire("nope") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toolCallJsonRoundTrip() {
|
||||
val call = ToolCall("c1", "play_movie", "{\"item\":\"m1\",\"audio\":0}")
|
||||
val decoded = agentJson.decodeFromString<ToolCall>(agentJson.encodeToString(call))
|
||||
assertEquals(call, decoded)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun attachmentJsonRoundTrip() {
|
||||
val attachment = Attachment(type = "image", uri = "file:///sdcard/a.jpg", mime = "image/jpeg")
|
||||
val decoded = agentJson.decodeFromString<Attachment>(agentJson.encodeToString(attachment))
|
||||
assertEquals(attachment, decoded)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun attachmentDefaultsTypeToImage() {
|
||||
val decoded = agentJson.decodeFromString<Attachment>("""{"uri":"file:///x.png"}""")
|
||||
assertEquals("image", decoded.type)
|
||||
assertEquals("file:///x.png", decoded.uri)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toolCallListToJsonStringAndBack() {
|
||||
val calls = listOf(
|
||||
ToolCall("c1", "play_movie", "{}"),
|
||||
ToolCall("c2", "search", "{\"q\":\"matrix\"}"),
|
||||
)
|
||||
val json = agentJson.encodeToString(calls)
|
||||
assertNotNull(json)
|
||||
assertEquals(calls, agentJson.decodeFromString<List<ToolCall>>(json))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user