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
19class OpencodeJsonTest {
21 private fun <T> decode(serializer: kotlinx.serialization.KSerializer<T>, json: String): T =
22 OpencodeJson.decodeFromString(serializer, json)
25 fun decodesPromptResponseWithPartsAndTokens() {
29 "role": "assistant", "id": "msg_1", "sessionID": "ses_1",
30 "modelID": "claude-sonnet", "providerID": "anthropic",
32 "tokens": { "input": 10, "output": 20, "reasoning": 0, "cache": { "read": 1, "write": 2 } },
33 "time": { "created": 100, "completed": 200 }
36 { "type": "text", "id": "prt_1", "messageID": "msg_1", "sessionID": "ses_1", "text": "Hello" }
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)
50 fun decodesToolPartStateMachine() {
52 { "type": "tool", "id": "prt_2", "messageID": "msg_1", "callID": "c1", "tool": "bash",
53 "state": { "status": "completed", "output": "done", "title": "ran bash" } }
55 val part = decode(Part.serializer(), json) as ToolPart
56 assertEquals("bash", part.tool)
57 assertEquals("done", (part.state as ToolCompleted).output)
61 fun decodesPartUpdatedEvent() {
63 { "type": "message.part.updated",
64 "properties": { "part": { "type": "text", "id": "prt_1", "messageID": "msg_1", "text": "Hel" } } }
66 val event = decode(BusEvent.serializer(), json) as MessagePartUpdated
67 assertEquals("Hel", (event.properties.part as TextPart).text)
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)
78 fun unknownEventTypeFallsBackInsteadOfThrowing() {
79 val event = decode(BusEvent.serializer(), """{"type":"some.future.event","properties":{"x":1}}""")
80 assertEquals(UnknownEvent, event)
84 fun unknownPartTypeFallsBackInsteadOfThrowing() {
85 val part = decode(Part.serializer(), """{"type":"future-part","id":"p9","foo":true}""")
86 assertTrue(part is UnknownPart)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list