git.iko.soy/opencode-android
on 2811bd0 help sign in
88 lines 3.5 kB history raw
1package soy.iko.opencode
3import soy.iko.opencode.data.model.AssistantMessage
4import soy.iko.opencode.data.model.BusEvent
5import soy.iko.opencode.data.model.MessagePartUpdated
6import soy.iko.opencode.data.model.MessageWithParts
7import soy.iko.opencode.data.model.Part
8import soy.iko.opencode.data.model.SessionIdle
9import soy.iko.opencode.data.model.TextPart
10import soy.iko.opencode.data.model.ToolCompleted
11import soy.iko.opencode.data.model.ToolPart
12import soy.iko.opencode.data.model.UnknownEvent
13import soy.iko.opencode.data.model.UnknownPart
14import soy.iko.opencode.data.network.OpencodeJson
15import org.junit.Assert.assertEquals
16import org.junit.Assert.assertTrue
17import org.junit.Test
19class OpencodeJsonTest {
21 private fun <T> decode(serializer: kotlinx.serialization.KSerializer<T>, json: String): T =
22 OpencodeJson.decodeFromString(serializer, json)
24 @Test
25 fun decodesPromptResponseWithPartsAndTokens() {
26 val json = """
27 {
28 "info": {
29 "role": "assistant", "id": "msg_1", "sessionID": "ses_1",
30 "modelID": "claude-sonnet", "providerID": "anthropic",
31 "cost": 0.012,
32 "tokens": { "input": 10, "output": 20, "reasoning": 0, "cache": { "read": 1, "write": 2 } },
33 "time": { "created": 100, "completed": 200 }
34 },
35 "parts": [
36 { "type": "text", "id": "prt_1", "messageID": "msg_1", "sessionID": "ses_1", "text": "Hello" }
37 ]
38 }
39 """.trimIndent()
41 val msg = decode(MessageWithParts.serializer(), json)
42 val info = msg.info as AssistantMessage
43 assertEquals("anthropic", info.providerID)
44 assertEquals(20L, info.tokens?.output)
45 assertTrue(info.isComplete)
46 assertEquals("Hello", (msg.parts.single() as TextPart).text)
47 }
49 @Test
50 fun decodesToolPartStateMachine() {
51 val json = """
52 { "type": "tool", "id": "prt_2", "messageID": "msg_1", "callID": "c1", "tool": "bash",
53 "state": { "status": "completed", "output": "done", "title": "ran bash" } }
54 """.trimIndent()
55 val part = decode(Part.serializer(), json) as ToolPart
56 assertEquals("bash", part.tool)
57 assertEquals("done", (part.state as ToolCompleted).output)
58 }
60 @Test
61 fun decodesPartUpdatedEvent() {
62 val json = """
63 { "type": "message.part.updated",
64 "properties": { "part": { "type": "text", "id": "prt_1", "messageID": "msg_1", "text": "Hel" } } }
65 """.trimIndent()
66 val event = decode(BusEvent.serializer(), json) as MessagePartUpdated
67 assertEquals("Hel", (event.properties.part as TextPart).text)
68 }
70 @Test
71 fun decodesSessionIdleEvent() {
72 val event = decode(BusEvent.serializer(), """{"type":"session.idle","properties":{"sessionID":"ses_1"}}""")
73 assertTrue(event is SessionIdle)
74 assertEquals("ses_1", (event as SessionIdle).properties.sessionID)
75 }
77 @Test
78 fun unknownEventTypeFallsBackInsteadOfThrowing() {
79 val event = decode(BusEvent.serializer(), """{"type":"some.future.event","properties":{"x":1}}""")
80 assertEquals(UnknownEvent, event)
81 }
83 @Test
84 fun unknownPartTypeFallsBackInsteadOfThrowing() {
85 val part = decode(Part.serializer(), """{"type":"future-part","id":"p9","foo":true}""")
86 assertTrue(part is UnknownPart)
87 }