Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/scripts/modal_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ def sync_to_s3(bucket: str = S3_BUCKET_NAME):
key = f"docs_db/docs.lance/{fpath.relative_to(lance_dir)}"
s3.upload_file(str(fpath), bucket, key)
uploaded += 1
print(f" Uploaded docs LanceDB directory")
print(" Uploaded docs LanceDB directory")

# --- code databases ---
code_db_dir = Path(CODE_DB_PATH)
Expand All @@ -411,7 +411,7 @@ def sync_to_s3(bucket: str = S3_BUCKET_NAME):
key = f"code_db/code_index.lancedb/{fpath.relative_to(code_lance)}"
s3.upload_file(str(fpath), bucket, key)
uploaded += 1
print(f" Uploaded code LanceDB directory")
print(" Uploaded code LanceDB directory")

print(f"S3 sync complete: {uploaded} files uploaded to s3://{bucket}/")
return {"bucket": bucket, "files_uploaded": uploaded}
Expand Down
4 changes: 3 additions & 1 deletion examples/sandboxes/test_linux_cloud_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ async def test_linux_cloud_vm():
len(screenshot),
time.monotonic() - t2,
)
assert screenshot[:4] == b"\x89PNG", f"Screenshot not PNG: first 4 bytes = {screenshot[:4]!r}"
assert (
screenshot[:4] == b"\x89PNG"
), f"Screenshot not PNG: first 4 bytes = {screenshot[:4]!r}"

total_time = time.monotonic() - t0
logger.info("Test passed in %.1fs (provision=%.1fs)", total_time, provision_time)
Expand Down
7 changes: 2 additions & 5 deletions libs/cua-driver-rs/tests/integration/driver_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ def _notify(self, method: str, params: Optional[dict] = None) -> None:
payload["params"] = params
self._write(payload)

