OSWright
Automatización de escritorio de Windows para agentes de IA que mantiene un modelo de la pantalla entre acciones y relee solo las regiones que cambiaron, en lugar de devolver una captura de pantalla tras cada paso. En una tarea de entrada de datos de ocho campos, esto midió 25 122 → 3 404 tokens (7×), con el resultado verificado contra el estado propio de la aplicación mediante UI Automation. 43 herramientas. Instalación: uvx oswright
Documentación
OSWright
Automatización de escritorio para agentes de IA, sin pagar por una captura de pantalla en cada paso.
mcp-name: io.github.Ask-812/oswright
Un servidor MCP que permite a un LLM controlar aplicaciones de escritorio reales — el equivalente de escritorio de Playwright MCP. Mantiene un modelo de la pantalla entre acciones y vuelve a leer solo las partes que cambiaron, por lo que el mismo trabajo cuesta un orden de magnitud menos de tokens.

Ocho campos leídos de una factura y escritos en un formulario de gastos, verificados por la
aplicación misma. Misma tarea, mismo resultado, 7,4× menos contexto que devolver
una captura de pantalla después de cada acción. Cada número en pantalla se mide durante la
ejecución — regenera todo con python benchmarks/record_demo.py.
Por qué existe esto
La mayoría de los agentes GUI vuelven a percibir toda la pantalla en cada paso: captura de pantalla, OCR, entregar la imagen al modelo, repetir. Medido en un escritorio en vivo, la observación mediana cambia el 0,012% de los píxeles de la pantalla. Volver a leer todo hace mucho más trabajo del que justifica el cambio, y cobra ~2.800 tokens de imagen tanto si ocurrió algo como si no.
OSWright pregunta al compositor qué cambió, vuelve a escanear solo eso, y responde
las búsquedas de elementos desde la fuente más barata que pueda. Las afirmaciones a continuación se miden
en esta máquina y son reproducibles desde benchmarks/ — incluyendo
las que no resultaron a su favor.
Características clave
- Multiplataforma. Windows (API Win32), Linux (pynput/X11), macOS (pynput/Quartz).
- Árbol de accesibilidad. Encuentra elementos de forma determinista por rol y nombre mediante Windows UI Automation — 100% preciso, instantáneo, sin necesidad de modelo.
- OCR rápido. OCR de Windows (integrado, instantáneo) con respaldo EasyOCR para Linux/macOS. Los resultados se almacenan en caché automáticamente.
- Ligero en Windows. Sin descarga de PyTorch — Windows usa el motor OCR integrado, por lo que una instalación completa son unos pocos MB en lugar de unos pocos GB.
- Coincidencia de imágenes. Localiza elementos mediante imagen de plantilla con OpenCV.
- Gestión de ventanas. Listar, enfocar, minimizar, cerrar y capturar ventanas específicas.
- Diferenciación de capturas. Detecta cuándo cambia la pantalla con
wait_for_change. - Acceso al portapapeles. Lee y escribe el portapapeles del sistema para transferencia de datos.
- Lanzador de aplicaciones. Inicia aplicaciones y espera a que se carguen.
- Captura automática. Cada acción devuelve una captura de pantalla para que el agente siempre vea el estado actual.
- 43 herramientas MCP. Pantalla, OCR, UIA, ratón, teclado, ventanas, portapapeles y acciones compuestas.
- Percepción incremental. Vuelve a escanear solo las partes de la pantalla que cambiaron, y puede devolver qué cambió en lugar de una captura completa — ~21× menos tokens por paso.
- Memoria de pantalla. Reconoce pantallas que ya ha leído antes y las reutiliza, verificadas por píxeles — 89× más barato que volver a leer.
- Percepción especulativa. Aprende qué hacen las acciones y confirma el resultado esperado en lugar de volver a leer — 19–23× más barato, con un informe
surprisecuando la interfaz hace algo inesperado. - Espera adaptativa. Espera a que la pantalla realmente se estabilice en lugar de dormir un fijo de 300 ms — 11,9 s ahorrados en una tarea de 50 pasos.
- Cascada de resolución. Las búsquedas de elementos se detienen en el método más barato que funcione; las búsquedas repetidas cuestan ~0,05 ms.
- Correcto con DPI. Las coordenadas son píxeles físicos en todas partes, por lo que los clics aterrizan correctamente en pantallas escaladas.
- Suite de pruebas. 259 pruebas automatizadas; las que manejan el escritorio se omiten cuando no hay pantalla disponible.
Requisitos
- Python 3.10 o más reciente
- VS Code, Cursor, Windsurf, Claude Desktop, o cualquier otro cliente MCP
Primeros pasos
Primero, instala el servidor MCP de OSWright con tu cliente.
Configuración estándar funciona en la mayoría de las herramientas:
{
"mcpServers": {
"oswright": {
"command": "uvx",
"args": ["oswright"]
}
}
}
Nota: Si no tienes
uvx, puedes usarpip install oswrighty luego establecer"command": "oswright"directamente.
Claude Desktop
Sigue la guía de instalación de MCP, usa la configuración estándar anterior.
Claude Code
claude mcp add oswright uvx oswright
VS Code
Añade a tu settings.json de usuario o espacio de trabajo bajo mcp.servers:
{
"mcp": {
"servers": {
"oswright": {
"command": "uvx",
"args": ["oswright"]
}
}
}
}
O usa la CLI de VS Code:
code --add-mcp '{"name":"oswright","command":"uvx","args":["oswright"]}'
Cursor
Ve a Cursor Settings -> MCP -> Add new MCP Server. Nómbralo oswright, usa el tipo command con el comando uvx oswright.
Windsurf
Sigue la documentación de MCP de Windsurf. Usa la configuración estándar anterior.
Cline
Añade a tu cline_mcp_settings.json:
{
"mcpServers": {
"oswright": {
"type": "stdio",
"command": "uvx",
"args": ["oswright"],
"disabled": false
}
}
}
Goose
Ve a Advanced settings -> Extensions -> Add custom extension. Nómbralo oswright, usa el tipo STDIO, y establece el command a uvx oswright.
Usando pip en lugar de uvx
Si prefieres una instalación estándar con pip:
pip install oswright
Luego usa esta configuración:
{
"mcpServers": {
"oswright": {
"command": "oswright"
}
}
}
O ejecuta directamente:
python -m oswright
Habilidad del agente
skills/oswright/SKILL.md le dice a un agente cuándo
recurrir a OSWright y cuáles herramientas son las baratas. Sigue el formato abierto
de Agent Skills. Copia la carpeta skills/oswright
al directorio de habilidades de tu agente — ~/.claude/skills/ para Claude Code, o el
equivalente para tu cliente.
La habilidad establece --observation-mode delta. Sin ella, cada acción devuelve una
captura de pantalla completa, que es el costo que OSWright existe para evitar.
Percepción incremental
La mayoría de los agentes GUI vuelven a percibir toda la pantalla en cada paso: captura completa, OCR completo, y luego entregan al modelo una imagen nueva. Medido en un escritorio en vivo, la observación mediana cambia el 0,012% de los píxeles — por lo que un rescan completo hace aproximadamente 240× más trabajo del que justifica el cambio, y la captura que devuelve cuesta ~2.800 tokens de imagen tanto si ocurrió algo como si no.
OSWright mantiene un modelo de la pantalla entre observaciones y vuelve a escanear solo las regiones que realmente se movieron.
observe() -> {"changed": true,
"added": [{"text": "Saved", "x": 812, "y": 447}],
"removed": ["Unsaved changes"],
"screen_fraction_scanned": 0.015}
Medido en esta máquina durante un bucle de agente de 14 pasos:
| v0.4.0 (OCR completo + captura) | incremental | |
|---|---|---|
| Latencia mediana por paso | 212 ms | 33 ms |
| Tokens por observación | ~2.764 | ~49 |
| Tokens en 14 pasos | 38.696 | 1.025 |
| Relectura de pantalla | 100% | 16% |
Cuanto más ocupada está la pantalla, mayor es la brecha: el OCR completo escala con cuánto texto hay
en pantalla, mientras que la ruta incremental escala con cuánto cambió. La misma
comparación mide 6,5× en un escritorio tranquilo y 14,3× con una página web densa
abierta. Vuelve a medir con benchmarks/ en lugar de confiar en estos números.
El costo es un proxy, sin embargo, y una ruta de percepción más barata que degradara silenciosamente la precisión sería peor que ninguna. Por eso se verifica contra la finalización de tareas: tareas con script que manejan la superficie real de la herramienta en cuatro aplicaciones, evaluadas contra el estado propio de cada aplicación — UI Automation para Calculadora y Explorador, el título de la ventana para Chrome y VS Code — nunca contra OCR.
| configuración | Calculadora | Explorador de archivos | Chrome | tokens |
|---|---|---|---|---|
| estilo v0.4 (captura completa) | 9/9 | 3/3 | 3/3 | 118.858 |
| solo delta | 9/9 | 3/3 | 3/3 | 5.252 |
| delta + memoria | 9/9 | 3/3 | 3/3 | 5.099 |
| delta + memoria + predicción | 9/9 | 3/3 | 3/3 | 7.981 |
La precisión es idéntica en todas las configuraciones mientras el costo en tokens cae 23×.
Ejecútalo con python benchmarks/bench_tasks.py.
Por qué tanto píxeles como accesibilidad
El diseño apuesta a que ninguna ruta de percepción gana en todas partes. Apagar cada mitad mide eso en lugar de afirmarlo:
| configuración | Calculadora | Explorador de archivos | Chrome |
|---|---|---|---|
| cascada completa | 9/9 | 3/3 | 3/3 |
| solo accesibilidad | 9/9 | 0/3 | 0/3 |
| solo píxeles | 6/9 | 3/3 | 3/3 |
Solo accesibilidad — la postura que toman la mayoría de los agentes GUI de Windows — es perfecta en
XAML y ciega en una vista de lista Win32 y en contenido web. Probado contra VS Code
ve 18 elementos, siendo todo el IDE un único nodo llamado Chrome Legacy Window, mientras que el OCR lee 94 incluyendo cada nombre de archivo.
Solo píxeles falla en los botones de la Calculadora, porque el botón que un humano lee como 7
se llama Seven, y el OCR de Windows no devuelve dígitos de la Calculadora en absoluto.
La cascada es la única configuración que pasa en todas partes.
La cascada de resolución
find_element y click_element se detienen en el primer método que puede responder,
por lo que el costo sigue cuán novedosa es la solicitud en lugar de cuán grande es la pantalla:
| Escalón | Método | Costo típico |
|---|---|---|
| 0 | Ya está en el modelo de pantalla | ~0,05 ms |
| 1 | Volver a escanear solo lo que cambió | ~70 ms |
| 2 | Árbol de accesibilidad (sabe que un Botón es un botón) | ~40 ms |
| 3 | Búfer de texto propio de la app mediante UIA TextPattern — caracteres exactos | ~400 ms |
| 4 | OCR de pantalla completa | ~250 ms |
Buscar texto que el modelo ya conoce es ~5.000× más barato que la ruta v0.4.0 (0,05 ms frente a 244 ms). La respuesta informa qué escalón respondió, para que puedas ver qué está costando realmente una tarea.
El escalón 3 vale la pena entenderlo: el TextRange.FindText de UIA busca en el
búfer de texto propio de la aplicación y devuelve rectángulos delimitadores exactos. Es
inmune a fuente, DPI, antialiasing y error de OCR. Está debajo de los escalones de píxeles
solo porque escanear los controles de una ventana cuesta unos cientos de
milisegundos de COM entre procesos — es el escalón preciso, no el rápido.
Nota sobre el orden. Estos escalones están ordenados por medición, no por teoría. El consejo común es hacer primario el árbol de accesibilidad, pero en aplicaciones reales no siempre es más barato: recorrer el árbol de Chrome tomó 537 ms aquí, más lento que un pase de OCR de pantalla completa, y VS Code expuso solo 18 elementos. Ni los píxeles ni la accesibilidad ganan en todas partes, por eso esto es una cascada en lugar de una elección.
Preguntar al compositor en lugar de mirar
En Windows, el compositor del escritorio ya sabe qué píxeles cambiaron y los expone mediante DXGI Desktop Duplication. Preguntarle cuesta 0,14 ms y no transfiere píxeles, frente a decenas de milisegundos para capturar un fotograma y descubrir que era idéntico — por lo que una observación inactiva omite la captura por completo.
Cuando algo ha cambiado, el compositor se queda con ese fotograma, por lo que
sus píxeles se leen directamente de la GPU en lugar de capturarse una segunda vez mediante
una API diferente — 1,5–2,3× más rápido que mss en las mediciones aquí.
El compositor se usa solo como un negativo rápido para la detección de cambios. Cuando informa un cambio, las regiones sucias aún provienen del hash del fotograma capturado: los dos se miden en intervalos ligeramente diferentes, por lo que los rectángulos del compositor pueden subestimar en relación con los píxeles realmente capturados, y una región subestimada es texto que nunca se vuelve a leer. Degrada silenciosamente al hash de mosaicos y a la captura normal donde Desktop Duplication no esté disponible.
Habilita las observaciones delta para las herramientas de acción con --observation-mode delta.
El valor predeterminado sigue siendo screenshot para compatibilidad con clientes existentes.
Reproduce todo esto tú mismo: consulta benchmarks/.
El razonamiento detrás de cada decisión, incluidos los callejones sin salida, está en
docs/ENGINEERING_LOG.md.
Configuración
El servidor MCP de OSWright admite los siguientes argumentos. Se pueden proporcionar en la configuración JSON como parte de la lista "args":
| Opción | Descripción | Variable de entorno |
|---|---|---|
--port <port> | Puerto para transporte SSE. Si se omite, usa stdio (predeterminado). | FASTMCP_PORT |
--host <host> | Host al que vincular el servidor HTTP/SSE. Predeterminado: 127.0.0.1. | FASTMCP_HOST |
--transport <mode> | Protocolo de transporte: stdio, sse, streamable-http. Se detecta automáticamente desde --port. | |
--ocr-languages <langs> | Idiomas de OCR (predeterminado: en). Ejemplo: --ocr-languages en es fr | OSWRIGHT_OCR_LANGUAGES |
--timeout <seconds> | Tiempo de espera predeterminado para operaciones de espera automática (predeterminado: 10). | OSWRIGHT_TIMEOUT |
--snapshot-max-width <px> | Reducir la escala de la captura automática devuelta después de cada acción. 0 (predeterminado) mantiene la resolución completa. Valores más bajos reducen significativamente el costo de tokens. | OSWRIGHT_SNAPSHOT_MAX_WIDTH |
--observation-mode <mode> | Qué devuelven las herramientas de acción: screenshot (predeterminado), delta (solo lo que cambió, ~30× menos tokens), o both. | OSWRIGHT_OBSERVATION_MODE |
--no-atlas | No recordar pantallas entre visitas. | OSWRIGHT_NO_ATLAS |
--no-speculate | No predecir el resultado de las acciones. | OSWRIGHT_NO_SPECULATE |
--allow-remote | Requerido para vincular una dirección que no sea de bucle local. Ver Seguridad. | |
--log-level <level> | Nivel de registro: DEBUG, INFO, WARNING, ERROR. Predeterminado: INFO. | OSWRIGHT_LOG_LEVEL |
Una bandera explícita de línea de comandos siempre tiene prioridad sobre la variable de entorno correspondiente.
Ejemplo: OCR multilingüe
{
"mcpServers": {
"oswright": {
"command": "uvx",
"args": ["oswright", "--ocr-languages", "en", "es", "fr"]
}
}
}
Servidor MCP independiente (SSE)
Cuando se ejecuta desde un proceso de trabajo u otra máquina, use transporte SSE:
uvx oswright --port 8931
Luego, en la configuración de su cliente MCP:
{
"mcpServers": {
"oswright": {
"url": "http://127.0.0.1:8931/sse"
}
}
}
Seguridad
OSWright no tiene autenticación. Cualquiera que pueda alcanzar el puerto obtiene control total de teclado, mouse, pantalla y portapapeles de la máquina: es una toma de control remota del escritorio, no una API aislada.
Por lo tanto, el servidor se vincula a 127.0.0.1 de forma predeterminada y se niega a iniciarse en una dirección que no sea de bucle local a menos que pase --allow-remote. Para alcanzarlo desde otra máquina, prefiera un túnel SSH sobre exponer el puerto:
ssh -L 8931:127.0.0.1:8931 user@desktop-host
El transporte Stdio (el predeterminado, usado por cada configuración de cliente MCP anterior) no está expuesto a la red en absoluto y es la forma recomendada de ejecutar OSWright.
Las herramientas que pueden destruir trabajo están anotadas en consecuencia: close_window está marcada como destructiva, y launch_app inicia programas arbitrarios. Las herramientas de captura de pantalla se niegan a sobrescribir un save_path existente.
Notas de plataforma
| Plataforma | Backend de entrada | Backend de OCR | Descargas adicionales |
|---|---|---|---|
| Windows | API Win32 (SendInput) | OCR de Windows (instantáneo, integrado) | Ninguna. Sin PyTorch. UI Automation incluida. |
| Linux | pynput (X11) | EasyOCR | PyTorch (~2.5 GB). Requiere X11; Wayland tiene soporte limitado. |
| macOS | pynput (Quartz) | EasyOCR | PyTorch (~2.5 GB). Conceda permisos de Accesibilidad en Configuración del Sistema > Privacidad > Accesibilidad. |
En Windows, EasyOCR no está instalado, porque el motor OCR integrado de Windows es más rápido y no necesita descarga de modelos. Instálelo solo si necesita un idioma que el OCR de Windows no soporta:
pip install "oswright[easyocr]"
Coordenadas
Todas las coordenadas devueltas por OCR, coincidencia de imágenes y UI Automation son píxeles físicos absolutos de pantalla, listos para pasar directamente a mouse_click. Esto se aplica a subregiones y a configuraciones de múltiples monitores donde el escritorio virtual comienza en un origen negativo. screenshot también informa origin_x/origin_y, la posición absoluta del píxel superior izquierdo de la imagen, para cuando lea una coordenada de la imagen usted mismo.
Herramientas
Pantalla
-
screenshot -- Toma una captura de pantalla de la pantalla o una región. Devuelve la imagen como contenido de imagen MCP nativo. Opcionalmente guarda en una ruta de archivo.
- Solo lectura: true
-
get_screen_info -- Obtiene las dimensiones de la pantalla y el número de monitores.
- Solo lectura: true
OCR / Búsqueda de texto
-
find_text_on_screen -- Encuentra todas las apariciones de texto en pantalla usando OCR. Devuelve coincidencias con coordenadas y confianza.
- Parámetros:
text,exact, límites de región,monitor - Solo lectura: true
- Parámetros:
-
read_screen_text -- Lee TODO el texto visible en la pantalla usando OCR. Devuelve cada elemento de texto detectado con su posición.
- Parámetros: límites de región,
monitor - Solo lectura: true
- Parámetros: límites de región,
Coincidencia de imágenes
- find_image_on_screen -- Encuentra todas las apariciones de una imagen plantilla en pantalla usando coincidencia de plantillas de OpenCV.
- Parámetros:
template_path,threshold,monitor - Solo lectura: true
- Parámetros:
Mouse
-
mouse_click -- Hace clic con el mouse en coordenadas o en la posición actual. Devuelve una captura de pantalla.
- Parámetros:
x,y,button,clicks
- Parámetros:
-
mouse_double_click -- Doble clic en coordenadas o en la posición actual. Devuelve una captura de pantalla.
-
mouse_move -- Mueve el cursor del mouse a coordenadas de pantalla.
-
mouse_scroll -- Desplaza la rueda del mouse. Devuelve una captura de pantalla.
- Parámetros:
amount,x,y
- Parámetros:
-
mouse_drag -- Arrastra de un punto a otro. Devuelve una captura de pantalla.
- Parámetros:
start_x,start_y,end_x,end_y,button,duration
- Parámetros:
-
get_mouse_position -- Obtiene la posición actual del cursor del mouse.
- Solo lectura: true
Teclado
-
type_text -- Escribe texto carácter por carácter. Devuelve una captura de pantalla.
- Parámetros:
text,delay
- Parámetros:
-
press_key -- Presiona una tecla o combinación como
Enter,Ctrl+C,Alt+Tab. Devuelve una captura de pantalla.- Parámetros:
key
- Parámetros:
Acciones compuestas
-
click_text -- Encuentra texto mediante OCR y hace clic en él. Reintenta automáticamente hasta encontrarlo o agotar el tiempo de espera. Devuelve una captura de pantalla.
- Parámetros:
text,exact,button,timeout,poll_interval,monitor
- Parámetros:
-
double_click_text -- Encuentra texto mediante OCR y hace doble clic en él. Devuelve una captura de pantalla.
-
right_click_text -- Encuentra texto mediante OCR y hace clic derecho en él. Devuelve una captura de pantalla.
-
hover_text -- Encuentra texto mediante OCR y pasa el cursor sobre él. Devuelve una captura de pantalla.
-
fill_field -- Encuentra una etiqueta, hace clic en ella, la limpia y escribe un valor. Devuelve una captura de pantalla.
- Parámetros:
target_text,value,exact,timeout,monitor
- Parámetros:
-
fill_form -- Completa múltiples campos en una sola llamada. Reduce los viajes de ida y vuelta.
- Parámetros:
fields(lista de{label, value}),timeout,monitor
- Parámetros:
-
wait_for_text -- Espera a que aparezca texto en pantalla. Sondea mediante OCR.
- Parámetros:
text,exact,timeout,poll_interval,monitor - Solo lectura: true
- Parámetros:
-
wait_for_text_gone -- Espera a que el texto desaparezca de la pantalla.
- Parámetros:
text,exact,timeout,poll_interval,monitor - Solo lectura: true
- Parámetros:
-
wait_for_time -- Espera una duración especificada (máximo 30s), luego toma una captura de pantalla.
Gestión de ventanas
-
list_windows -- Lista todas las ventanas visibles. Opcionalmente filtra por subcadena del título.
- Parámetros:
title_filter - Solo lectura: true
- Parámetros:
-
focus_window -- Trae una ventana al primer plano por título. Devuelve una captura de pantalla.
- Parámetros:
title
- Parámetros:
-
close_window -- Cierra una ventana por título (envía WM_CLOSE). Devuelve una captura de pantalla.
- Parámetros:
title
- Parámetros:
-
minimize_window -- Minimiza una ventana por título. Devuelve una captura de pantalla.
- Parámetros:
title
- Parámetros:
-
screenshot_window -- Captura una captura de pantalla de solo una ventana.
- Parámetros:
title,save_path - Solo lectura: true
- Parámetros:
Portapapeles
-
get_clipboard -- Obtiene el contenido de texto actual del portapapeles del sistema.
- Solo lectura: true
-
set_clipboard -- Copia texto al portapapeles del sistema.
- Parámetros:
text
- Parámetros:
Gestión de aplicaciones
-
launch_app -- Lanza una aplicación y opcionalmente espera a que cargue. Ejecuta el programa directamente, nunca a través de un shell.
- Parámetros:
command,args,wait_text,timeout - Informa
wait_text_foundpara que pueda saber si la aplicación realmente cargó.
- Parámetros:
-
get_ocr_info -- Obtiene información sobre el backend de OCR activo y los backends disponibles.
- Solo lectura: true
Percepción incremental
-
observe -- Informa qué cambió en pantalla desde la última observación. Vuelve a escanear solo las regiones que se movieron. Prefiera esto sobre
screenshotpara rastrear el estado.- Parámetros:
force_full - Solo lectura: true
- Parámetros:
-
find_element -- Encuentra texto en pantalla usando el método más barato que pueda responder. Informa qué nivel de la cascada respondió.
- Parámetros:
text,exact,window_title - Solo lectura: true
- Parámetros:
-
click_element -- Encuentra texto mediante la cascada y hace clic en él. La alternativa barata a
click_text.- Parámetros:
text,exact,button,window_title
- Parámetros:
-
read_model_text -- Lee texto en pantalla del modelo incremental sin volver a hacer OCR de la pantalla.
- Parámetros:
query,limit - Solo lectura: true
- Parámetros:
-
perception_stats -- Informa cuánto trabajo de percepción ha evitado el modelo.
- Solo lectura: true
-
remember_screen -- Recuerda la pantalla actual para que futuras visitas omitan leerla. Persiste entre sesiones.
- Solo lectura: true
-
atlas_stats -- Informa qué ha recordado el atlas de pantalla y con qué frecuencia ayudó.
- Solo lectura: true
Accesibilidad / UI Automation (Windows)
-
get_ui_tree -- Obtiene el árbol de accesibilidad de la ventana enfocada. Devuelve todos los elementos interactivos con nombres, tipos, posiciones. Determinista e instantáneo.
- Parámetros:
window_title,max_depth - Solo lectura: true
- Parámetros:
-
click_ui_element -- Hace clic en un elemento de UI usando el árbol de accesibilidad. Más confiable que OCR.
- Parámetros:
name,control_type,automation_id,window_title
- Parámetros:
-
fill_ui_element -- Establece el valor de un elemento de UI (por ejemplo, cuadro de texto). Más confiable que el relleno basado en OCR.
- Parámetros:
value,name,automation_id,window_title
- Parámetros:
Pantalla avanzada
-
get_active_window -- Obtiene información sobre la ventana actualmente enfocada.
- Solo lectura: true
-
wait_for_change -- Espera a que la pantalla cambie visualmente. Toma una captura de referencia, sondea hasta que sea diferente.
- Parámetros:
timeout,poll_interval
- Parámetros:
Biblioteca de Python
OSWright también funciona como una biblioteca de Python independiente con una API estilo Playwright:
from oswright import OSWright
with OSWright() as ow:
screen = ow.screen()
screen.click(text="Start")
screen.type_text("Hello World")
screen.press("Ctrl+S")
screen.screenshot("desktop.png")
See the examples/ directory for more.
Arquitectura
oswright/
__init__.py # Package entry point (single source of __version__)
core.py # OSWright class (= Browser)
screen.py # Screen class (= Page)
locator.py # Locator + Assertions (= Locator + expect)
capture.py # Screen capture (mss - cross-platform, thread-safe)
dirty.py # Change detection - which parts of the screen moved
screenmodel.py # Persistent screen model, updated incrementally
cascade.py # Resolution cascade - cheapest method that can answer
atlas.py # Remembers screens across visits and sessions
settle.py # Knowing when the screen has finished responding
speculate.py # Predicting what an action does, instead of looking
textprovider.py # Exact text from the app itself via UIA TextPattern
detect.py # OCR dispatcher with caching (auto-selects best backend)
_ocr_windows.py # Windows OCR backend (instant, built-in)
accessibility.py # Windows UI Automation (deterministic element finding)
cache.py # Screenshot diffing, image hashing, OCR result cache
_dpi.py # Process DPI awareness (keeps every API in physical pixels)
_dxgi_windows.py # Compositor dirty rectangles via DXGI Desktop Duplication
input.py # Platform dispatcher for input backends
_input_windows.py # Windows input backend (Win32 API)
_input_pynput.py # Linux/macOS input backend (pynput)
window.py # Window management (list, focus, close)
clipboard.py # Clipboard read/write (cross-platform)
mcp_server.py # MCP server (43 tools for AI agents)
tests/
conftest.py # Fixtures that skip when no display/OCR is available
test_core.py # Unit tests (no desktop required)
test_perception.py # Incremental perception (stubbed, runs headless)
test_atlas.py # Screen memory and its failure modes (headless)
test_speculate.py # Prediction, settling, and their limits (headless)
test_e2e.py # End-to-end tests against the real desktop (marked `e2e`)
Recordando pantallas
Las aplicaciones son deterministas: el mismo diálogo tiene el mismo diseño cada vez. OSWright recuerda las pantallas que ha leído y las reutiliza en la siguiente visita, entre sesiones: 125 ms de lectura en frío → 1.4 ms de recuperación en caliente (89×).
Una pantalla recordada nunca se confía solo en el reconocimiento. Algunas regiones se verifican por píxeles antes de reutilizar el diseño, de modo que una pantalla que ha cambiado se rechaza en lugar de actuar sobre ella. La verificación falla de forma segura: una pantalla sin nada comprobable no se recuerda en absoluto.
Desactivar con --no-atlas. Las pantallas recordadas viven en ~/.oswright/atlas.json.
Prediciendo acciones en lugar de observarlas
Las aplicaciones son deterministas: hacer clic en Guardar produce el mismo diálogo cada vez, así que después de la primera observación el resultado de una acción ya se conoce. OSWright aprende qué hacen las acciones y confirma la pantalla esperada en lugar de leerla de nuevo: 19–23× más barato que observar (2.3 ms frente a 43–50 ms).
Una predicción debe verse dos veces antes de confiarse, se retira si resulta
incorrecta y se verifica de las mismas dos maneras que una pantalla recordada. Una
predicción fallida se informa al agente como un surprise: la interfaz hizo
algo que no hace normalmente, lo cual vale la pena saber en lugar de absorberlo en silencio.
Lo que garantiza una predicción confirmada: el diseño: los mismos controles en
los mismos lugares. No que cada carácter sea idéntico. Un solo dígito cambiado altera
menos píxeles que un cursor parpadeante, así que ninguna verificación de pantalla completa
puede separarlos a ninguna resolución. Usa observe(force_full=True) cuando el texto exacto importe.
Desactivar con --no-speculate.
Esperando solo lo necesario
Las herramientas de acción solían dormir un fijo de 300 ms, elegido para el caso más lento, así que cada acción pagaba el peor caso. El compositor sabe cuándo la pantalla deja de cambiar, así que la espera ahora termina cuando la interfaz realmente se asienta:
| Sueño fijo anterior | 300 ms |
| Espera real mediana | 61.5 ms |
| Ahorrado en una tarea de 50 pasos | 11.9 s |
"Asentado" significa sin cambio grande reciente, no sin cambio: un escritorio real nunca está quieto: un cursor y un reloj producen un evento de cambio cada ~18 ms que cubre alrededor de 32 píxeles, mientras que los cambios genuinos de interfaz cubren decenas de miles.
Pendiente
- Inyección de entrada en Wayland, y macOS
AXTextMarkercomo equivalente de TextPattern. - Un nivel de modelo de visión para superficies que no son ni accesibles ni legibles como texto: juegos, lienzos, editores de imágenes.
- Transiciones basadas en más que la pantalla anterior, para acciones cuyo resultado depende de un estado que no es visible.
Qué se mide y qué no
El costo de percepción y el éxito de la tarea se miden ambos en esta máquina y
son reproducibles mediante benchmarks/: en cuatro aplicaciones, una percepción
más barata no cuesta precisión, y la división píxeles/accesibilidad se mide en lugar de
argumentarse.
Contra Windows-MCP
Mismas tareas, cuatro escenarios, cada uno calificado por la propia aplicación. Ninguna herramienta se califica a sí misma, y Windows-MCP se ejecuta con sus propios valores predeterminados:
| Calculadora | Explorador | Chrome | Chrome, 2 pasos | aprobados | tokens | |
|---|---|---|---|---|---|---|
| oswright | 5/5 | 4/5 | 5/5 | 5/5 | 19/20 | 832 |
| Windows-MCP, captura por acción | 5/5 | 5/5 | 5/5 | 5/5 | 20/20 | 14,053 |
| Windows-MCP, captura una vez | 5/5 | 5/5 | 5/5 | 5/5 | 20/20 | 8,214 |
Léelo con honestidad: Windows-MCP fue más confiable, y oswright fue 16.9x más barato. oswright falló un clic de veinte, en una ventana que acababa de abrirse.
La diferencia de costo es estructural, no un ajuste de sintonía. Windows-MCP
devuelve la pantalla al agente -- Snapshot renderiza el árbol de accesibilidad
como (x,y) button "Seven" [action: click] -- y toma las coordenadas de vuelta, así que una
descripción de la pantalla se carga en el contexto del modelo en cada acción.
oswright toma el texto y devuelve el resultado.
La brecha de confiabilidad puede estar causada por la velocidad: oswright resuelve y hace clic en ~100 ms, a veces antes de que una ventana recién enfocada esté lista para entrada, donde un bucle más lento le da a la aplicación el tiempo que nunca tuvo que pedir. Eso es una hipótesis, no un hallazgo: agregar un asentamiento previo a la acción no hizo una diferencia medible en diez pruebas, así que se registra en lugar de arreglarse.
El escenario Chrome, 2 steps existe porque cada otra tarea aquí es lo suficientemente
corta como para que una herramienta pueda leer la pantalla una vez y reutilizar esas
coordenadas. Allí el primer clic mueve los controles 325 px hacia abajo en la página,
y la configuración de captura única tuvo que releer la pantalla -- así que en tareas
cuya interfaz se mueve, su número barato no existe y su costo real es el de por acción.
Reproduce con python benchmarks/bench_head_to_head.py (configuración en el
docstring del archivo).
Lo que esto no establece: cuatro tareas cortas en una laptop. Nada sobre trabajo largo de múltiples pasos, recuperación o madurez del producto: Windows-MCP tiene OAuth, analítica, un vigilante y un instalador; oswright no tiene ninguno de esos. Su recorrido de accesibilidad también lee el contenido de la página de Chrome, que el propio nivel de accesibilidad de oswright no hace. "Sustancialmente más barato por acción, a un pequeño costo de confiabilidad" es la afirmación. "Mejor producto" no lo es.
Desarrollo
pip install -e ".[dev]"
pytest tests/ # everything available on this machine
pytest tests/ -m "not e2e" # unit tests only, no desktop needed
ruff check oswright tests # lint
python benchmarks/bench_pipeline.py # reproduce the performance numbers
python benchmarks/bench_tasks.py # task success (opens Calculator repeatedly)
Las decisiones de diseño, mediciones y callejones sin salida se registran en
docs/ENGINEERING_LOG.md.
Licencia
MIT