feat: add support for Windows-only tools and enhance platform checks
Some checks failed
CI / test (push) Failing after 10s

This commit is contained in:
Space-Banane
2026-05-31 21:02:56 +02:00
parent d514fe161c
commit f0058d1057
2 changed files with 28 additions and 3 deletions

View File

@@ -6,6 +6,7 @@ import json
import logging
import os
import re
import sys
import subprocess
import threading
import time
@@ -331,6 +332,7 @@ OBSERVATION_TOOL_NAMES = VISUAL_TOOL_NAMES | WINDOW_TOOL_NAMES | DIALOG_TOOL_NAM
"clipboard_get",
"get_cursor_position",
}
WINDOWS_ONLY_TOOL_NAMES = WINDOW_TOOL_NAMES | DIALOG_TOOL_NAMES | UI_ELEMENT_TOOL_NAMES
MAX_ACTION_SIGNATURE_ATTEMPTS = 3
MAX_STABLE_OBSERVATION_STEPS = 3
FINISH_LIKELY_OBSERVATION_TOOLS = {"see_screen", "enhance", "get_active_window", "detect_dialog"}
@@ -1022,9 +1024,10 @@ class ScreenJobAgent:
},
},
]
optional_native_tools = WINDOW_TOOL_NAMES | DIALOG_TOOL_NAMES | UI_ELEMENT_TOOL_NAMES
if not self._native_control_tools_enabled():
optional_native_tools = set(WINDOWS_ONLY_TOOL_NAMES)
if self._is_windows_host() and not self._native_control_tools_enabled():
optional_native_tools = optional_native_tools - {"get_active_window"}
if not self._is_windows_host() or not self._native_control_tools_enabled():
return [
tool
for tool in all_tools
@@ -1080,6 +1083,9 @@ class ScreenJobAgent:
def _sorted_prohibited_key_combos(self) -> list[str]:
return sorted(self.prohibited_key_combos)
def _is_windows_host(self) -> bool:
return sys.platform.startswith("win")
def _native_automation_mode(self) -> str:
mode = str(self.options.native_automation_mode or "prefer").strip().lower()
if mode not in {"off", "prefer", "require_fallback"}:
@@ -1087,7 +1093,7 @@ class ScreenJobAgent:
return mode
def _native_control_tools_enabled(self) -> bool:
return self._native_automation_mode() != "off"
return self._is_windows_host() and self._native_automation_mode() != "off"
def _active_app_identity(self, window: dict[str, Any] | None) -> str:
if not isinstance(window, dict):
@@ -3753,6 +3759,8 @@ class ScreenJobAgent:
def _dispatch_tool(self, name: str, args: dict[str, Any]) -> dict[str, Any]:
if name in self.disabled_tools:
return {"ok": False, "error": f"Tool '{name}' is disabled for this job."}
if not self._is_windows_host() and name in WINDOWS_ONLY_TOOL_NAMES:
return {"ok": False, "error": f"Tool '{name}' is only available on Windows."}
finish_likely_result = self._check_finish_likely_gate(name, args)
if finish_likely_result is not None:
return finish_likely_result

View File

@@ -752,6 +752,23 @@ def test_tool_schemas_hide_optional_native_tools_when_mode_off(tmp_path: Path, m
assert "list_ui_elements" not in schemas
def test_tool_schemas_hide_windows_only_tools_on_non_windows_host(tmp_path: Path, monkeypatch) -> None:
agent = _build_agent(tmp_path, monkeypatch)
monkeypatch.setattr(agent_module.sys, "platform", "linux")
schemas = {tool["name"]: tool for tool in agent._tool_schemas()}
assert "get_active_window" not in schemas
assert "list_windows" not in schemas
assert "detect_dialog" not in schemas
assert "list_ui_elements" not in schemas
result = agent._dispatch_tool("get_active_window", {})
assert result["ok"] is False
assert result["error"] == "Tool 'get_active_window' is only available on Windows."
def test_list_windows_returns_structured_surface_metadata(tmp_path: Path, monkeypatch) -> None:
agent = _build_agent(tmp_path, monkeypatch)
monkeypatch.setattr(