feat: auto-send Android assistant prompts

This commit is contained in:
Ayaan Zaidi
2026-04-02 19:56:24 +05:30
parent 4207ca2eb8
commit 186647cb74
5 changed files with 73 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ enum class HomeDestination {
data class AssistantLaunchRequest(
val source: String,
val prompt: String?,
val autoSend: Boolean,
)
fun parseAssistantLaunchIntent(intent: Intent?): AssistantLaunchRequest? {
@@ -25,6 +26,7 @@ fun parseAssistantLaunchIntent(intent: Intent?): AssistantLaunchRequest? {
AssistantLaunchRequest(
source = "assist",
prompt = null,
autoSend = false,
)
actionAskOpenClaw -> {
@@ -32,6 +34,7 @@ fun parseAssistantLaunchIntent(intent: Intent?): AssistantLaunchRequest? {
AssistantLaunchRequest(
source = "app_action",
prompt = prompt,
autoSend = prompt != null,
)
}

View File

@@ -31,6 +31,8 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
val requestedHomeDestination: StateFlow<HomeDestination?> = _requestedHomeDestination
private val _chatDraft = MutableStateFlow<String?>(null)
val chatDraft: StateFlow<String?> = _chatDraft
private val _pendingAssistantAutoSend = MutableStateFlow<String?>(null)
val pendingAssistantAutoSend: StateFlow<String?> = _pendingAssistantAutoSend
private fun ensureRuntime(): NodeRuntime {
runtimeRef.value?.let { return it }
@@ -252,6 +254,11 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
fun handleAssistantLaunch(request: AssistantLaunchRequest) {
_requestedHomeDestination.value = HomeDestination.Chat
if (request.autoSend) {
_pendingAssistantAutoSend.value = request.prompt
_chatDraft.value = null
return
}
_chatDraft.value = request.prompt
}
@@ -263,6 +270,10 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
_chatDraft.value = null
}
fun clearPendingAssistantAutoSend() {
_pendingAssistantAutoSend.value = null
}
fun setMicEnabled(enabled: Boolean) {
ensureRuntime().setMicEnabled(enabled)
}

View File

@@ -48,6 +48,16 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
internal fun resolvePendingAssistantAutoSend(
pendingPrompt: String?,
healthOk: Boolean,
pendingRunCount: Int,
): String? {
val prompt = pendingPrompt?.trim()?.ifEmpty { null } ?: return null
if (!healthOk || pendingRunCount > 0) return null
return prompt
}
@Composable
fun ChatSheetContent(viewModel: MainViewModel) {
val messages by viewModel.chatMessages.collectAsState()
@@ -61,11 +71,23 @@ fun ChatSheetContent(viewModel: MainViewModel) {
val pendingToolCalls by viewModel.chatPendingToolCalls.collectAsState()
val sessions by viewModel.chatSessions.collectAsState()
val chatDraft by viewModel.chatDraft.collectAsState()
val pendingAssistantAutoSend by viewModel.pendingAssistantAutoSend.collectAsState()
LaunchedEffect(Unit) {
viewModel.loadChat(mainSessionKey)
}
LaunchedEffect(pendingAssistantAutoSend, healthOk, pendingRunCount, thinkingLevel) {
val prompt =
resolvePendingAssistantAutoSend(
pendingPrompt = pendingAssistantAutoSend,
healthOk = healthOk,
pendingRunCount = pendingRunCount,
) ?: return@LaunchedEffect
viewModel.sendChat(message = prompt, thinking = thinkingLevel, attachments = emptyList())
viewModel.clearPendingAssistantAutoSend()
}
val context = LocalContext.current
val resolver = context.contentResolver
val scope = rememberCoroutineScope()

View File

@@ -2,7 +2,9 @@ package ai.openclaw.app
import android.content.Intent
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@@ -18,6 +20,7 @@ class AssistantLaunchTest {
requireNotNull(parsed)
assertEquals("assist", parsed.source)
assertNull(parsed.prompt)
assertFalse(parsed.autoSend)
}
@Test
@@ -30,6 +33,7 @@ class AssistantLaunchTest {
requireNotNull(parsed)
assertEquals("app_action", parsed.source)
assertEquals("summarize my unread texts", parsed.prompt)
assertTrue(parsed.autoSend)
}
@Test

View File

@@ -0,0 +1,33 @@
package ai.openclaw.app.ui.chat
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
class ChatSheetContentTest {
@Test
fun resolvesPendingAssistantAutoSendOnlyWhenChatIsReady() {
assertNull(
resolvePendingAssistantAutoSend(
pendingPrompt = "summarize mail",
healthOk = false,
pendingRunCount = 0,
),
)
assertNull(
resolvePendingAssistantAutoSend(
pendingPrompt = "summarize mail",
healthOk = true,
pendingRunCount = 1,
),
)
assertEquals(
"summarize mail",
resolvePendingAssistantAutoSend(
pendingPrompt = " summarize mail ",
healthOk = true,
pendingRunCount = 0,
),
)
}
}