diff --git a/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt b/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt index 02e9b136091..8cb2b0b47dc 100644 --- a/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt +++ b/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt @@ -131,6 +131,8 @@ class NodeRuntime(context: Context) { isForeground = { _isForeground.value }, cameraEnabled = { cameraEnabled.value }, locationEnabled = { locationMode.value != LocationMode.Off }, + smsAvailable = { sms.canSendSms() }, + debugBuild = { BuildConfig.DEBUG }, onCanvasA2uiPush = { _canvasA2uiHydrated.value = true _canvasRehydratePending.value = false diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt index 0e58517f2f6..d293df76668 100644 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt +++ b/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt @@ -20,6 +20,8 @@ class InvokeDispatcher( private val isForeground: () -> Boolean, private val cameraEnabled: () -> Boolean, private val locationEnabled: () -> Boolean, + private val smsAvailable: () -> Boolean, + private val debugBuild: () -> Boolean, private val onCanvasA2uiPush: () -> Unit, private val onCanvasA2uiReset: () -> Unit, ) { @@ -36,18 +38,7 @@ class InvokeDispatcher( message = "NODE_BACKGROUND_UNAVAILABLE: canvas/camera/screen commands require foreground", ) } - if (spec.availability == InvokeCommandAvailability.CameraEnabled && !cameraEnabled()) { - return GatewaySession.InvokeResult.error( - code = "CAMERA_DISABLED", - message = "CAMERA_DISABLED: enable Camera in Settings", - ) - } - if (spec.availability == InvokeCommandAvailability.LocationEnabled && !locationEnabled()) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_DISABLED", - message = "LOCATION_DISABLED: enable Location in Settings", - ) - } + availabilityError(spec.availability)?.let { return it } return when (command) { // Canvas commands @@ -170,4 +161,46 @@ class InvokeDispatcher( ) } } + + private fun availabilityError(availability: InvokeCommandAvailability): GatewaySession.InvokeResult? { + return when (availability) { + InvokeCommandAvailability.Always -> null + InvokeCommandAvailability.CameraEnabled -> + if (cameraEnabled()) { + null + } else { + GatewaySession.InvokeResult.error( + code = "CAMERA_DISABLED", + message = "CAMERA_DISABLED: enable Camera in Settings", + ) + } + InvokeCommandAvailability.LocationEnabled -> + if (locationEnabled()) { + null + } else { + GatewaySession.InvokeResult.error( + code = "LOCATION_DISABLED", + message = "LOCATION_DISABLED: enable Location in Settings", + ) + } + InvokeCommandAvailability.SmsAvailable -> + if (smsAvailable()) { + null + } else { + GatewaySession.InvokeResult.error( + code = "SMS_UNAVAILABLE", + message = "SMS_UNAVAILABLE: SMS not available on this device", + ) + } + InvokeCommandAvailability.DebugBuild -> + if (debugBuild()) { + null + } else { + GatewaySession.InvokeResult.error( + code = "INVALID_REQUEST", + message = "INVALID_REQUEST: unknown command", + ) + } + } + } }