diff --git a/tools/computer_use/schema.py b/tools/computer_use/schema.py index b83ab60f6047..22259377ca7c 100644 --- a/tools/computer_use/schema.py +++ b/tools/computer_use/schema.py @@ -230,6 +230,17 @@ COMPUTER_USE_SCHEMA: Dict[str, Any] = { }, }, "required": ["action"], + "allOf": [ + { + "if": { + "properties": {"action": {"const": "switch_desktop"}}, + "required": ["action"], + }, + "then": { + "required": ["direction"], + }, + }, + ], }, } diff --git a/tools/computer_use/tool.py b/tools/computer_use/tool.py index e4be71b8f0c1..c83183b62230 100644 --- a/tools/computer_use/tool.py +++ b/tools/computer_use/tool.py @@ -431,7 +431,7 @@ def _dispatch(backend: ComputerUseBackend, action: str, args: Dict[str, Any]) -> if not hasattr(backend, "switch_desktop"): return json.dumps({"error": "switch_desktop not supported by current backend"}) res = backend.switch_desktop(str(direction)) - return json.dumps({"ok": res.ok, "message": res.message}) + return _maybe_follow_capture(backend, res, capture_after) return json.dumps({"error": f"unknown action {action!r}"}) diff --git a/tools/computer_use/windows_backend.py b/tools/computer_use/windows_backend.py index 62db4bb4c10c..f9e878f29182 100644 --- a/tools/computer_use/windows_backend.py +++ b/tools/computer_use/windows_backend.py @@ -302,6 +302,9 @@ def _switch_desktop_via_keybd(direction: str, overlay_client) -> bool: virtual-desktop transition, so we stop it before switching and restart it on the new desktop. """ + if direction not in ("left", "right"): + return False + VK_CONTROL = 0x11 VK_LWIN = 0x5B VK_LEFT = 0x25 @@ -322,15 +325,19 @@ def _switch_desktop_via_keybd(direction: str, overlay_client) -> bool: try: overlay_client.stop() _send_inputs(seq) + # The virtual-desktop transition is asynchronous — a brief delay + # before restarting the overlay avoids racing the DWM compositor. + time.sleep(0.15) overlay_client._dead = False overlay_client.start() return True - except Exception: + except Exception as e: + logger.warning("switch_desktop SendInput failed: %s", e) try: overlay_client._dead = False overlay_client.start() - except Exception: - pass + except Exception as e2: + logger.warning("switch_desktop overlay restart also failed: %s", e2) return False