fix(cua): remove send action — LLM taps send button via coordinates from screenshot instead
This commit is contained in:
@@ -378,27 +378,7 @@ def execute_action(action: dict) -> str:
|
|||||||
return f"swiped ({x1},{y1})->({x2},{y2})"
|
return f"swiped ({x1},{y1})->({x2},{y2})"
|
||||||
|
|
||||||
elif act == "send":
|
elif act == "send":
|
||||||
# First dismiss keyboard if visible (ESCAPE=111 is safe, unlike BACK which navigates)
|
return "`send` action is deprecated — use tap with coordinates instead"
|
||||||
adb("shell", "input", "keyevent", "111")
|
|
||||||
time.sleep(0.5)
|
|
||||||
# Auto-locate send button: rightmost clickable button in the bottom input bar.
|
|
||||||
_, screen_h = get_screen_size()
|
|
||||||
bottom_threshold = int(screen_h * 0.60)
|
|
||||||
xml = ui_dump()
|
|
||||||
matches = re.findall(r'clickable="true"[^>]*bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"', xml)
|
|
||||||
bottom_buttons = [(int(x1), int(y1), int(x2), int(y2)) for x1, y1, x2, y2 in matches if int(y1) > bottom_threshold]
|
|
||||||
if bottom_buttons:
|
|
||||||
send_btn = max(bottom_buttons, key=lambda b: (b[0] + b[2]) // 2)
|
|
||||||
cx = (send_btn[0] + send_btn[2]) // 2
|
|
||||||
cy = (send_btn[1] + send_btn[3]) // 2
|
|
||||||
adb("shell", "input", "tap", str(cx), str(cy))
|
|
||||||
return f"send button tapped ({cx}, {cy})"
|
|
||||||
# Fallback: tap bottom-right area
|
|
||||||
screen_w, _ = get_screen_size()
|
|
||||||
fx = screen_w - 32
|
|
||||||
fy = screen_h - 48
|
|
||||||
adb("shell", "input", "tap", str(fx), str(fy))
|
|
||||||
return f"send button tapped (fallback {fx}, {fy})"
|
|
||||||
|
|
||||||
elif act == "wait":
|
elif act == "wait":
|
||||||
secs = float(action.get("seconds", 2))
|
secs = float(action.get("seconds", 2))
|
||||||
@@ -436,7 +416,6 @@ Available actions:
|
|||||||
{"type": "type", "text": "<string>"}
|
{"type": "type", "text": "<string>"}
|
||||||
{"type": "key", "key": "enter|back|home|delete|tab"}
|
{"type": "key", "key": "enter|back|home|delete|tab"}
|
||||||
{"type": "swipe", "x1": <int>, "y1": <int>, "x2": <int>, "y2": <int>, "duration": <ms>}
|
{"type": "swipe", "x1": <int>, "y1": <int>, "x2": <int>, "y2": <int>, "duration": <ms>}
|
||||||
{"type": "send"} -- tap the send/submit button (auto-locates via UI hierarchy)
|
|
||||||
{"type": "wait", "seconds": <float>}
|
{"type": "wait", "seconds": <float>}
|
||||||
{"type": "screenshot", "label": "<tag>"} -- observe current state without acting
|
{"type": "screenshot", "label": "<tag>"} -- observe current state without acting
|
||||||
{"type": "done", "summary": "<what was accomplished>"}
|
{"type": "done", "summary": "<what was accomplished>"}
|
||||||
@@ -444,13 +423,15 @@ Available actions:
|
|||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
- Issue exactly ONE action per turn as a JSON object. No markdown, no explanation outside JSON.
|
- Issue exactly ONE action per turn as a JSON object. No markdown, no explanation outside JSON.
|
||||||
- Coordinates are in pixels relative to the screenshot dimensions.
|
- Coordinates are in pixels relative to the screenshot dimensions. YOU provide the coordinates.
|
||||||
- IMPORTANT: In this app, pressing "enter" inserts a newline — it does NOT send the message.
|
- IMPORTANT: In this app, pressing "enter" inserts a newline — it does NOT send the message.
|
||||||
To send a message use {"type": "send"} which auto-locates and taps the send/arrow button.
|
There is NO "send" action. To send a message, use {"type": "tap", "x": ..., "y": ...}
|
||||||
Do NOT press "back" after typing — it will navigate away.
|
with coordinates from the screenshot pointing at the send/submit button (usually bottom-right).
|
||||||
The "send" action handles keyboard dismissal internally, so you don't need to dismiss it manually.
|
- Do NOT press "back" after typing — it will navigate away from the session.
|
||||||
If the text input is already focused (cursor visible), type directly without tapping it first.
|
- If the keyboard appears after tapping the text input and blocks the send button,
|
||||||
Only tap the input if you see no cursor/blinking indicator.
|
first tap a blank area above the keyboard (not on the keyboard) to dismiss it,
|
||||||
|
THEN tap the send button. Or: tap the send button from memory if it was visible before the keyboard appeared.
|
||||||
|
- If the text input is already focused (cursor visible), type directly without tapping it first.
|
||||||
- Be efficient: skip unnecessary waits, tap directly on visible targets.
|
- Be efficient: skip unnecessary waits, tap directly on visible targets.
|
||||||
- When the goal is fully achieved respond with {"type": "done", "summary": "..."}.
|
- When the goal is fully achieved respond with {"type": "done", "summary": "..."}.
|
||||||
- If genuinely stuck after 5+ attempts on the same element respond with {"type": "fail", ...}.
|
- If genuinely stuck after 5+ attempts on the same element respond with {"type": "fail", ...}.
|
||||||
@@ -727,7 +708,7 @@ def run_onboarding_showcase(
|
|||||||
f"Tap the text input field. "
|
f"Tap the text input field. "
|
||||||
f"Type this exact message: {TYPESCRIPT_TASK!r} "
|
f"Type this exact message: {TYPESCRIPT_TASK!r} "
|
||||||
"Do NOT press back (it navigates away). "
|
"Do NOT press back (it navigates away). "
|
||||||
"Use the send action to submit. "
|
"Tap the send/arrow button (bottom-right) to submit. "
|
||||||
"After sending, wait and watch — opencode will show tool calls and file writes as it works. "
|
"After sending, wait and watch — opencode will show tool calls and file writes as it works. "
|
||||||
"Wait up to 90 seconds total for the session to go idle/complete "
|
"Wait up to 90 seconds total for the session to go idle/complete "
|
||||||
"(no new activity for at least 5 seconds, or a completion indicator appears). "
|
"(no new activity for at least 5 seconds, or a completion indicator appears). "
|
||||||
@@ -794,10 +775,11 @@ SMOKE_SCENARIOS = [
|
|||||||
"name": "coding_task",
|
"name": "coding_task",
|
||||||
"goal": (
|
"goal": (
|
||||||
"You see the OpenCode mobile app. Tap the '+' button (top-right) to create a new session. "
|
"You see the OpenCode mobile app. Tap the '+' button (top-right) to create a new session. "
|
||||||
|
"Wait 3 seconds for the new session/chat screen to fully load. "
|
||||||
"Tap the text input at the bottom. "
|
"Tap the text input at the bottom. "
|
||||||
f"Type this exact task: {PYTHON_CODING_TASK!r} "
|
f"Type this exact task: {PYTHON_CODING_TASK!r} "
|
||||||
"Do NOT press back (it navigates away). "
|
"Do NOT press back (it navigates away). "
|
||||||
"Use the send action to submit the task. "
|
"Tap the send/arrow button (bottom-right) to submit the task. "
|
||||||
"After sending, wait and watch — opencode will think and then produce code. "
|
"After sending, wait and watch — opencode will think and then produce code. "
|
||||||
"Wait up to 120 seconds total for the session to complete "
|
"Wait up to 120 seconds total for the session to complete "
|
||||||
"(look for file creation messages, a summary from assistant, or 'idle' status). "
|
"(look for file creation messages, a summary from assistant, or 'idle' status). "
|
||||||
|
|||||||
Reference in New Issue
Block a user