davidliu
Committed by GitHub

Add types for agent and transcription attributes (#733)

  1 +---
  2 +"client-sdk-android": minor
  3 +---
  4 +
  5 +Add types for agent and transcription attributes
@@ -14,6 +14,7 @@ dagger = "2.46" @@ -14,6 +14,7 @@ dagger = "2.46"
14 groupie = "2.9.0" 14 groupie = "2.9.0"
15 junit-lib = "4.13.2" 15 junit-lib = "4.13.2"
16 junit-jupiter = "5.5.0" 16 junit-jupiter = "5.5.0"
  17 +klaxon = "5.5"
17 kotlinx-serialization = "1.5.0" 18 kotlinx-serialization = "1.5.0"
18 leakcanaryAndroid = "2.8.1" 19 leakcanaryAndroid = "2.8.1"
19 lint = "30.0.1" 20 lint = "30.0.1"
@@ -48,6 +49,7 @@ dagger-lib = { module = "com.google.dagger:dagger", version.ref = "dagger" } @@ -48,6 +49,7 @@ dagger-lib = { module = "com.google.dagger:dagger", version.ref = "dagger" }
48 dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } 49 dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" }
49 groupie = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" } 50 groupie = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" }
50 groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" } 51 groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" }
  52 +klaxon = { module = "com.beust:klaxon", version.ref = "klaxon" }
51 noise = { module = "com.github.paramsen:noise", version.ref = "noise" } 53 noise = { module = "com.github.paramsen:noise", version.ref = "noise" }
52 androidx-lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidx-lifecycle" } 54 androidx-lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidx-lifecycle" }
53 androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } 55 androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
@@ -148,6 +148,8 @@ dependencies { @@ -148,6 +148,8 @@ dependencies {
148 api libs.okhttp.lib 148 api libs.okhttp.lib
149 implementation libs.okhttp.coroutines 149 implementation libs.okhttp.coroutines
150 api libs.audioswitch 150 api libs.audioswitch
  151 + implementation libs.klaxon
  152 +
151 implementation libs.androidx.annotation 153 implementation libs.androidx.annotation
152 implementation libs.androidx.core 154 implementation libs.androidx.core
153 implementation libs.protobuf.javalite 155 implementation libs.protobuf.javalite
  1 +/*
  2 + * Copyright 2025 LiveKit, Inc.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package io.livekit.android.room.types
  18 +
  19 +import com.beust.klaxon.Converter
  20 +import com.beust.klaxon.Json
  21 +import com.beust.klaxon.JsonValue
  22 +import com.beust.klaxon.Klaxon
  23 +
  24 +private fun <T> Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =
  25 + this.converter(
  26 + object : Converter {
  27 + @Suppress("UNCHECKED_CAST")
  28 + override fun toJson(value: Any) = toJson(value as T)
  29 + override fun fromJson(jv: JsonValue) = fromJson(jv) as Any
  30 + override fun canConvert(cls: Class<*>) = cls == k.java || (isUnion && cls.superclass == k.java)
  31 + },
  32 + )
  33 +
  34 +private val klaxon = Klaxon()
  35 + .convert(AgentInput::class, { AgentInput.fromValue(it.string!!) }, { "\"${it.value}\"" })
  36 + .convert(AgentOutput::class, { AgentOutput.fromValue(it.string!!) }, { "\"${it.value}\"" })
  37 + .convert(AgentState::class, { AgentState.fromValue(it.string!!) }, { "\"${it.value}\"" })
  38 +
  39 +data class AgentAttributes(
  40 + @Json(name = "lk.agent.inputs")
  41 + val lkAgentInputs: List<AgentInput>? = null,
  42 +
  43 + @Json(name = "lk.agent.outputs")
  44 + val lkAgentOutputs: List<AgentOutput>? = null,
  45 +
  46 + @Json(name = "lk.agent.state")
  47 + val lkAgentState: AgentState? = null,
  48 +
  49 + @Json(name = "lk.publish_on_behalf")
  50 + val lkPublishOnBehalf: String? = null,
  51 +) {
  52 + fun toJson() = klaxon.toJsonString(this)
  53 +
  54 + companion object {
  55 + fun fromJson(json: String) = klaxon.parse<AgentAttributes>(json)
  56 + }
  57 +}
  58 +
  59 +enum class AgentInput(val value: String) {
  60 + Audio("audio"),
  61 + Text("text"),
  62 + Video("video");
  63 +
  64 + companion object {
  65 + fun fromValue(value: String): AgentInput = when (value) {
  66 + "audio" -> Audio
  67 + "text" -> Text
  68 + "video" -> Video
  69 + else -> throw IllegalArgumentException()
  70 + }
  71 + }
  72 +}
  73 +
  74 +enum class AgentOutput(val value: String) {
  75 + Audio("audio"),
  76 + Transcription("transcription");
  77 +
  78 + companion object {
  79 + fun fromValue(value: String): AgentOutput = when (value) {
  80 + "audio" -> Audio
  81 + "transcription" -> Transcription
  82 + else -> throw IllegalArgumentException()
  83 + }
  84 + }
  85 +}
  86 +
  87 +enum class AgentState(val value: String) {
  88 + Idle("idle"),
  89 + Initializing("initializing"),
  90 + Listening("listening"),
  91 + Speaking("speaking"),
  92 + Thinking("thinking");
  93 +
  94 + companion object {
  95 + fun fromValue(value: String): AgentState = when (value) {
  96 + "idle" -> Idle
  97 + "initializing" -> Initializing
  98 + "listening" -> Listening
  99 + "speaking" -> Speaking
  100 + "thinking" -> Thinking
  101 + else -> throw IllegalArgumentException()
  102 + }
  103 + }
  104 +}
  105 +
  106 +/**
  107 + * Schema for transcription-related attributes
  108 + */
  109 +data class TranscriptionAttributes(
  110 + /**
  111 + * The segment id of the transcription
  112 + */
  113 + @Json(name = "lk.segment_id")
  114 + val lkSegmentID: String? = null,
  115 +
  116 + /**
  117 + * The associated track id of the transcription
  118 + */
  119 + @Json(name = "lk.transcribed_track_id")
  120 + val lkTranscribedTrackID: String? = null,
  121 +
  122 + /**
  123 + * Whether the transcription is final
  124 + */
  125 + @Json(name = "lk.transcription_final")
  126 + val lkTranscriptionFinal: Boolean? = null,
  127 +) {
  128 + fun toJson() = klaxon.toJsonString(this)
  129 +
  130 + companion object {
  131 + fun fromJson(json: String) = klaxon.parse<TranscriptionAttributes>(json)
  132 + }
  133 +}