Skip to content

HyperHand 0.3.0

Latest

Choose a tag to compare

@github-actions github-actions released this 11 Oct 02:53
· 15 commits to main since this release

Breaking: the MCP tool surface is redesigned for AI callers. Tool names, parameters and result formats change without aliases, and the guest protocol moves to a new generation: the host refuses older agents with agent_outdated until vm_update_agent is run.

Migration from 0.2.0

  1. Host. Install the new release over the old one with hyperhand.exe install (one UAC prompt).

  2. Guest agents. Run vm_update_agent on every VM. Until then every agent call to an old agent is refused with agent_outdated (fields agent_protocol, host_protocol, next call vm_update_agent); vm_status, vm_doctor and vm_update_agent keep working on it, and vm_update_agent replaces a 0.2.0 agent in place. If the agent does not answer, use vm_install_agent. A VM restored from an older checkpoint brings back the old agent and needs vm_update_agent again.

  3. Every call names its VM. Pass vm (a name from vm_list) on every tool except vm_list; there is no default VM. vm_end_turn may omit vm only to end the whole task.

  4. Results and errors are JSON. Parse the single JSON text item of each result (an observation's PNG image comes before it) instead of ok, handle: N, name<TAB>state or exit_code: text. An error is an isError result whose text is {"error", "reason", "next", ...}; follow next.

  5. Replace removed tools and parameters:

    0.2.0 Now
    vm_screenshot (source, region, coordinate metadata) vm_observe (handle or pid, max_size); actions take image pixels with its observation_id
    vm_controls vm_observe with controls: true (indexed text tree), or vm_find_controls for one control
    vm_focus_window nothing: actions activate their target (activate, default true)
    window, title, exact on any tool, title-selected waits handle (from vm_windows, vm_find_controls, vm_observe, vm_launch or an action result) or pid; vm_wait window and control kinds with handle/pid, automation_id, control_name or observation_id and index
    vm_type mode (clipboard paste) vm_type always types key events; vm_clipboard_set then vm_key ctrl+v to paste
    vm_click double count: 2
    vm_scroll delta delta_y (and delta_x)
    vm_drag x1, y1, x2, y2 from: {x, y}, to: {x, y}
    vm_checkpoint name label and keep; select checkpoints by the returned id
    GUI programs started with vm_exec vm_launch (vm_exec waits for the command to finish)
  6. Scripts. scripts/restart-tray.ps1 and scripts/dev-install.ps1 are gone: development installs use go run ./cmd/hyperhand dev-install. Scripts without an MCP client can use client/hyperhand_client.py; pass one task_id per piece of work so that ownership and observations carry over between calls.

Removed

  • scripts/restart-tray.ps1, which installed a build with a UAC prompt. Development installs use go run ./cmd/hyperhand dev-install (no UAC, through the preauthorized HyperHand Dev Install task registered once with scripts/dev-install-setup.ps1).
  • vm_screenshot: replaced by vm_observe. There is no source, region or coordinate metadata to apply; actions take image pixels of an observation.
  • vm_controls: replaced by vm_observe with controls: true, which returns the tree as indexed text instead of JSON nodes.
  • vm_focus_window: actions activate their target window themselves (activate, default true).
  • Legacy title-selected window waits; the new UI conditions use HWND/PID or observation/control identity instead.
  • Title selectors: the window, title and exact parameters of every tool. Windows are selected by handle (from vm_windows, vm_find_controls, vm_observe, vm_launch or an action result) or pid only.
  • vm_type mode: the clipboard paste path is gone; text is injected as Unicode key events, with the Hyper-V keyboard for ASCII text when the agent is not available.
  • vm_click double (use count), vm_scroll delta (use delta_y), vm_drag x1/y1/x2/y2 (use from/to), vm_checkpoint name (use label and keep).
  • Free-text results: ok, handle: N lines, name<TAB>state lists and exit_code: blocks.
  • Guest op screenshot: all screenshots are taken on the host.

Changed

  • vm_shutdown that times out because a program blocks shutdown now says what the guest may look like: Windows may already be signing the user out, with the agent gone and the desktop ignoring input. The error carries vm and state and a next naming vm_observe, raw input, and vm_turn_off or vm_restore as the only way out of a stuck guest, instead of the generic failed advice. The tool description advises saving or closing such programs first, or using vm_save.
  • vm_exec with admin: true whose timeout_ms passes before elevation completes (an unanswered UAC prompt) now fails with elevation_timeout (the command did not run; next says how to elevate without a prompt or answer it from the host) instead of returning timed_out: true with empty output, which looked like a command that ran too long. The guest protocol changes: run vm_update_agent on every VM.
  • Documentation: README.md is rewritten for human readers (what HyperHand is for, quick start with example requests, limitations, privacy); the tool list moves to the user guide, and building, testing, development installs and releasing move to the new docs/building.md.
  • New icon for hyperhand.exe, its tray icon, the settings window and hyperhand-agent.exe: a white monitor outline on a blue rounded square, replacing the gripper icon.
  • Success results that need a follow-up call carry next: a vm_push mirror plan (status: "planned") says that nothing was written yet and names the apply call (phase: "apply", its plan_id, the same paths, force and task_id, before expires_at); a background vm_exec names the vm_job call with its job_id. Callers had stopped after the plan, believing the mirror done.
  • Breaking: vm is required on every tool except vm_list; there is no default VM any more ("the only running VM, or the only VM if none is running"). With several VMs on a host, a call meant for a VM that was off silently reached another one, including vm_restore, vm_shutdown, vm_turn_off and vm_exec. A call without vm is refused before anything runs with invalid_argument, reason vm is required: there is no default VM, next listing the VM names and field vms; the input schemas mark vm as required. vm_end_turn may still omit vm to end the whole task (only the task's own waits, temporary checkpoints and ownership), but all_temp: true requires vm (reason vm is required with all_temp: ...) instead of deleting temporary checkpoints on every VM.
    • Migration: pass vm (a name from vm_list) on every call; pass vm with every vm_end_turn that uses all_temp: true; Stop hooks that call vm_end_turn without vm (such as the examples in docs/hooks/) keep working.
  • Observed controls can be re-located using their previous screen bounds as a read-only hint. The guest verifies the exact runtime ID and control-view ancestry to the requested window before accepting a hit; covered, moved or mismatched hints fall back to the existing traversal. Actions and wait conditions still read current values and state, and scoped reads retain password-subtree protection.
  • Semantic actions return readable post-action state and verify Toggle, Expand, Collapse, Select and ScrollIntoView outcomes. An immediate read is followed by up to 250 ms of read-only polling when needed; actions are never replayed. Unknown outcomes, password values and unobservable Invoke effects stay verified: null.
  • Every result is one JSON object in a single text item (vm_observe and actions with an after-action screenshot put a PNG image item before it). Every error is an isError result whose text is {"error": <code>, "reason", "next", "run_id", ...fields}; next names the call that makes progress. Codes: invalid_argument, stale_observation, stale_element, session_unusable, activate_failed, target_disabled, covered, integrity_mismatch, target_not_responding, unsupported_pattern, partial_input, agent_required, agent_outdated, ambiguous_target, no_window, no_checkpoint, failed.
  • Tools carry MCP annotations: read-only (vm_list, vm_status, vm_checkpoints, vm_pull, vm_clipboard_get, vm_wait, vm_windows, vm_find_controls, vm_observe, vm_doctor), destructive (vm_shutdown, vm_turn_off, vm_restore, vm_checkpoint_delete, vm_push, vm_update_agent, vm_end_turn) and idempotent hints; openWorldHint is false.
  • vm_windows returns {windows, foreground, focused_control, session}; each window gains group_root (the root of its owner chain within the process, at most 8 links) and integrity (low, medium, high, system); focused_control is the UI Automation focused element with window, name, control_type, automation_id, class_name, runtime_id, rect; session is the agent's session state.
  • Actions (vm_click, vm_drag, vm_scroll, vm_set_value, vm_invoke, vm_type, vm_key) take observation_id with image pixels or a control index; the host maps pixels to the screen, re-finds controls by runtime ID and refuses an observation whose window moved, resized, minimized or closed (stale_observation). The check chain before input is: session, freshness, target, activation, enabled, hit (covered), integrity, each with its code and next. Actions default to activate: true and to observe_after: screenshot (none for vm_type and vm_key; controls, both; settle_ms default 300, max 5000), returning the receiving window and an after observation with a new observation_id. Raw input (pointer actions without observation_id, vm_key without handle/pid) goes to the console with no checks at all, so the sign-in screen, the lock screen and UAC prompts stay reachable; an index of a whole-screen observation's tree targets the foreground window the tree belongs to with the full chain.
  • Window groups: a target's own windows (top-level windows of its process that it owns, directly or through other owned windows, up to 8 links) count as the target: an AutoCAD main-window handle reaches its untitled command line and command history popup, and the result names the window reached. Refusals name the window to act on next (act_on, foreground): a disabled window's own foreground dialog, another process's foreground window that probably blocks it, or the covering window described by class and process even when vm_windows does not list it (shell overlays).
  • vm_click gains count (1 to 3) and modifiers (ctrl, shift, alt, held on the Hyper-V keyboard around the click); vm_drag takes from/to and modifiers; vm_scroll takes delta_y and delta_x (horizontal wheel through the agent).
  • vm_type has one mode: Unicode key events through the agent (type_keys); without a target, the Hyper-V keyboard for ASCII text when the agent is absent or its session is locked or on the secure desktop (agent_required or session_unusable for other text); it accepts handle/pid or observation_id with index (clicks the control first and reads it back afterwards: verified says whether value contains the typed text), returns {applied_chars, total_chars, window, after} and reports a stop after some characters as partial_input with the same counts (failed with applied_chars: 0 when nothing was typed).
  • vm_key accepts the numeric keypad (num0-num9, numenter, numdot, numplus, numminus, nummul, numdiv), numlock, f13-f20, printscreen, scrolllock, pause, apps, capslock and X11-style aliases (Return, Escape, Control_L, Shift_L, Alt_L, Super_L, KP_0-KP_9, KP_Enter, KP_Decimal, KP_Add, KP_Subtract, KP_Multiply, KP_Divide, period, comma, slash, minus, equal, Prior, Next); a sequence stopped after at least one combination is partial_input with applied and total (a failure before the first keeps its own code); the result is {ok, combinations, window, after}.
  • vm_checkpoint takes label (1 to 64 characters without \ / : * ? " < > | or line breaks; default hhmmss) and keep and names the checkpoint <run_id>-temp-<label> or <run_id>-keep-<label>, returning {id, name, type, kind, state, parent, created_at}; a VM whose checkpoint setting is Disabled is refused with invalid_argument.
  • vm_checkpoints returns the tree: {vm, checkpoint_type, current_parent, checkpoints: [{id, name, parent, created_at, type, run_id, label, kind, state, holds_memory, current, children}]} in creation order; parent is the parent's id (null for a root), kind is Hyper-V's snapshot type lower-cased, state the saved power state, holds_memory whether it saved memory, current marks the checkpoint the VM's current state branches from, created_at is RFC 3339 with the host's offset.
  • Checkpoints are selected by id (from vm_checkpoints; the stable selector, since names may repeat) or by name when exactly one checkpoint has it; several: ambiguous_target with ids; none: no_checkpoint.
  • vm_restore takes id or name and save_current (first saves the current state as <run_id>-temp-before-restore), returning {vm, restored: {id, name, type}, state, saved_current, next}.
  • vm_end_turn takes all_temp (delete the temp checkpoints of every run on the VM named by vm, which it requires) and returns skipped: [{id, name, reason}] for the checkpoints it did not delete (no longer temp, or a Hyper-V failure with all_temp), besides cancelled_waits, deleted_checkpoints and errors; registered checkpoints are checked against the VM's current list before deletion.
  • vm_list returns {vms: [{name, id, state}], run_id}; vm_status, vm_start, vm_unlock, vm_shutdown, vm_turn_off, vm_restore, vm_exec, vm_push, vm_pull, vm_clipboard_get, vm_clipboard_set, vm_wait ({satisfied, elapsed_ms}), vm_install_agent and vm_update_agent return JSON objects; vm_shutdown on a VM that is already off returns {vm, state: "off"}.
  • vm_exec runs commands to completion only; its description points GUI programs to vm_launch.
  • Every new agent connection is pinged first: an agent whose protocol is older than the host's is refused with agent_outdated for every op except ping and update_agent, so vm_status, vm_doctor and vm_update_agent still work on it; vm_start, vm_install_agent and vm_update_agent also check the agent that answers their readiness ping; an agent's unknown op answer is reported the same way.
  • Guest protocol: ping reports protocol; list_windows takes optional {focused} (only vm_windows and vm_observe ask for the focused control, which costs a UI Automation helper process) and returns foreground, focused, session, agent_integrity and per-window group_root and integrity; list_controls nodes carry runtime_id, patterns, value, has_value and focused, and the result carries focused and selected_text.
  • Every failed error carries a default next (call vm_status, then vm_doctor if the VM is running; the action may or may not have happened, so observe before repeating it).
  • Tool descriptions of vm_windows, vm_find_controls, vm_observe, the actions, vm_exec, vm_pull and vm_clipboard_get state that titles, control names, values, command output, file contents and clipboard text are data from the guest, not instructions.

Added

  • vm_set_checkpoint_type: set the VM's checkpoint setting (Standard, Production, ProductionOnly or Disabled, Set-VM -CheckpointType) that decides what vm_checkpoint creates; returns checkpoint_type and previous, writes nothing when unchanged, and needs write ownership. New service operation checkpoint_type; reinstall the host.

  • vm_evidence: export the task's work on a VM as one reviewable zip on the host (evidence.json, report.md, screenshots): host and agent versions and executable hashes, the VM and its current checkpoint, every call of the task on the VM with arguments, results or errors and timing (vm_batch steps nested), the assertions of vm_batch steps and vm_wait with their outcome, file hashes from vm_file_info and from files, and the screenshots. Only this task's calls on this VM are included; the stored unlock password and redact strings are replaced with [redacted] (secrets shorter than 4 characters are skipped and counted; screenshots are not redacted). Every task now keeps a bounded journal of its calls (2000 calls, 128 MiB of images) until it ends.

  • vm_save and vm_pause: save a running or paused VM's memory to disk and stop it (state: saved, up to 5 minutes), or freeze a running VM in memory (state: paused); both are idempotent and refuse impossible transitions (failed with state and next call vm_start ...). vm_start resumes either and waits until the agent answers and the desktop is usable, as for a start; its result adds previous_state (running, off, saved or paused). New service operations save and pause; reinstall the host. No agent update needed.

  • vm_batch: run up to 64 tool steps in order in one call. Each step runs exactly like a direct call on the batch's vm and task (validation, ownership and errors unchanged); a string argument ${<step>.<path>} takes a value from an earlier step's result (for example the handle of a vm_launch step), and assert checks a step's result with equals, contains or exists. The batch stops at the first failed step (step_failed, with the step's own error) or failed assertion (assertion_failed, with the actual value), reports failed_step, last_completed and every result so far, and never repeats a step. Structural mistakes (unknown or excluded tools, another vm, forward references, malformed assertions) and an unknown vm are refused before any step runs; the result names the VM as Hyper-V does. Annotated destructive, since its steps may be. Host only; no agent update needed. The Python client returns every image of a result as _images and sums the steps' timeouts for the HTTP timeout of a vm_batch.

  • MIT license (LICENSE).

  • vm_file_info: read-only facts about 1 to 64 guest paths in one call, with environment variables such as %APPDATA% expanded in the agent's user context: {files: [{path, resolved, exists, type, size, sha256, version, modified, error}]}. version is the PE ProductVersion string; a missing path is exists: false, an unreadable file or one over 1 GiB gets a per-entry error. Needs no write ownership. New guest op file_info in a new protocol generation, so run vm_update_agent (older agents get agent_outdated).

  • hyperhand.exe dev-install [--no-build] [--timeout <seconds>], run from the repository root as go run ./cmd/hyperhand dev-install, replaces scripts/dev-install.ps1: it builds both executables into build\dev-install (version dev-<yyyyMMdd-HHmmss>-<commit>[-dirty]), runs the preauthorized HyperHand Dev Install task without UAC and checks the installed hashes, the service and the single installed tray process. Progress goes to stdout, errors to stderr, and the exit code is nonzero on failure.

  • vm_invoke action is optional: omitted, it defaults to the control's only action (other than SetValue) from the observation's tree, such as Invoke on a Button ... actions=[Invoke]; a control with several or no actions is refused with invalid_argument, supported and a next listing the actions to choose from.

  • client/hyperhand_client.py: a minimal official client for scripts and AI agents (Python 3.8+, standard library only), usable as a module or a command. It keeps one MCP session and a stable task_id (generated, --task, --task-file or HYPERHAND_TASK_ID), takes key=value arguments (Windows paths unescaped), @file.json or stdin, prints one UTF-8 JSON object, turns error results into HyperHandError / exit code 1 (transport problems exit 2), saves PNG images and returns their path as _image, parses control trees and finds controls by type, name, AutomationID, value, state, action or point (--find). Re-opens the session after a host restart. HyperHand.call(tool, arguments=None, /, *, http_timeout=None, **kwargs) takes every tool argument as a keyword, including vm_launch args; the HTTP timeout keyword is http_timeout. See client/README.md.

  • Background guest commands: vm_exec with background: true starts the command as a job in the guest agent and returns its id at once; vm_job reads its state and incremental output by byte offsets (stdout_next/stderr_next, complete), long-polls with wait_ms without holding the agent connection, cancels the whole process tree (cancel: true, needs write ownership) and lists the agent's jobs. Jobs survive MCP reconnects, task ends and host restarts and can be read by any task; they default to a 1-hour timeout (24 hours at most), keep 16 MiB per stream, and up to 32 jobs are kept for 24 hours after they end. An agent restart forgets them (no_job) without stopping their processes. New error code no_job. New guest protocol generation: the host refuses older agents with agent_outdated; run vm_update_agent on every VM.

  • vm_find_controls searches a window or selected subtree by exact AutomationId/name/type with independent traversal and result limits. Matches become task-scoped observations usable by existing actions and UI waits. vm_observe accepts observation_id/index to read a subtree; diffing requires the same root. Scoped reads fail closed on missing/incomplete identities and old agents. New guest operations require updating the agent.

  • UI conditions in vm_wait: window appearance, disappearance and foreground; control appearance, disappearance and exact enabled/value/state matching. Supports check_only, assert with assertion_failed, bounded host polling, concurrent actions, task cancellation and structured last-state evidence. Ambiguous, stale, truncated, password-redacted and unavailable provider results cannot silently satisfy an assertion.

  • Directory mirroring through vm_push mode: mirror: read-only phase: plan lists copies, empty directories and deletions; phase: apply consumes a task/VM-bound plan after rechecking both inventories. Changed files are staged and verified before extra files and empty directories are removed. Drift, partial completion and unconfirmed responses are distinct results; failed applies require a new plan. Ordinary copy behavior is unchanged. Mirror rejects links, type conflicts and manifests exceeding 4096 entries or 1 MiB per side.

  • vm_invoke supports control-targeted ScrollUp, ScrollDown, ScrollLeft and ScrollRight through UIA ScrollPattern, one small provider-defined step per call. Observations and results include supported axes and scroll percentages; verification reports observed directional movement, including false at an unchanged boundary.

  • Control observations expose executable actions and readable semantic state (toggle, expansion, selection, read-only and offscreen); unknown properties stay absent and controls_diff includes capability/state changes. Unsupported actions report action names rather than UIA pattern names.

  • Task ownership: optional task_id on every tool, independent observations, waits and checkpoint runs, and exclusive VM writes until task-scoped vm_end_turn cleanup. Persistent MCP sessions get a default task; short-lived connections and agents sharing a session can pass distinct IDs.

  • Stronger observation freshness: shared VM revisions invalidate old coordinates after input and other state-changing calls; lifecycle changes invalidate control references too. Coordinate actions also check local screenshot changes, and window checks include process/class identity. Stable UIA runtime IDs can still be re-located after ordinary input.

  • vm_apps: query launchable desktop applications from guest Start Menu shortcuts and App Paths. Returns stable IDs, preserved vm_launch arguments, current-session running state matched by executable path, visible window handles, result limits and partial-source warnings. No drive scan or UWP/MSIX launching.

  • vm_observe: one call returns a PNG of the screen or of one window (handle, pid; max_size), the observed window, the focused control, selected_text and, with controls: true, the UI Automation tree as indexed text ([index] ControlType "name" id=... (x,y wxh) disabled|offscreen|focused value="..."; max_depth, max_nodes); diff_from replaces the tree by controls_diff (added, removed, changed; a node whose index shifted counts as changed). The result carries observation_id; the host keeps the 8 most recent observations per VM. The screenshot is the host console image, so it works while the guest is locked or shows a UAC prompt (agent: "offline" then); a window that does not answer UI Automation yields the screenshot with stale_risk: "target not responding: control tree not read".

  • vm_set_value (UI Automation ValuePattern.SetValue, read back as verified, value and state; verified is null when the read-back was cut at 512 UTF-16 units) and vm_invoke (Invoke, Toggle, Expand, Collapse, Select, ScrollIntoView, ScrollUp, ScrollDown, ScrollLeft, ScrollRight) by control index; unsupported_pattern lists the control's supported executable actions, stale_element reports a vanished control, target_not_responding a window that does not answer within 12 s on the host or the agent's 10 s UI Automation timeout.

  • Index actions re-locate the control by runtime ID before acting (guest control_action action Locate, which performs nothing and returns the element's current rect and value): vm_click with index and vm_type with index click the centre of the control's current rectangle, so a control that moved since the observation is still hit; a vanished control is stale_element.

  • vm_launch: start a program detached (not in the vm_exec job object, optionally admin) and wait up to wait_window_ms (default 60 s) for its first visible top-level window; returns {pid, handle, title, class, elapsed_ms}, or no_window with pid while the process keeps running.

  • vm_checkpoint_delete: delete a checkpoint by id (manual checkpoints by id only) or by unique name, with subtree: true the checkpoint and all its descendants; waits for Hyper-V to merge the disk differences (up to 15 minutes) and returns {deleted: [{id, name, type}], merged_into_current, elapsed_ms}.

  • vm_checkpoint_keep: rename a temp checkpoint to <run_id>-keep-<label> (optional new label) so that vm_end_turn no longer deletes it; returns {id, name, type}; a keep or manual checkpoint is invalid_argument.

  • Error code no_checkpoint: no checkpoint has the given id or name.

  • Broker operation checkpoint_rename; checkpoint_restore and checkpoint_delete take the checkpoint id (a GUID), checkpoint_delete also subtree.

  • vm_end_turn: cancel this server's pending vm_wait calls and delete the temp checkpoints of this run; returns {cancelled_waits, deleted_checkpoints, skipped, errors}. Hook examples for Claude Code (Stop) and a Codex plugin (Stop, Interrupt, SubagentStop) in docs/hooks/.

  • vm_doctor: read-only checks of the host service, MCP listener, service pipe, Hyper-V socket registration and enhanced session mode, and of the VM's power, agent version and protocol, session and agent integrity, each ok, warn or fail with a suggestion.

  • Run ID run-<yyyymmdd-hhmm>-<4 hex> per server process, returned by vm_list and carried in every error object and checkpoint name.

  • Integrity check: input to a window whose process runs at a higher integrity level than the agent is refused with integrity_mismatch instead of being dropped silently by Windows.

  • Guest ops control_action (with Locate and a rect in its result), launch and hscroll.

Fixed

  • vm_apps lost Start Menu shortcuts whose name, target or arguments hold characters outside the guest's ANSI code page (Chinese on an English Windows, emoji anywhere): it read them through WScript.Shell, which converts through that code page, so the target came back with ? and the shortcut was skipped or its arguments changed. Shortcuts are now read through IShellLinkW, which keeps Unicode. running also compares executable paths in long form, so a process started from an 8.3 short path matches a shortcut that stores the long one, and the reverse. Requires the updated guest agent (vm_update_agent); the protocol is unchanged.
  • Production checkpoints were reported as kind: standard while the documentation promised production: HyperHand mapped Hyper-V's Recovery snapshot type to production, but Recovery is what backup software creates, and Hyper-V gives standard and production checkpoints the same type (Standard). kind is now Hyper-V's snapshot type lower-cased (standard, recovery, planned, ...), and vm_checkpoints and vm_checkpoint add holds_memory: true when the checkpoint saved memory (state running or saved), false for production checkpoints and those taken while off, which restore to off.
  • Saved and paused VMs were reported with raw numbers ("6", "9") in vm_list, vm_status and the tray, because current Hyper-V reports them as EnabledState 6 and 9 rather than 32769 and 32768; both forms now map to Saved and Paused.
  • An action on a hung window no longer blocks every call to its VM until the program recovers. When a window stops processing messages, Windows puts a Ghost window (<title> (Not Responding)) in the foreground, so the action tried to activate the real window, and the agent's restore and raise calls waited on its hung thread (minutes on Win10, while vm_windows from other clients queued behind it). The agent now refuses to focus a window that IsHungAppWindow reports, and the action returns target_not_responding at once with handle, pid and a next naming vm_exec taskkill /PID <pid> /F. vm_find_controls and the UI conditions of vm_wait report the guest's 10-second UI Automation helper timeout as target_not_responding instead of failed. Requires the updated guest agent (vm_update_agent); the protocol is unchanged.
  • A client that opens and deletes one MCP session per call no longer leaves the VM owned by a task nobody can reach. Deleting a session (HTTP DELETE) ends its default task once none of its calls is in flight: waits cancelled, observations and mirror plans dropped, VM ownership released; its temporary checkpoints stay for vm_end_turn all_temp. Explicit task_ids keep their ownership across sessions as before. vm_busy adds owner_idle_ms and owner_in_flight and names vm_end_turn {task_id: owner_task_id, vm} for an abandoned owner; vm_status adds owner: {task_id, idle_ms, in_flight, this_task} (null when free).
  • vm_type into AutoCAD no longer stops with partial_input after the first characters of a command name. AutoCAD's dynamic-input tooltip (CAcDynInputWndControl, a bare popup owned by the main window on its UI thread) takes the foreground and keyboard focus and forwards the keys to the command line; the agent now accepts such an input popup of the target (WS_POPUP without caption, sizing border or system menu, not a dialog, same process and thread, owner chain reaching the target) as the foreground while the target stays visible, enabled and not minimized. Modal dialogs, floating palettes (they have a sizing border and system menu), popups of other threads or processes and other windows still stop the input. Requires the updated guest agent (vm_update_agent); the protocol is unchanged.
  • Window integrity inspection uses an aligned token-information buffer and preserves SID pointer provenance, avoiding a crash under Go's race/checkptr instrumentation.
  • vm_install_agent confirms the per-installation ID returned by the newly launched agent, so an older running process (including the same version) cannot report success early. Readiness polling stops promptly on cancellation.
  • UI Automation provider failures, including read-only or disabled controls, remain operation failures instead of reporting the responding agent as offline or falling back to raw keyboard input.
  • vm_invoke Select detects the SelectionItem pattern on individual list/tree items using the correct UI Automation property, instead of checking the parent container's Selection pattern.
  • Missing, unknown or mistyped tool arguments return structured JSON invalid_argument results before VM access, preserving identifiable task ownership instead of leaking the MCP SDK's plain-text validation errors. Omitted or null arguments remain compatible with tools that have no required fields.