def _call(
self, method: str, params: Optional[dict] = None, timeout: float = 20.0
) -> dict:
def _call(self, method: str, params: Optional[dict] = None, timeout: float = 20.0) -> dict:
self._next_id += 1
request_id = self._next_id
payload = {"jsonrpc": "2.0", "id": request_id, "method": method}
Expand Down Expand Up @@ -198,8 +196,7 @@ def resolve_window_id(

if require_on_current_space:
preferred = [
w for w in windows
if w.get("is_on_screen") and w.get("on_current_space") is not False
w for w in windows if w.get("is_on_screen") and w.get("on_current_space") is not False
]
if preferred:
preferred.sort(key=lambda w: w.get("z_index", 0), reverse=True)
Expand Down
85 changes: 48 additions & 37 deletions libs/cua-driver-rs/tests/integration/test_api_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

# ── helpers ────────────────────────────────────────────────────────────────────


def _run(
args: list[str],
timeout: int = 20,
Expand Down Expand Up @@ -129,9 +130,9 @@ def _swift_binary() -> str | None:

# In Rust, not in Swift yet. Tests for these will fail on the Swift binary.
RUST_ONLY_TOOLS = [
"type_text_chars", # per-character delay typing; Swift uses type_text
"browser_eval", # CDP JS eval; Swift uses 'page' for browser JS
"get_accessibility_tree",# lightweight desktop AX snapshot (separate from get_window_state)
"type_text_chars", # per-character delay typing; Swift uses type_text
"browser_eval", # CDP JS eval; Swift uses 'page' for browser JS
"get_accessibility_tree", # lightweight desktop AX snapshot (separate from get_window_state)
]

# In Swift, not registered in Rust yet (page.rs exists but not in register_all).
Expand All @@ -142,6 +143,7 @@ def _swift_binary() -> str | None:

# ── parity mixin ───────────────────────────────────────────────────────────────


class _ParityMixin:
"""All API surface tests. Concrete subclasses set `cls.binary`."""

Expand Down Expand Up @@ -185,8 +187,14 @@ def test_list_tools_contains_required_tool_names(self) -> None:
r = _run([self.binary, "list-tools"])
self.assertEqual(r.returncode, 0)
for name in [
"click", "screenshot", "list_windows", "press_key",
"get_window_state", "type_text", "hotkey", "scroll",
"click",
"screenshot",
"list_windows",
"press_key",
"get_window_state",
"type_text",
"hotkey",
"scroll",
]:
self.assertIn(name, r.stdout, f"list-tools missing: {name!r}")

Expand Down Expand Up @@ -216,7 +224,8 @@ def test_describe_each_required_tool_exits_zero(self) -> None:
with self.subTest(tool=name):
r = _run([self.binary, "describe", name])
self.assertEqual(
r.returncode, 0,
r.returncode,
0,
f"describe {name!r} exited {r.returncode}: {r.stderr}",
)
self.assertIn(name, r.stdout)
Expand Down Expand Up @@ -331,10 +340,7 @@ def test_call_check_permissions_returns_accessibility_and_screen_recording(
try:
data = json.loads(r.stdout)
except json.JSONDecodeError:
self.fail(
f"call check_permissions did not output JSON.\n"
f"stdout: {r.stdout!r}"
)
self.fail(f"call check_permissions did not output JSON.\n" f"stdout: {r.stdout!r}")
self.assertIn("accessibility", data)
self.assertIn("screen_recording", data)

Expand All @@ -351,8 +357,11 @@ def test_call_get_config_returns_config_object(self) -> None:
data = json.loads(r.stdout)
# Config must have at least one of the known top-level keys.
known_keys = {
"schema_version", "capture_mode", "max_image_dimension",
"agent_cursor", "telemetry_enabled",
"schema_version",
"capture_mode",
"max_image_dimension",
"agent_cursor",
"telemetry_enabled",
}
self.assertTrue(
known_keys.intersection(data.keys()),
Expand Down Expand Up @@ -407,8 +416,12 @@ def test_call_get_window_state_for_calculator(self) -> None:

# get_window_state
rs = _run(
[self.binary, "call", "get_window_state",
f'{{"pid": {pid}, "window_id": {window_id}}}'],
[
self.binary,
"call",
"get_window_state",
f'{{"pid": {pid}, "window_id": {window_id}}}',
],
timeout=30,
)
self.assertEqual(rs.returncode, 0, f"get_window_state stderr: {rs.stderr}")
Expand All @@ -427,7 +440,7 @@ def test_call_press_key_missing_pid_exits_1(self) -> None:
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_click_missing_required_args_exits_1(self) -> None:
r = _run([self.binary, "call", "click", '{}'])
r = _run([self.binary, "call", "click", "{}"])
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_type_text_missing_pid_exits_1(self) -> None:
Expand All @@ -439,19 +452,19 @@ def test_call_hotkey_missing_pid_exits_1(self) -> None:
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_scroll_missing_required_args_exits_1(self) -> None:
r = _run([self.binary, "call", "scroll", '{}'])
r = _run([self.binary, "call", "scroll", "{}"])
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_drag_missing_required_args_exits_1(self) -> None:
r = _run([self.binary, "call", "drag", '{}'])
r = _run([self.binary, "call", "drag", "{}"])
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_get_window_state_missing_pid_exits_1(self) -> None:
r = _run([self.binary, "call", "get_window_state", '{"window_id": 1}'])
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

def test_call_launch_app_no_args_exits_1(self) -> None:
r = _run([self.binary, "call", "launch_app", '{}'])
r = _run([self.binary, "call", "launch_app", "{}"])
self.assertEqual(r.returncode, 1, f"stdout: {r.stdout}")

# ── CLI: implicit call (tool name as first positional) ────────────────────
Expand Down Expand Up @@ -853,10 +866,16 @@ def test_mcp_get_config_roundtrip(self) -> None:
with self._mcp() as c:
result = c.call_tool("get_config")
sc = result.get("structuredContent", result)
known = {"schema_version", "capture_mode", "max_image_dimension",
"agent_cursor", "telemetry_enabled"}
self.assertTrue(known.intersection(sc.keys()),
f"get_config has no known keys: {list(sc.keys())}")
known = {
"schema_version",
"capture_mode",
"max_image_dimension",
"agent_cursor",
"telemetry_enabled",
}
self.assertTrue(
known.intersection(sc.keys()), f"get_config has no known keys: {list(sc.keys())}"
)

def test_mcp_set_config_max_image_dimension(self) -> None:
with self._mcp() as c:
Expand All @@ -881,6 +900,7 @@ def test_mcp_get_recording_state(self) -> None:

def test_mcp_set_recording_enable_disable(self) -> None:
import tempfile

with tempfile.TemporaryDirectory() as tmpdir:
with self._mcp() as c:
# Enable recording — output_dir is required.
Expand Down Expand Up @@ -952,9 +972,7 @@ def test_mcp_launch_app_missing_args_raises_error(self) -> None:
self._assert_tool_raises_mcp_error("launch_app", {})

def test_mcp_set_value_missing_pid_raises_error(self) -> None:
self._assert_tool_raises_mcp_error(
"set_value", {"element_index": 0, "value": "x"}
)
self._assert_tool_raises_mcp_error("set_value", {"element_index": 0, "value": "x"})

def test_mcp_replay_trajectory_bad_dir_raises_error(self) -> None:
self._assert_tool_raises_mcp_error(
Expand Down Expand Up @@ -1000,9 +1018,7 @@ def test_mcp_get_window_state_has_required_sc_keys(self) -> None:
wins = c.call_tool("list_windows", {"pid": pid})["structuredContent"]["windows"]
if not wins:
self.skipTest("Calculator has no windows")
state = c.call_tool("get_window_state", {
"pid": pid, "window_id": wins[0]["window_id"]
})
state = c.call_tool("get_window_state", {"pid": pid, "window_id": wins[0]["window_id"]})
sc = state.get("structuredContent", state)
for key in ("tree_markdown", "screenshot_width", "screenshot_height"):
self.assertIn(key, sc, f"get_window_state structuredContent missing: {key!r}")
Expand Down Expand Up @@ -1045,9 +1061,7 @@ def test_mcp_set_agent_cursor_motion_arc(self) -> None:
# ── stdio MCP: zoom ───────────────────────────────────────────────────────

def test_mcp_zoom_missing_pid_raises_error(self) -> None:
self._assert_tool_raises_mcp_error(
"zoom", {"x1": 0, "y1": 0, "x2": 100, "y2": 100}
)
self._assert_tool_raises_mcp_error("zoom", {"x1": 0, "y1": 0, "x2": 100, "y2": 100})

# ── stdio MCP: page ───────────────────────────────────────────────────────

Expand All @@ -1063,9 +1077,7 @@ def test_mcp_page_is_registered(self) -> None:
self.assertIn("page", names, "'page' tool is not registered")

def test_mcp_page_missing_pid_raises_error(self) -> None:
self._assert_tool_raises_mcp_error(
"page", {"action": "get_text"}
)
self._assert_tool_raises_mcp_error("page", {"action": "get_text"})

# ── stdio MCP: Rust-only tools (missing in Swift) ────────────────────────

Expand Down Expand Up @@ -1133,9 +1145,7 @@ def test_mcp_browser_eval_is_registered(self) -> None:

def test_mcp_browser_eval_missing_pid_raises_error(self) -> None:
"""browser_eval with no pid should return an MCP error."""
self._assert_tool_raises_mcp_error(
"browser_eval", {"expression": "1+1"}
)
self._assert_tool_raises_mcp_error("browser_eval", {"expression": "1+1"})

# ── stdio MCP: protocol-level contracts ──────────────────────────────────

Expand Down Expand Up @@ -1173,6 +1183,7 @@ def test_mcp_protocol_version_echo(self) -> None:

# ── concrete test classes (one per binary) ────────────────────────────────────


class SwiftParityTests(_ParityMixin, unittest.TestCase):
"""Run the full parity suite against the Swift cua-driver binary."""

Expand Down
Loading
Loading