mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:50:43 +00:00
refactor(android): unify invoke error parsing
This commit is contained in:
@@ -535,16 +535,8 @@ class GatewaySession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun invokeErrorFromThrowable(err: Throwable): InvokeResult {
|
private fun invokeErrorFromThrowable(err: Throwable): InvokeResult {
|
||||||
val msg = err.message?.trim().takeIf { !it.isNullOrEmpty() } ?: err::class.java.simpleName
|
val parsed = parseInvokeErrorFromThrowable(err, fallbackMessage = err::class.java.simpleName)
|
||||||
val parts = msg.split(":", limit = 2)
|
return InvokeResult.error(code = parsed.code, message = parsed.message)
|
||||||
if (parts.size == 2) {
|
|
||||||
val code = parts[0].trim()
|
|
||||||
val rest = parts[1].trim()
|
|
||||||
if (code.isNotEmpty() && code.all { it.isUpperCase() || it == '_' }) {
|
|
||||||
return InvokeResult.error(code = code, message = rest.ifEmpty { msg })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return InvokeResult.error(code = "UNAVAILABLE", message = msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun failPending() {
|
private fun failPending() {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package ai.openclaw.android.gateway
|
||||||
|
|
||||||
|
data class ParsedInvokeError(
|
||||||
|
val code: String,
|
||||||
|
val message: String,
|
||||||
|
val hadExplicitCode: Boolean,
|
||||||
|
) {
|
||||||
|
val prefixedMessage: String
|
||||||
|
get() = "$code: $message"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseInvokeErrorMessage(raw: String): ParsedInvokeError {
|
||||||
|
val trimmed = raw.trim()
|
||||||
|
if (trimmed.isEmpty()) {
|
||||||
|
return ParsedInvokeError(code = "UNAVAILABLE", message = "error", hadExplicitCode = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val parts = trimmed.split(":", limit = 2)
|
||||||
|
if (parts.size == 2) {
|
||||||
|
val code = parts[0].trim()
|
||||||
|
val rest = parts[1].trim()
|
||||||
|
if (code.isNotEmpty() && code.all { it.isUpperCase() || it == '_' }) {
|
||||||
|
return ParsedInvokeError(
|
||||||
|
code = code,
|
||||||
|
message = rest.ifEmpty { trimmed },
|
||||||
|
hadExplicitCode = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ParsedInvokeError(code = "UNAVAILABLE", message = trimmed, hadExplicitCode = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseInvokeErrorFromThrowable(
|
||||||
|
err: Throwable,
|
||||||
|
fallbackMessage: String = "error",
|
||||||
|
): ParsedInvokeError {
|
||||||
|
val raw = err.message?.trim().takeIf { !it.isNullOrEmpty() } ?: fallbackMessage
|
||||||
|
return parseInvokeErrorMessage(raw)
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package ai.openclaw.android.node
|
package ai.openclaw.android.node
|
||||||
|
|
||||||
|
import ai.openclaw.android.gateway.parseInvokeErrorFromThrowable
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.JsonNull
|
import kotlinx.serialization.json.JsonNull
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
@@ -37,14 +38,9 @@ fun parseHexColorArgb(raw: String?): Long? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun invokeErrorFromThrowable(err: Throwable): Pair<String, String> {
|
fun invokeErrorFromThrowable(err: Throwable): Pair<String, String> {
|
||||||
val raw = (err.message ?: "").trim()
|
val parsed = parseInvokeErrorFromThrowable(err, fallbackMessage = "UNAVAILABLE: error")
|
||||||
if (raw.isEmpty()) return "UNAVAILABLE" to "UNAVAILABLE: error"
|
val message = if (parsed.hadExplicitCode) parsed.prefixedMessage else parsed.message
|
||||||
|
return parsed.code to message
|
||||||
val idx = raw.indexOf(':')
|
|
||||||
if (idx <= 0) return "UNAVAILABLE" to raw
|
|
||||||
val code = raw.substring(0, idx).trim().ifEmpty { "UNAVAILABLE" }
|
|
||||||
val message = raw.substring(idx + 1).trim().ifEmpty { raw }
|
|
||||||
return code to "$code: $message"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun normalizeMainKey(raw: String?): String? {
|
fun normalizeMainKey(raw: String?): String? {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package ai.openclaw.android.gateway
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class InvokeErrorParserTest {
|
||||||
|
@Test
|
||||||
|
fun parseInvokeErrorMessage_parsesUppercaseCodePrefix() {
|
||||||
|
val parsed = parseInvokeErrorMessage("CAMERA_PERMISSION_REQUIRED: grant Camera permission")
|
||||||
|
assertEquals("CAMERA_PERMISSION_REQUIRED", parsed.code)
|
||||||
|
assertEquals("grant Camera permission", parsed.message)
|
||||||
|
assertTrue(parsed.hadExplicitCode)
|
||||||
|
assertEquals("CAMERA_PERMISSION_REQUIRED: grant Camera permission", parsed.prefixedMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseInvokeErrorMessage_rejectsNonCanonicalCodePrefix() {
|
||||||
|
val parsed = parseInvokeErrorMessage("IllegalStateException: boom")
|
||||||
|
assertEquals("UNAVAILABLE", parsed.code)
|
||||||
|
assertEquals("IllegalStateException: boom", parsed.message)
|
||||||
|
assertFalse(parsed.hadExplicitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseInvokeErrorFromThrowable_usesFallbackWhenMessageMissing() {
|
||||||
|
val parsed = parseInvokeErrorFromThrowable(IllegalStateException(), fallbackMessage = "fallback")
|
||||||
|
assertEquals("UNAVAILABLE", parsed.code)
|
||||||
|
assertEquals("fallback", parsed.message)
|
||||||
|
assertFalse(parsed.hadExplicitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user