@agent-sh/computer-use-linux 0.7.9 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ The Rust crate is published as [`computer-use-linux`](https://crates.io/crates/c
|
|
|
26
26
|
|
|
27
27
|
Most computer-use MCP servers are macOS-only (they lean on AppKit, AXUIElement, CGEvent). The few that target Linux either drive `xdotool` against an X11 root window or shell out to OCR over screenshots. Four things set this one apart:
|
|
28
28
|
|
|
29
|
-
- **Wayland actually works.** Pointer actions can use the `org.freedesktop.portal.RemoteDesktop` interface on Wayland, with `ydotool` / `ydotoold` (uinput) as the deterministic fallback. Literal text prefers `wtype` on compatible Wayland compositors
|
|
29
|
+
- **Wayland actually works.** Pointer actions can use the `org.freedesktop.portal.RemoteDesktop` interface on Wayland, with `ydotool` / `ydotoold` (uinput) as the deterministic fallback. Literal text prefers KDE clipboard integration on Plasma, `wtype` on compatible Wayland compositors, and portal keysyms on other Wayland sessions, including GNOME with ydotool installed. Portal text startup or conversion errors fail the call without replaying text through ydotool. Raw ydotool text accepts printable ASCII, tab and newline only, and its physical US key positions can produce different text under the active layout. Screenshots use the GNOME Shell DBus screenshot method when present, `org.freedesktop.portal.Screenshot` otherwise, then on a native X11 session a root-window `GetImage` (device pixels, no toolkit scaling), and finally spawn `gnome-screenshot` for background/systemd contexts where the DBus paths are denied.
|
|
30
30
|
- **Window targeting is compositor-aware.** The window registry tries GNOME Shell extension, GNOME Shell Introspect, COSMIC Wayland helper, KWin DBus scripting, Hyprland `hyprctl`, the niri IPC socket, i3 IPC, and generic X11/EWMH in order, then reports exactly which backend won or why each backend failed.
|
|
31
31
|
- **Semantic selectors, not pixel coordinates.** Tools like `click`, `perform_action`, and `set_value` accept `role` / `name` / `text` / `states` selectors backed by AT-SPI. Pixel coordinates remain available as a fallback for rendering-only surfaces (canvas, games, X clients without ATK).
|
|
32
32
|
- **One JSON readiness report.** `computer-use-linux doctor` returns a structured document covering platform, portals, AT-SPI, windowing, input, and a `readiness` summary with explicit blockers and a recommended next step. MCP hosts can render or surface that to the user without parsing prose.
|
|
@@ -80,6 +80,8 @@ the origin. A missing window target is rejected.
|
|
|
80
80
|
|
|
81
81
|
Targeted `press_key`/`type_text` results append focused-element feedback from AT-SPI (role, name, editable) and warn when no editable element holds focus. Click/screenshot/input results warn when the target window or coordinate is partially or fully off-screen. `get_app_state` returns a compact readiness block by default; pass `verbose: true` for the full diagnostics report. It also reports `tree_scoped` (false when no app target narrowed the AT-SPI tree, with a warning in `message`) and `accessibility_tree_truncated` (true when the node, depth, or read budget stopped traversal with unread elements left).
|
|
82
82
|
|
|
83
|
+
On GNOME, a read-only keymap preflight rejects the whole string before input if a character is absent or requires a modifier level Mutter cannot synthesize. The background reader cannot establish the active layout group, so every configured group must support the text. This can reject text that works in one of several groups; use `set_value` on an editable field instead. The check requires `libxkbcommon.so.0` at runtime and stops after a two-second keymap read deadline. It does not cover held modifiers or a keymap changed concurrently with typing.
|
|
84
|
+
|
|
83
85
|
**Semantic actions**
|
|
84
86
|
|
|
85
87
|
- `perform_action` — invoke any AT-SPI action exposed by an element (`Press`, `Activate`, `Toggle`, …); defaults to the primary action
|
|
@@ -384,7 +386,7 @@ Spawn the binary with `["mcp"]` as the argv tail. It speaks JSON-RPC over stdio
|
|
|
384
386
|
computer-use-linux doctor | jq .readiness
|
|
385
387
|
```
|
|
386
388
|
|
|
387
|
-
Aim for `can_register_mcp_tools`, `can_build_accessibility_tree`, `can_send_development_input`,
|
|
389
|
+
Aim for `can_register_mcp_tools`, `can_build_accessibility_tree`, `can_send_development_input`, and `can_query_windows` all `true`, with an empty `blockers` array. Doctor lists detected screenshot routes in `capabilities.screenshot`, but does not take a screenshot or request consent. Detected routes are always `screenshot_capture_status: "unverified"` and `can_capture_screenshots: false` in a doctor report. `get_app_state` records the result of its requested raw capture as `verified` or `failed`; only `verified` sets `can_capture_screenshots: true` in that response. If no route is detected, the status is `unavailable`. An unverified capture is a warning, not an installation blocker.
|
|
388
390
|
|
|
389
391
|
2. **If `accessibility.at_spi_bus.ok = false`** — run `computer-use-linux setup` (or call the `setup_accessibility` MCP tool). This sets:
|
|
390
392
|
- `org.gnome.desktop.interface toolkit-accessibility true`
|
|
@@ -393,7 +395,7 @@ Spawn the binary with `["mcp"]` as the argv tail. It speaks JSON-RPC over stdio
|
|
|
393
395
|
|
|
394
396
|
3. **If `windowing.can_list_windows = false`** — inspect `doctor.windowing.backends`. On GNOME Wayland, run `computer-use-linux setup-window-targeting` (or call `setup_window_targeting`) to install the bundled `computer-use-linux@avifenesh.dev` Shell extension, then log out and back in so GNOME Shell loads it. On KDE, Hyprland, niri, i3, COSMIC, or generic X11, install or expose the matching compositor tool/helper shown in the backend details.
|
|
395
397
|
|
|
396
|
-
4. **
|
|
398
|
+
4. **Verify screenshot capture.** Call `get_app_state` or run `computer-use-linux screenshot`. The Screenshot portal may request consent for the caller's app ID. On GNOME, that dialog can be rejected when the app ID does not match the focused app. A detected portal interface alone does not prove capture permission. Inspect the full backend error and the desktop portal logs if capture fails; `gnome-screenshot` is an optional fallback when GNOME Shell or portal calls are denied.
|
|
397
399
|
|
|
398
400
|
5. **Confirm compatible ydotool 1.0.3+ and `ydotoold` are available.**
|
|
399
401
|
|
|
@@ -413,10 +415,12 @@ Most setups need none of these — `doctor` and the installers pick sensible def
|
|
|
413
415
|
| --- | --- |
|
|
414
416
|
| `COMPUTER_USE_LINUX_NOTIFY_ON_COMPLETE` | Set exactly to `1` to expose the optional `complete_interaction` notification tool. Requires `notify-send` and a desktop notification service; disabled by default. |
|
|
415
417
|
| `COMPUTER_USE_LINUX_COSMIC_HELPER` | Path to the `computer-use-linux-cosmic` helper when it isn't next to the binary or on `PATH`. |
|
|
416
|
-
| `CU_DISABLE_ABS_POINTER` | Disable the uinput absolute pointer
|
|
417
|
-
| `COMPUTER_USE_LINUX_FORCE_PORTAL_POINTER` / `…_KEYBOARD` |
|
|
418
|
+
| `CU_DISABLE_ABS_POINTER` | Disable the uinput absolute pointer. Wayland coordinate actions then need the RemoteDesktop portal; they refuse input rather than use ydotool's relative-motion approximation. Native X11 fallback is unchanged. |
|
|
419
|
+
| `COMPUTER_USE_LINUX_FORCE_PORTAL_POINTER` / `…_KEYBOARD` | Prefer the RemoteDesktop portal on Wayland, skipping auto-detection. Pointer forcing skips the absolute uinput backend. Forced ydotool or XTEST keyboard overrides take precedence; KDE literal text keeps its clipboard route. Portal startup and text conversion failures return errors without replaying through ydotool. |
|
|
420
|
+
| `COMPUTER_USE_LINUX_PORTAL_SCROLL_INVERT` | Set to `1` to reverse vertical scrolling through the RemoteDesktop portal. Defaults to normal direction on both GNOME and KDE Plasma; horizontal direction is unchanged. |
|
|
418
421
|
| `COMPUTER_USE_LINUX_PERSIST_REMOTE_DESKTOP` | Set exactly to `1` to ask the RemoteDesktop portal to remember pointer and keyboard grants across processes. The first dialog still appears (on GNOME the remember box starts checked). Later processes reuse the single-use restore token from `Start`, stored mode `0600` under `$XDG_STATE_HOME/computer-use-linux/` (or `~/.local/state/computer-use-linux/`). Pointer and keyboard tokens are separate. Needs interface version 2. Unset, every new process is prompted. No effect when input is not using the portal. |
|
|
419
|
-
| `COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER` / `…_KEYBOARD` | Always route pointer / keyboard through `ydotool`, skipping the portal and KDE clipboard paths; pointer forcing also skips native-X11 `xdotool` coordinate clicks and scrolls. |
|
|
422
|
+
| `COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER` / `…_KEYBOARD` | Always route pointer / keyboard through `ydotool`, skipping the portal and KDE clipboard paths; pointer forcing also skips the absolute uinput backend and native-X11 `xdotool` coordinate clicks and scrolls. Coordinate pointer actions on Wayland then refuse input because ydotool cannot position them accurately; scrolling at the current pointer remains available. |
|
|
423
|
+
| `YDOTOOL_SOCKET` | Explicit ydotool socket path. When unset, only an owner-only `.ydotool_socket` in the user's private runtime directory is accepted; the legacy shared `/tmp/.ydotool_socket` is never selected automatically. Setting this variable is an operator trust override for custom layouts. |
|
|
420
424
|
| `COMPUTER_USE_LINUX_FORCE_XDOTOOL_KEYBOARD` | Prefer `xdotool`/XTEST keyboard input when `DISPLAY` is available. `COMPUTER_USE_LINUX_FORCE_YDOTOOL_KEYBOARD=1` takes precedence. |
|
|
421
425
|
| `COMPUTER_USE_LINUX_XDOTOOL_TYPE_DELAY_MS` | Per-character delay for `xdotool type` in milliseconds (default `12`). `0` is faster but can deliver characters out of order on some X servers. |
|
|
422
426
|
| `COMPUTER_USE_LINUX_SCREENSHOT_BACKEND` | Force a single screenshot backend, skipping the fallback chain. Accepts `gnome-shell`, `portal`, `x11`, or `gnome-screenshot`. `x11` works only on a native X11 session. Pin `gnome-screenshot` for background/systemd contexts where the GNOME Shell and portal DBus paths are denied. |
|
|
@@ -432,7 +436,7 @@ files.
|
|
|
432
436
|
|
|
433
437
|
| Variable | Effect |
|
|
434
438
|
| --- | --- |
|
|
435
|
-
| `COMPUTER_USE_LINUX_BIN` | Run this binary instead of the one bundled by the npm package. |
|
|
439
|
+
| `COMPUTER_USE_LINUX_BIN` | Run this absolute binary path instead of the one bundled by the npm package. Relative paths are ignored. |
|
|
436
440
|
| `COMPUTER_USE_LINUX_DOWNLOAD_BASE` | Override the GitHub release base URL the installer downloads from (mirrors, air-gapped hosts). |
|
|
437
441
|
| `COMPUTER_USE_LINUX_SKIP_DOWNLOAD=1` | Skip the post-install binary download entirely. |
|
|
438
442
|
| `COMPUTER_USE_LINUX_LOCAL_BINARY` / `…_LOCAL_COSMIC_HELPER` | Install from a local build instead of downloading (used by CI and local testing). |
|
|
@@ -443,8 +447,9 @@ files.
|
|
|
443
447
|
- **DBus where desktops expose it** — [`zbus`](https://crates.io/crates/zbus) for portal calls (`org.freedesktop.portal.Screenshot`, `…RemoteDesktop`, `…ScreenCast`), GNOME Shell screenshots (`org.gnome.Shell.Screenshot`), the bundled GNOME extension's `dev.avifenesh.ComputerUseLinux.WindowControl` service, and temporary KWin scripting.
|
|
444
448
|
- **MCP transport** — [`rmcp`](https://crates.io/crates/rmcp) with the `transport-io` feature; stdio framing, no network.
|
|
445
449
|
- **Input fallback** — on X11, keyboard input prefers `xdotool`/XTEST and falls back only when xdotool cannot launch. On Wayland, literal text uses `wtype` when installed and the remote-desktop portal is unavailable; `wtype` supports Unicode through the virtual-keyboard protocol on compatible compositors such as Hyprland/wlroots. If wtype is unavailable, the binary falls back to a compatible ydotool 1.0.3+ CLI and `ydotoold` socket. A launched wtype failure is returned without replaying the text. `install.sh` can configure `ydotoold`; the `setup` command only enables the GNOME AT-SPI bridge.
|
|
450
|
+
- **Wayland coordinate input** — coordinate clicks, drags, and targeted scrolls require the absolute uinput pointer or an approved RemoteDesktop portal session. Targeted scroll positions through uinput before sending only wheel events through ydotool. If accurate positioning is unavailable, the call returns `ok: false` before sending coordinate input. The absolute pointer still requires a successful full-desktop capture when first created; an existing device does not need another capture. Scrolling without a point or window/element target keeps using the current pointer position.
|
|
446
451
|
- **Native X11 coordinate clicks** — eligible native X11 sessions use one supervised `xdotool mousemove -- X Y click --repeat N BUTTON` command for left, middle, and right clicks; ydotool is used only when xdotool cannot launch, while a launched nonzero xdotool command is reported as an error without replay. `COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER=1` skips this xdotool path.
|
|
447
|
-
- **Native X11 scroll.** The same sessions send one `xdotool` command, `mousemove -- X Y click --delay 12 --repeat N BUTTON` when a point is set, or `click` alone when it is not. Buttons are 4 up, 5 down, 6 left, and 7 right, and `N` is the same notch count ydotool would pass to `mousemove --wheel` (five per page). ydotool's absolute move warps through (0, 0); GTK 3 then drops the single following wheel event because re-entry resets its XI2 scroll valuators. XTEST has no scroll valuators, so GTK takes the button path. A missing xdotool falls back to ydotool; a launched nonzero xdotool command does not. `COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER=1` skips this path.
|
|
452
|
+
- **Native X11 scroll.** The same sessions send one `xdotool` command, `mousemove -- X Y click --delay 12 --repeat N BUTTON` when a point is set, or `click` alone when it is not. Buttons are 4 up, 5 down, 6 left, and 7 right, and `N` is the same notch count ydotool would pass to `mousemove --wheel` (five per page). ydotool's absolute move warps through (0, 0); GTK 3 then drops the single following wheel event because re-entry resets its XI2 scroll valuators. XTEST has no scroll valuators, so GTK takes the button path. A missing xdotool falls back to ydotool; a launched nonzero xdotool command does not. `COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER=1` skips this path.
|
|
448
453
|
- **Native X11 transport.** Native X11 queries (window origins, root screenshots, `doctor`) connect and read replies under one shared 2-second deadline enforced in the transport itself, including the handshake and every reply. A stalled X server closes the query connection instead of leaving a blocked worker behind. Unix sockets, literal IP addresses, and `localhost` need no resolver. A remote hostname in `DISPLAY` needs `getent ahosts` for bounded name resolution; if it is missing or fails, the X11 route is reported as unavailable.
|
|
449
454
|
- **Window registry** — `list_windows`, `focused_window`, `activate_window`, `press_key`, and `type_text` share a backend registry. It tries GNOME extension, GNOME Introspect, COSMIC helper, KWin scripting, Hyprland `hyprctl`, the niri IPC socket, i3 IPC, and generic X11/EWMH in that order, skipping empty or failed backends so another compositor backend can answer.
|
|
450
455
|
- **niri backend** — prefers `niri msg`, falling back to direct JSON IPC over the same session socket. `is_minimized` maps to `hidden`. Bounds use `layout.window_size` (or `tile_size`) and, when available, the tile position plus the window's offset and the output's logical origin. Uniform output scaling converts these to device pixels; unknown or mixed scaling omits bounds. Missing window positions stay `null`, so listing and focusing still work without enabling coordinate targeting. An accepted focus action is verified by querying the focused window again.
|
|
@@ -457,7 +462,7 @@ files.
|
|
|
457
462
|
Computer-use tooling is, by definition, a privilege-escalation surface. The threat model:
|
|
458
463
|
|
|
459
464
|
- **`ydotoold` runs as a per-user service** with read/write access to `/dev/uinput`. `install.sh` automates this for systemd user sessions and prints manual supervisor guidance elsewhere. Any process that can connect to its socket (`/run/user/$UID/.ydotool_socket`, mode `0600` by default) can synthesize arbitrary input — keypresses, clicks, anything. Keep the socket in the user runtime dir (the default), not in `/tmp` or any world-readable location. Do not run `ydotoold` as root or as a system service.
|
|
460
|
-
- **
|
|
465
|
+
- **Screenshot consent depends on the portal and caller's app ID.** A saved permission can apply to multiple processes with that identity. Doctor only detects the available routes and does not request consent. Use `get_app_state` with `include_screenshot: false` to skip capture.
|
|
461
466
|
- **Persisted remote control is opt-in.** `COMPUTER_USE_LINUX_PERSIST_REMOTE_DESKTOP=1` stores the portal's single-use restore token in the user state directory, mode `0600`. A same-user process that can read that file can restore remote control without a new prompt until the desktop revokes the grant. Leave the variable unset to keep a prompt on every new process.
|
|
462
467
|
- **AT-SPI exposes window contents to any client on your session bus.** Enabling the AT-SPI bridge (`setup_accessibility`) is a prerequisite for this binary; it's also what screen readers use, and it shares the same trust boundary.
|
|
463
468
|
- **The GNOME Shell extension** is loaded only into your user's GNOME Shell, runs in the Shell's JS sandbox, and exposes a single DBus interface on the user session bus. It does not request any extra permissions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-sh/computer-use-linux",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.11",
|
|
4
4
|
"description": "Linux desktop-control MCP server: AT-SPI accessibility trees, Wayland/X11 input, screenshots, and compositor window targeting.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -7,9 +7,9 @@ export interface GeneratedMcpToolDefinition {
|
|
|
7
7
|
annotations: Record<string, unknown>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export const GENERATED_SERVER_VERSION = "0.7.
|
|
11
|
-
export const GENERATED_TOOL_CATALOG_HASH = "
|
|
12
|
-
export const GENERATED_SHELL_TOOL_CATALOG_HASH = "
|
|
10
|
+
export const GENERATED_SERVER_VERSION = "0.7.11";
|
|
11
|
+
export const GENERATED_TOOL_CATALOG_HASH = "666f4649084b7c1a240e6a0eacc01a55379b64a579355f50071211437e91229c";
|
|
12
|
+
export const GENERATED_SHELL_TOOL_CATALOG_HASH = "554322e70886f5c1e1a3ad06869c5be91c140103f71350ad635160e128c1563d";
|
|
13
13
|
export const GENERATED_MCP_TOOLS =
|
|
14
14
|
[
|
|
15
15
|
{
|
|
@@ -1030,6 +1030,8 @@ export const GENERATED_MCP_TOOLS =
|
|
|
1030
1030
|
"pages": {
|
|
1031
1031
|
"default": null,
|
|
1032
1032
|
"format": "double",
|
|
1033
|
+
"maximum": 100,
|
|
1034
|
+
"minimum": -100,
|
|
1033
1035
|
"type": [
|
|
1034
1036
|
"number",
|
|
1035
1037
|
"null"
|
package/pi/extension/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "node:fs";
|
|
23
23
|
import { createRequire } from "node:module";
|
|
24
24
|
import { homedir } from "node:os";
|
|
25
|
-
import { delimiter, join } from "node:path";
|
|
25
|
+
import { delimiter, isAbsolute, join } from "node:path";
|
|
26
26
|
import { Type, type TSchema } from "typebox";
|
|
27
27
|
import {
|
|
28
28
|
GENERATED_MCP_TOOLS,
|
|
@@ -47,6 +47,7 @@ const DEFAULT_TOOLS = [
|
|
|
47
47
|
const MAX_RESULT_TEXT_CHARS = 200_000;
|
|
48
48
|
const MAX_RESULT_IMAGE_BYTES = 2 * 1024 * 1024;
|
|
49
49
|
const MAX_RESULT_IMAGES = 4;
|
|
50
|
+
const SAFE_CHILD_PATH = ["/usr/local/bin", "/usr/bin", "/bin"].join(delimiter);
|
|
50
51
|
const TRUNCATION_NOTICE =
|
|
51
52
|
"[Result truncated by the Pi extension. Request a smaller/bounded result.]";
|
|
52
53
|
const SHELL_ENABLED = process.env.COMPUTER_USE_LINUX_ENABLE_SHELL === "1";
|
|
@@ -164,16 +165,23 @@ function executable(path: string): boolean {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
|
|
168
|
+
export function sanitizeExecutablePath(pathValue: string | undefined): string {
|
|
169
|
+
return (pathValue ?? "")
|
|
170
|
+
.split(delimiter)
|
|
171
|
+
.filter((dir) => dir.length > 0 && isAbsolute(dir))
|
|
172
|
+
.join(delimiter);
|
|
173
|
+
}
|
|
174
|
+
|
|
167
175
|
/**
|
|
168
|
-
* First executable `name` in a PATH-style list, or `null`. Empty
|
|
169
|
-
* skipped rather than read
|
|
176
|
+
* First executable `name` in a PATH-style list, or `null`. Empty and relative
|
|
177
|
+
* segments are skipped rather than read relative to the current directory.
|
|
170
178
|
*/
|
|
171
179
|
export function findExecutableOnPath(
|
|
172
180
|
pathValue: string | undefined,
|
|
173
181
|
name: string,
|
|
174
182
|
isExecutable: (path: string) => boolean = executable,
|
|
175
183
|
): string | null {
|
|
176
|
-
for (const dir of (pathValue
|
|
184
|
+
for (const dir of sanitizeExecutablePath(pathValue).split(delimiter)) {
|
|
177
185
|
if (!dir) continue;
|
|
178
186
|
const candidate = join(dir, name);
|
|
179
187
|
if (isExecutable(candidate)) return candidate;
|
|
@@ -228,19 +236,24 @@ function runtimeEnvironment(): Record<string, string> {
|
|
|
228
236
|
"COMPUTER_USE_LINUX_SCREENSHOT_BACKEND",
|
|
229
237
|
"CU_DISABLE_ABS_POINTER",
|
|
230
238
|
]);
|
|
231
|
-
|
|
239
|
+
const env = Object.fromEntries(
|
|
232
240
|
Object.entries(process.env).filter(
|
|
233
241
|
(entry): entry is [string, string] =>
|
|
234
242
|
typeof entry[1] === "string" &&
|
|
235
243
|
(allowed.has(entry[0]) || entry[0].startsWith("LC_")),
|
|
236
244
|
),
|
|
237
245
|
);
|
|
246
|
+
const sanitizedPath = sanitizeExecutablePath(env.PATH);
|
|
247
|
+
env.PATH = sanitizedPath || SAFE_CHILD_PATH;
|
|
248
|
+
return env;
|
|
238
249
|
}
|
|
239
250
|
|
|
240
251
|
function defaultFindBinary(): BinaryLaunch | null {
|
|
241
252
|
const env = runtimeEnvironment();
|
|
242
253
|
const override = process.env.COMPUTER_USE_LINUX_BIN?.trim();
|
|
243
|
-
|
|
254
|
+
// Relative overrides would be resolved from Pi's potentially untrusted
|
|
255
|
+
// project directory. Ignore them and continue with bundled/global discovery.
|
|
256
|
+
if (override && isAbsolute(override) && executable(override)) {
|
|
244
257
|
return { binaryPath: override, env };
|
|
245
258
|
}
|
|
246
259
|
|
|
@@ -194,7 +194,10 @@ Ready output should have:
|
|
|
194
194
|
- `can_build_accessibility_tree: true`
|
|
195
195
|
- `can_query_windows: true`
|
|
196
196
|
- `can_send_development_input: true`
|
|
197
|
-
- `
|
|
197
|
+
- `screenshot_capture_status: "unverified"`
|
|
198
|
+
- `can_capture_screenshots: false`
|
|
198
199
|
- `blockers: []`
|
|
199
200
|
|
|
201
|
+
Doctor detects screenshot routes without capturing or requesting consent. Treat unverified capture as a warning. Call `get_app_state` with `include_screenshot: true` to verify it: a successful raw capture reports `screenshot_capture_status: "verified"` and `can_capture_screenshots: true`; a failure reports `failed` and keeps the boolean false. Inspect `screenshot_error` for the full backend cause.
|
|
202
|
+
|
|
200
203
|
Then test with your agent by calling the `doctor` tool or asking the agent to list desktop windows.
|
|
@@ -137,5 +137,8 @@ Ready output has:
|
|
|
137
137
|
- `can_build_accessibility_tree: true`
|
|
138
138
|
- `can_query_windows: true`
|
|
139
139
|
- `can_send_development_input: true`
|
|
140
|
-
- `
|
|
140
|
+
- `screenshot_capture_status: "unverified"`
|
|
141
|
+
- `can_capture_screenshots: false`
|
|
141
142
|
- `blockers: []`
|
|
143
|
+
|
|
144
|
+
Doctor detects screenshot routes without capturing or requesting consent. Treat unverified capture as a warning. Call `get_app_state` with `include_screenshot: true` to verify it: a successful raw capture reports `screenshot_capture_status: "verified"` and `can_capture_screenshots: true`; a failure reports `failed` and keeps the boolean false. Inspect `screenshot_error` for the full backend cause.
|