mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-20 21:23:23 +00:00
feat: auto-send Android assistant prompts
This commit is contained in:
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user