feat(ui): add Bots and Groups tab strip with GroupCard and disband action (#987)
This commit is contained in:
9 files changed
+497
-92
No files matched your search
@@ -69,8 +69,8 @@ data class CanonicalSessionInfo(
|
||||
val root_title: String? = null,
|
||||
val title: String? = null,
|
||||
val preview: String? = null,
|
||||
val started_at: Long? = null,
|
||||
val last_active: Long? = null,
|
||||
val started_at: Double? = null,
|
||||
val last_active: Double? = null,
|
||||
val message_count: Int? = null,
|
||||
)
|
||||
|
||||
@@ -79,8 +79,8 @@ data class ProfileSessionSummary(
|
||||
val id: String,
|
||||
val title: String? = null,
|
||||
val preview: String? = null,
|
||||
val started_at: Long? = null,
|
||||
val last_active: Long? = null,
|
||||
val started_at: Double? = null,
|
||||
val last_active: Double? = null,
|
||||
val message_count: Int? = null,
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ data class ProfileWorkerSummary(
|
||||
val id: String,
|
||||
val source: String? = null,
|
||||
val title: String? = null,
|
||||
val last_active: Long? = null,
|
||||
val last_active: Double? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@@ -100,7 +100,7 @@ data class BotRosterMeta(
|
||||
val hidden: Boolean? = null,
|
||||
val groups: List<String>? = null,
|
||||
val group: String? = null,
|
||||
val created: Long? = null,
|
||||
val created: Double? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -939,6 +939,16 @@ object HermesWsClient {
|
||||
val event =
|
||||
try {
|
||||
val rpc = OkHttpProvider.json.decodeFromString<JsonRpcResponse>(text)
|
||||
// Resolve pending request() calls with the RAW JsonElement from
|
||||
// rpc.result, BEFORE EventParser.parse() converts it via toAny().
|
||||
// This preserves integer/float type fidelity needed by callers
|
||||
// that re-deserialize the result into typed data classes.
|
||||
val rpcId = rpc.id
|
||||
if (rpcId != null && rpc.error == null && rpc.result != null) {
|
||||
synchronized(outboundLock) { pendingPromptSubmits.remove(rpcId) }
|
||||
removeQueuedMessage(rpcId)
|
||||
resolvePending(rpcId, rpc.result, null)
|
||||
}
|
||||
val parsed = EventParser.parse(rpc, text)
|
||||
if (parsed is WsEvent.MessageComplete) {
|
||||
parsed.copy(
|
||||
|
||||
@@ -8,6 +8,7 @@ import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.booleanOrNull
|
||||
import kotlinx.serialization.json.doubleOrNull
|
||||
import kotlinx.serialization.json.intOrNull
|
||||
import kotlinx.serialization.json.longOrNull
|
||||
|
||||
/**
|
||||
@@ -46,6 +47,19 @@ fun Any?.toJsonElement(): JsonElement =
|
||||
null -> JsonNull
|
||||
is JsonElement -> this
|
||||
is Boolean -> JsonPrimitive(this)
|
||||
is Int -> JsonPrimitive(this)
|
||||
is Long -> JsonPrimitive(this)
|
||||
is Float -> JsonPrimitive(this)
|
||||
is Double -> {
|
||||
// Preserve integer semantics: 177.0 → JsonPrimitive(177) not "177.0"
|
||||
if (this % 1.0 == 0.0 && this >= Int.MIN_VALUE.toDouble() && this <= Int.MAX_VALUE.toDouble()) {
|
||||
JsonPrimitive(this.toInt())
|
||||
} else if (this % 1.0 == 0.0 && this >= Long.MIN_VALUE.toDouble() && this <= Long.MAX_VALUE.toDouble()) {
|
||||
JsonPrimitive(this.toLong())
|
||||
} else {
|
||||
JsonPrimitive(this)
|
||||
}
|
||||
}
|
||||
is Number -> JsonPrimitive(this)
|
||||
is String -> JsonPrimitive(this)
|
||||
is Map<*, *> -> JsonObject(this.map { it.key.toString() to it.value.toJsonElement() }.toMap())
|
||||
@@ -63,7 +77,7 @@ fun JsonElement.toAny(): Any? =
|
||||
if (isString) {
|
||||
content
|
||||
} else {
|
||||
booleanOrNull ?: doubleOrNull ?: longOrNull ?: content
|
||||
booleanOrNull ?: intOrNull ?: longOrNull ?: doubleOrNull ?: content
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user