style: ruff format after MCP server integration

Reformat the files touched by Tasks 1-14 of the host-agent MCP server
plan. No semantic changes; pre-existing format issues in unrelated
files (test_templates, test_skill_sync_wiring, 0010_skill_management,
test_skill_catalog_mcp) left untouched for a separate housekeeping
pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 15:52:32 +08:00
co-authored by Claude Opus 4.6
parent 6d9237a592
commit e69cea0245
16 changed files with 60 additions and 62 deletions
+12 -12
View File
@@ -40,15 +40,17 @@ def tool_handlers(
device_id=device_id, device_id=device_id,
manager=manager, manager=manager,
), ),
"swipe": lambda start_x, start_y, end_x, end_y, duration_ms=500, device_id=None: call_with_semantic_errors( "swipe": lambda start_x, start_y, end_x, end_y, duration_ms=500, device_id=None: (
swipe, call_with_semantic_errors(
start_x, swipe,
start_y, start_x,
end_x, start_y,
end_y, end_x,
duration_ms=duration_ms, end_y,
device_id=device_id, duration_ms=duration_ms,
manager=manager, device_id=device_id,
manager=manager,
)
), ),
"input_text": lambda text, device_id=None: call_with_semantic_errors( "input_text": lambda text, device_id=None: call_with_semantic_errors(
input_text, input_text,
@@ -85,9 +87,7 @@ def tool_handlers(
"describe_screen": lambda device_id=None: call_with_semantic_errors( "describe_screen": lambda device_id=None: call_with_semantic_errors(
lambda: describe_screen(device_id, manager=manager).to_dict() lambda: describe_screen(device_id, manager=manager).to_dict()
), ),
"list_devices": lambda: [ "list_devices": lambda: [device.to_dict() for device in manager.list_devices()],
device.to_dict() for device in manager.list_devices()
],
"device_status": lambda device_id: call_with_semantic_errors( "device_status": lambda device_id: call_with_semantic_errors(
lambda: {"device_id": device_id, "status": manager.status(device_id)} lambda: {"device_id": device_id, "status": manager.status(device_id)}
), ),
@@ -51,8 +51,7 @@ class AssignmentExecutor:
return AssignmentExecutionResult( return AssignmentExecutionResult(
status="failed", status="failed",
failure_reason=( failure_reason=(
f"device {assignment.device_id} is held by an active " f"device {assignment.device_id} is held by an active MCP session"
"MCP session"
), ),
) )
with bind_planner_execution_context(assignment): with bind_planner_execution_context(assignment):
@@ -57,9 +57,7 @@ class McpBusyTracker:
lease = McpDeviceLease( lease = McpDeviceLease(
device_id=device_id, device_id=device_id,
session_id=session_id, session_id=session_id,
acquired_at=( acquired_at=(existing.acquired_at if existing is not None else now),
existing.acquired_at if existing is not None else now
),
last_seen_at=now, last_seen_at=now,
) )
self._leases[device_id] = lease self._leases[device_id] = lease
@@ -154,4 +152,4 @@ class McpBusyTracker:
if (cutoff - lease.last_seen_at).total_seconds() > self._ttl if (cutoff - lease.last_seen_at).total_seconds() > self._ttl
] ]
for device_id in expired: for device_id in expired:
del self._leases[device_id] del self._leases[device_id]
@@ -74,9 +74,7 @@ class McpTokenStore:
created_at=datetime.fromisoformat(str(data["created_at"])), created_at=datetime.fromisoformat(str(data["created_at"])),
) )
except (KeyError, TypeError, ValueError) as exc: except (KeyError, TypeError, ValueError) as exc:
raise McpTokenStoreError( raise McpTokenStoreError(f"MCP token file schema invalid: {exc}") from exc
f"MCP token file schema invalid: {exc}"
) from exc
def _generate_and_write(self) -> McpToken: def _generate_and_write(self) -> McpToken:
token = McpToken( token = McpToken(
+2 -4
View File
@@ -141,9 +141,7 @@ def _wrap_tool(
return _with_display_status(handler, status_tracker, *args, **kwargs) return _with_display_status(handler, status_tracker, *args, **kwargs)
if device_id is not None and tool_name not in _NON_DEVICE_TOOLS: if device_id is not None and tool_name not in _NON_DEVICE_TOOLS:
_check_and_acquire( _check_and_acquire(device_id, session_id, mcp_busy_tracker, status_tracker)
device_id, session_id, mcp_busy_tracker, status_tracker
)
return handler(*args, **kwargs) return handler(*args, **kwargs)
@@ -254,4 +252,4 @@ def _call_tool_sync(
raise KeyError(f"tool {tool_name!r} has no callable") raise KeyError(f"tool {tool_name!r} has no callable")
return fn(**arguments) return fn(**arguments)
finally: finally:
_TEST_SESSION_ID.reset(token) _TEST_SESSION_ID.reset(token)
+1 -3
View File
@@ -697,9 +697,7 @@ def test_create_application_wires_mcp_components(tmp_path, monkeypatch) -> None:
# Build the same console app the production path builds and verify /mcp # Build the same console app the production path builds and verify /mcp
# is mounted (responds 401, not 404) without a bearer token. # is mounted (responds 401, not 404) without a bearer token.
mcp_token_store = McpTokenStore( mcp_token_store = McpTokenStore(config.identity_path.parent / "host_mcp_token.json")
config.identity_path.parent / "host_mcp_token.json"
)
mcp_token_store.load_or_create() mcp_token_store.load_or_create()
mcp_busy_tracker = McpBusyTracker(ttl_seconds=60.0) mcp_busy_tracker = McpBusyTracker(ttl_seconds=60.0)
mcp_server = build_mcp_server( mcp_server = build_mcp_server(
@@ -154,7 +154,14 @@ def test_workflow_assignment_maps_cancellation_stop_to_cancelled_status() -> Non
return object() if definition_id == "workflow-a" else None return object() if definition_id == "workflow-a" else None
class FakeWorkflowRunner: class FakeWorkflowRunner:
def run(self, loaded_definition, device_id: str, *, should_stop=None, stop_reason=None): def run(
self,
loaded_definition,
device_id: str,
*,
should_stop=None,
stop_reason=None,
):
assert should_stop is not None and should_stop() assert should_stop is not None and should_stop()
assert stop_reason is not None assert stop_reason is not None
return SimpleNamespace( return SimpleNamespace(
+3 -1
View File
@@ -150,7 +150,9 @@ def test_duplicate_instance_exits_with_clear_error(
def test_mcp_token_subcommand_prints_token(tmp_path, capsys, monkeypatch) -> None: def test_mcp_token_subcommand_prints_token(tmp_path, capsys, monkeypatch) -> None:
monkeypatch.setenv("HOST_AGENT_IDENTITY_PATH", str(tmp_path / "host_identity.json")) monkeypatch.setenv("HOST_AGENT_IDENTITY_PATH", str(tmp_path / "host_identity.json"))
monkeypatch.setenv("HOST_AGENT_LOCAL_ACCOUNT_PATH", str(tmp_path / "host_local_account.json")) monkeypatch.setenv(
"HOST_AGENT_LOCAL_ACCOUNT_PATH", str(tmp_path / "host_local_account.json")
)
# Also set control plane URL to satisfy config loading # Also set control plane URL to satisfy config loading
monkeypatch.setenv("HOST_AGENT_CONTROL_PLANE_URL", "https://cloud.example") monkeypatch.setenv("HOST_AGENT_CONTROL_PLANE_URL", "https://cloud.example")
from host_agent.cli import main from host_agent.cli import main
+16 -8
View File
@@ -61,7 +61,9 @@ def test_heartbeat_synchronizer_runs_at_configured_interval_until_stopped() -> N
calls: list[list[str]] = [] calls: list[list[str]] = []
class FakeClient: class FakeClient:
async def heartbeat(self, devices, *, address=None, policy_revision=0, **kwargs): async def heartbeat(
self, devices, *, address=None, policy_revision=0, **kwargs
):
calls.append([device.device_id for device in devices]) calls.append([device.device_id for device in devices])
return HeartbeatResponse( return HeartbeatResponse(
host_id="host-a", host_id="host-a",
@@ -99,7 +101,9 @@ def test_sync_once_notifies_status_tracker_and_on_sync_with_device_count() -> No
) )
class FakeClient: class FakeClient:
async def heartbeat(self, devices, *, address=None, policy_revision=0, **kwargs): async def heartbeat(
self, devices, *, address=None, policy_revision=0, **kwargs
):
return HeartbeatResponse( return HeartbeatResponse(
host_id="host-a", host_id="host-a",
accepted_devices=len(devices), accepted_devices=len(devices),
@@ -134,7 +138,9 @@ def test_heartbeat_caches_safe_host_policy_and_reuses_its_revision(tmp_path) ->
revisions: list[int] = [] revisions: list[int] = []
class UpdatingClient: class UpdatingClient:
async def heartbeat(self, devices, *, address=None, policy_revision=0, **kwargs): async def heartbeat(
self, devices, *, address=None, policy_revision=0, **kwargs
):
revisions.append(policy_revision) revisions.append(policy_revision)
return HeartbeatResponse( return HeartbeatResponse(
host_id="host-a", host_id="host-a",
@@ -176,9 +182,7 @@ def test_heartbeat_caches_safe_host_policy_and_reuses_its_revision(tmp_path) ->
asyncio.run(scenario()) asyncio.run(scenario())
assert revisions == [0] assert revisions == [0]
assert '"token":' not in ( assert '"token":' not in (tmp_path / "host_policy.json").read_text(encoding="utf-8")
tmp_path / "host_policy.json"
).read_text(encoding="utf-8")
def test_sync_once_passes_mcp_busy_device_ids_to_client() -> None: def test_sync_once_passes_mcp_busy_device_ids_to_client() -> None:
@@ -189,7 +193,9 @@ def test_sync_once_passes_mcp_busy_device_ids_to_client() -> None:
last_kwargs: dict[str, object] = {} last_kwargs: dict[str, object] = {}
class FakeClient: class FakeClient:
async def heartbeat(self, devices, *, address=None, policy_revision=0, **kwargs): async def heartbeat(
self, devices, *, address=None, policy_revision=0, **kwargs
):
last_kwargs.update(kwargs) last_kwargs.update(kwargs)
return HeartbeatResponse( return HeartbeatResponse(
host_id="host-a", host_id="host-a",
@@ -216,7 +222,9 @@ def test_sync_once_passes_empty_when_tracker_is_none() -> None:
last_kwargs: dict[str, object] = {} last_kwargs: dict[str, object] = {}
class FakeClient: class FakeClient:
async def heartbeat(self, devices, *, address=None, policy_revision=0, **kwargs): async def heartbeat(
self, devices, *, address=None, policy_revision=0, **kwargs
):
last_kwargs.update(kwargs) last_kwargs.update(kwargs)
return HeartbeatResponse( return HeartbeatResponse(
host_id="host-a", host_id="host-a",
@@ -100,9 +100,7 @@ def test_snapshot_matches_busy_device_ids() -> None:
def test_wait_until_usable_succeeds_when_free() -> None: def test_wait_until_usable_succeeds_when_free() -> None:
tracker, _ = _tracker_with_now() tracker, _ = _tracker_with_now()
ok = tracker.wait_until_usable( ok = tracker.wait_until_usable("phone-1", "sess-a", timeout=1.0, poll_interval=0.01)
"phone-1", "sess-a", timeout=1.0, poll_interval=0.01
)
assert ok is True assert ok is True
assert "phone-1" in tracker.busy_device_ids() assert "phone-1" in tracker.busy_device_ids()
@@ -110,9 +108,7 @@ def test_wait_until_usable_succeeds_when_free() -> None:
def test_wait_until_usable_returns_false_on_timeout() -> None: def test_wait_until_usable_returns_false_on_timeout() -> None:
tracker, _ = _tracker_with_now() tracker, _ = _tracker_with_now()
tracker.acquire("phone-1", "sess-a") tracker.acquire("phone-1", "sess-a")
ok = tracker.wait_until_usable( ok = tracker.wait_until_usable("phone-1", "sess-b", timeout=0.1, poll_interval=0.02)
"phone-1", "sess-b", timeout=0.1, poll_interval=0.02
)
assert ok is False assert ok is False
@@ -147,4 +143,4 @@ def test_wait_until_usable_blocks_then_fails_when_cloud_remains_busy() -> None:
cloud_busy_check=lambda: True, cloud_busy_check=lambda: True,
) )
assert ok is False assert ok is False
assert tracker.busy_device_ids() == [] assert tracker.busy_device_ids() == []
+1 -3
View File
@@ -833,9 +833,7 @@ def _seed_local_task(
source_task_id: str | None = "cloud-task-1", source_task_id: str | None = "cloud-task-1",
) -> str: ) -> str:
task = Task(goal="open settings", device_id="dev-1", status=status) task = Task(goal="open settings", device_id="dev-1", status=status)
metadata_store.create_task( metadata_store.create_task(task, source_task_id=source_task_id, source_attempt=1)
task, source_task_id=source_task_id, source_attempt=1
)
return task.id return task.id
+4 -2
View File
@@ -52,7 +52,9 @@ class _FakeDriver(Driver):
) -> None: ) -> None:
return None return None
def swipe_path(self, waypoints: list[tuple[float, float]], duration_ms: int) -> None: def swipe_path(
self, waypoints: list[tuple[float, float]], duration_ms: int
) -> None:
return None return None
def double_tap(self, x: float, y: float, interval_ms: int = 80) -> None: def double_tap(self, x: float, y: float, interval_ms: int = 80) -> None:
@@ -307,4 +309,4 @@ def test_wrapped_tool_accepts_context_kwarg() -> None:
tool_manager = server._tool_manager # type: ignore[attr-defined] tool_manager = server._tool_manager # type: ignore[attr-defined]
tool = tool_manager.get_tool("take_screenshot") tool = tool_manager.get_tool("take_screenshot")
assert tool is not None assert tool is not None
assert tool.context_kwarg == "ctx" assert tool.context_kwarg == "ctx"
@@ -25,4 +25,4 @@ def upgrade() -> None:
def downgrade() -> None: def downgrade() -> None:
op.drop_column("pooled_devices", "mcp_busy") op.drop_column("pooled_devices", "mcp_busy")
+1 -3
View File
@@ -82,9 +82,7 @@ class DevicePool:
) )
busy_set = set(mcp_busy_device_ids or []) busy_set = set(mcp_busy_device_ids or [])
devices = [ devices = [
self._to_pooled( self._to_pooled(device, host_id, now, mcp_busy=device.id in busy_set)
device, host_id, now, mcp_busy=device.id in busy_set
)
for device in snapshot for device in snapshot
] ]
if allow_device_takeover: if allow_device_takeover:
+3 -7
View File
@@ -48,9 +48,7 @@ def test_sync_host_devices_marks_mcp_busy_devices(pool: DevicePool) -> None:
def test_sync_host_devices_default_mcp_busy_is_false(pool: DevicePool) -> None: def test_sync_host_devices_default_mcp_busy_is_false(pool: DevicePool) -> None:
pool.sync_host_devices( pool.sync_host_devices("host-1", [_device("device-1", status="idle")])
"host-1", [_device("device-1", status="idle")]
)
devices = pool.list_devices() devices = pool.list_devices()
assert devices[0].mcp_busy is False assert devices[0].mcp_busy is False
@@ -65,8 +63,6 @@ def test_sync_host_devices_clears_mcp_busy_on_next_sync(
[_device("device-1", status="idle")], [_device("device-1", status="idle")],
mcp_busy_device_ids=["device-1"], mcp_busy_device_ids=["device-1"],
) )
pool.sync_host_devices( pool.sync_host_devices("host-1", [_device("device-1", status="idle")])
"host-1", [_device("device-1", status="idle")]
)
devices = pool.list_devices() devices = pool.list_devices()
assert devices[0].mcp_busy is False assert devices[0].mcp_busy is False
@@ -50,4 +50,4 @@ def test_mcp_busy_device_is_skipped_by_scheduler(pool: DevicePool) -> None:
scheduler.submit(goal="test", constraints=TaskConstraints()) scheduler.submit(goal="test", constraints=TaskConstraints())
assignments = scheduler.assign() assignments = scheduler.assign()
assert len(assignments) == 1 assert len(assignments) == 1
assert assignments[0].device_id == "dev-idle" assert assignments[0].device_id == "dev-idle"