Skip to content

Releases: taxah92/dsh-pve-vm

dsh-pve-vm 0.2.5 — SPICE VMs: the first frame and the clipboard

Choose a tag to compare

@taxah92 taxah92 released this 23 Oct 15:00

dsh-pve-vm 0.2.5 — SPICE VMs: the first frame and the clipboard

This release makes the plugin work with SPICE/QXL virtual machines — the ones Proxmox starts with
vga: qxl and a SPICE client — and removes a way to wedge the QEMU guest agent.

Fixed

  • The first frame of a QXL/SPICE VM could come out blank. On guests with a hardware cursor QEMU
    sends a “cursor only” update before the full frame, and the first waitForUpdate sometimes ended
    exactly there: console_shot and the “VM screen” panel returned a white frame. A new
    RfbClient.waitForFrame() keeps reading until an update carries a real rectangle, console captures
    use it, and the panel allows the first frame of a session up to 1.5 s (FIRST_FRAME_WAIT_MS).
    Reproduced on a 3440x1336 guest: the blank update arrived first, the real frame 79–300 ms later.
  • The clipboard did not work on SPICE VMs at all. console_paste and console_clipboard required
    vga: <type>,clipboard=vnc plus a SPICE agent, which is impossible on vga: qxl: the
    com.redhat.spice.0 channel is taken by spicevmc, and enabling clipboard=vnc there would remove
    the SPICE agent (dynamic resolution and your SPICE clipboard). Both tools now use the guest agent
    first — on Windows a scheduled task in the logged-in user session (the clipboard is per-session;
    SYSTEM in session 0 cannot see it), on Linux xsel/xclip/wl-copy/wl-paste in the active
    graphical session. The VNC clipboard stays as a fallback when the VM has clipboard=vnc. A
    logged-in session is required: there is no clipboard on the logon screen.
  • Non-ASCII in a guest argv could wedge the guest agent. PVE truncates non-ASCII QMP payloads
    (Proxmox #6609), so qm guest exec timed out
    and qemu-ga stayed stuck until its service was restarted. The controller now refuses such an
    argv before anything is sent (NON_ASCII_ARGV) and points at stdin/base64 envelopes.

Changed

  • typeTextArgv passes the guest script via base64, so a guestTypeCommand with non-ASCII text
    no longer travels in argv.
  • console_paste and console_clipboard timeouts were raised for the task round trip, and the
    clipboard result gained channel and truncated.
  • The default Linux input script now picks the first active graphical session (filters by session
    type x11/wayland/mir), fixing “No protocol specified” on guests where loginctl reports an
    empty Display for an X11 session.

Verification

  • npm run check, check-client and check-plugin on the publication: no problems, 16 tools.
  • Live acceptance on Proxmox VE 8.4: SPICE/QXL Windows 11 guest, Windows Server 2025 guest and a
    RedOS 8 / MATE guest — frames arrive, Cyrillic text pastes into Notepad through the guest channel,
    and the Linux clipboard round trip (get → set → read → restore) matches.
  • The npm tarball (30 files) is the checked artifact: the registry shasum equals the local
    npm pack sha1 (a2100f1d98e8da24e29e1a9cf6d26209fdc0d53b), and the release asset is the tarball
    downloaded from the registry.

Install

dsh plugin --profile web add dsh-pve-vm
# or straight from the repository:
dsh plugin --profile web add github:taxah92/dsh-pve-vm

Full changelog: CHANGELOG.md

dsh-pve-vm 0.2.4 — Simplified Chinese translation

Choose a tag to compare

@taxah92 taxah92 released this 18 Oct 12:11

dsh-pve-vm 0.2.4 — Simplified Chinese translation

Added

  • The web UI now speaks Simplified Chinese (zh). The settings card and the “VM screen” sidebar
    panel are translated; DeepSeek Harness ships the zh locale, so the plugin follows it exactly like
    it already followed en and ru. Missing keys would fall back to English, but there are none —
    tools/check-client.mjs now fails when a locale lacks a key or a {placeholder} differs between
    dictionaries.
  • The plugin card in Settings ▸ Plugins reads Chinese. locale/zh.json joins the existing
    en/ru metadata files, in the same meta shape the panel already reads.

Chinese labels cover the whole contribution: the settings section (19 fields with hints), the status
line, the screen panel controls and every state banner, and the tab title/guide.

Verification

  • check-client and check-plugin on the publication: no problems, 16 tools.
  • The three dictionaries (ru, en, zh) have identical key sets (70 keys each) and identical
    {vmid} / {resolution} / {capture} / {pointer} / {kb} / {message} placeholders. The new
    gate was verified negatively: removing view.paused and dropping {vmid} from view.status
    produces exactly those two reports.
  • The npm tarball (30 files) contains locale/zh.json and the Chinese zh: block in client.js;
    the registry shasum equals the local npm pack sha1.

No host-side code changed — the host half still runs the 0.2.2 guest-channel code unchanged.

Install

dsh plugin --profile web add dsh-pve-vm
# or straight from the repository:
dsh plugin --profile web add github:taxah92/dsh-pve-vm

Full changelog: CHANGELOG.md

dsh-pve-vm 0.2.3 — packaging fix: the npm tarball was missing tools/

Choose a tag to compare

@taxah92 taxah92 released this 17 Oct 09:18

dsh-pve-vm 0.2.3 — packaging fix

What was broken

index.js imports ./tools/console.js and ./tools/guest.js — the definitions of all 16 tools —
but the files list in package.json never included that directory. The published npm tarball
therefore could not be imported at all:

dsh plugin --profile web add dsh-pve-vm
→ ERR_MODULE_NOT_FOUND: Cannot find module '…/dsh-pve-vm/tools/console.js'

Every release up to and including 0.2.2 was affected. Installing straight from the repository
(dsh plugin --profile web add github:taxah92/dsh-pve-vm) was not affected — that path uses the
repository itself, where tools/ has always been present.

Fixed

  • files now includes tools/.
  • The two-copy gate in the development workspace (tools/sync-pve-vm.mjs) checks that every relative
    import of the packed tree resolves inside the package. Verified against the old list: it reports
    exactly index.js → ./tools/console.js and index.js → ./tools/guest.js.

No runtime code changed since 0.2.2 — the guest-channel work (request markers, file-length checks,
OEM/ANSI decoding, 1 MiB writes, honest timeouts) is all in 0.2.2 and carried over unchanged.

Verification

  • A local npm pack of 0.2.3 contains tools/console.js and tools/guest.js; importing the packed
    tree with the real peer packages succeeds (Config, apply, inject, name), and all 24 relative
    imports resolve.
  • check-plugin / check-client on the publication: 16 tools, no problems.

Install

dsh plugin --profile web add dsh-pve-vm
# or straight from the repository:
dsh plugin --profile web add github:taxah92/dsh-pve-vm

Full changelog: CHANGELOG.md

dsh-pve-vm 0.2.2 — the guest channel made reliable

Choose a tag to compare

@taxah92 taxah92 released this 17 Oct 09:07

dsh-pve-vm 0.2.2 — the guest channel made reliable

Found by running the plugin against a real Windows guest (Windows Server 2025, 4 GB RAM), not by
reading code: a live 19-check suite went from failing somewhere on every run to green.

Fixed

  • A non-ASCII command could wedge the guest agent until QEMU-GA was restarted. The fault is
    in Proxmox, not qemu-ga: non-ASCII QMP payloads are truncated by one byte per character
    (#6609). A Windows command now travels as a
    base64 envelope; argv with non-ASCII is refused before anything is sent
    (UNICODE_ARGV_WINDOWS).
  • Russian output came back as mojibake. PVE puts guest bytes into JSON as latin-1 and a Windows
    console writes in its OEM code page; output is now decoded from bytes with the code page cached
    per VM. Messages of cmd.exe itself arrive in the system ANSI code page even when chcp reports
    OEM, so the decoder tries both and keeps the readable one.
  • Commands longer than 30 s reported a false failure. qm guest exec waits 30 s and returns a
    pid without exited; the plugin now passes --timeout and reports STILL_RUNNING with the pid
    instead of exitcode -1.
  • vm_file_write worked only up to ~8 KB. File data now goes over stdin (--pass-stdin), which
    raises the limit to 1 MiB per call.
  • vm_file_read broke the QGA channel at 1 MiB. Files are read in 256 KiB chunks with an offset,
    and a chunk is retried (reading is idempotent).
  • A successful but short or foreign agent reply could silently corrupt a result. qemu-ga
    reuses pids, and the tail of an earlier command can arrive as the answer to a new one. Every read
    script and the non-ASCII command envelope now carry a per-call request marker and the real file
    length; a reply that does not match is retried, and if it still does not add up the tool fails
    instead of quietly returning an incomplete or foreign result.
  • PowerShell progress noise (CLIXML) no longer replaces error texts — every generated script
    starts with $ProgressPreference='SilentlyContinue'.

Changed

  • All qm calls to one VM are serialised with a 250 ms gap: QEMU serves one QMP client at a time,
    and back-to-back calls used to steal each other's replies.
  • A failed call is retried exactly once, and only when PVE answers “agent is not running” — that
    check runs before the command is sent, so the retry cannot execute anything twice.
  • vm_status explains how to recover a wedged guest agent; tool descriptions state the real limits.

Notes

  • A command that outlives timeoutMs keeps running in the guest — the tool reports
    STILL_RUNNING with the pid instead of pretending it failed.
  • Residual PVE/QMP flakiness on a busy guest is not a plugin bug: on mixed load one call in ~20 can
    still hit the five-second QMP timeout, and qemu-ga can hand back an earlier command's output when
    Windows reuses a pid. File reads and non-ASCII commands now detect and retry that; a plain
    vm_exec has nothing to check its output against.

Install

dsh plugin --profile web add dsh-pve-vm
# or straight from the repository:
dsh plugin --profile web add github:taxah92/dsh-pve-vm

Full changelog: CHANGELOG.md

dsh-pve-vm 0.2.1 — Russian plugin card

Choose a tag to compare

@taxah92 taxah92 released this 14 Oct 07:10

The plugin card in the panel is now localized — and it finally shows its own title instead of the package name.

Fixed

  • locale/en.json and locale/ru.json were written in a format the panel never reads. The
    reader (readPluginMeta in dsh-app-boot) takes display text from a meta object —
    {"meta": {"title": …, "description": …}} — and silently drops a flat {title, description} file.
    Both files were flat, so the card in the plugin inventory showed the package name dsh-pve-vm and
    the manifest description; the Russian text never appeared anywhere. Wrapped in meta: the card now
    reads “Proxmox VE VM control” / “Управление ВМ Proxmox VE” and follows the panel language.

Checks

  • tools/check-plugin.mjs verifies the card metadata: the meta shape of every locale/*.json,
    field parity between the languages, and — through the installed harness — that readPluginMeta
    answers with a translation map rather than the package-name fallback.

Registry sha1 ee7c24afb201947f4d47c90c32f9561e63b28ecb is identical to a local npm pack;
the attached tarball is the one the registry serves. Install with
dsh plugin --profile web add dsh-pve-vm.

dsh-pve-vm 0.2.0 — live VM screen in the right sidebar

Choose a tag to compare

@taxah92 taxah92 released this 13 Oct 20:17

Watch the agent work: a live VM screen in the right sidebar of the harness web UI.

Added

  • The “VM screen” tab. A right-sidebar panel that streams the frames the agent sees.
    The frames come from the agent's own RFB session, so no second VNC session appears and
    the qm vncproxy password is never reset under the agent's feet. Captures and tools share
    one session queue, so they never tear the stream for each other. The panel is watch-only by
    design: nothing is injected into the guest.
  • viewAutoOpen (off by default) — reveal the tab by itself when the agent touches a console.
  • viewFollowAgent (on by default) — the panel follows the VM the agent works with; a VM chip
    pins it by hand. Watching never counts as agent work, so the panel cannot chase itself.
  • viewFps (2) and viewScale (2) — frame pace and resolution divisor, both changeable
    on the fly inside the panel.
  • Host routes /pve-vm/console/state, /frame and /release on the harness web server,
    registered only when the composition has a webServer. They carry a loopback-only fence: the
    Host must be loopback, a present Origin must match it, sec-fetch-site: cross-site is
    refused, and POST must be application/json.
  • RfbClient.waitForUpdate({ idleOk: true }) — silence at a message boundary means “the screen did
    not change” instead of an error, while a timeout inside a message stays fatal.

Fixed

  • inputChannel and sendkeyDelayMs never reached the tools. Both keys were missing from
    CONFIG_KEYS, so snapshot() dropped them and every run silently used the built-in auto/80 ms
    defaults: the settings form accepted the values, the code ignored them.

Verified

  • node tools/check-plugin.mjs — route inventory and fence (foreign Host, foreign Origin,
    cross-site and non-JSON POST all answer 403).
  • node tools/check-client.mjs — tab type, both sidebar seats, key, dictionary, declared
    ctx.inject(['sidebarRight', 'sidebarRightTabs']).
  • node tools/view-test.mjs against a live VM: a real HTTP server, state 200, a genuine PNG frame
    (1280×800 at half scale), ~1.2 s for the first frame and ~0.26 s incremental, release closing
    the session, and the check that watching leaves no agent-activity mark.

dsh-pve-vm 0.1.1 — Linux guest fixes

Choose a tag to compare

@taxah92 taxah92 released this 13 Oct 17:03

Linux guest support. Four defects that made the guest-agent half unusable on Linux — all found by
installing the plugin against a real RedOS 8 guest with a MATE desktop, not by reading the code.

Fixed

  • Guest OS detection rejected almost every Linux distribution. The guest agent reports id
    from /etc/os-release, and only IDs containing linux were accepted — RedOS reports redos,
    Debian debian, Ubuntu ubuntu. All of them landed in other, so every vm_* tool answered
    running a shell command is not supported for guest OS «other». Windows was unaffected
    (mswindows), which is why it went unnoticed.
  • vm_type_text typed nothing on a GDM desktop. The built-in typing script used
    $HOME/.Xauthority, which does not exist when GDM owns the session — RedOS and RHEL keep the file
    at /run/user/<uid>/gdm/Xauthority. xdotool then talked to the X server with no authorization,
    failed with No protocol specified, and the text never appeared.
  • vm_type_text could not submit text. text=$(… | base64 -d) — command substitution strips
    trailing newlines, so text ending in "\n" was typed without pressing Enter and the shell prompt
    never came back.
  • Console errors hid the actual cause. When the node's sshd does not accept AcceptEnv,
    LC_PVE_TICKET never arrives and qm vncproxy exits with a precise
    LC_PVE_TICKET not set, VNC proxy without password is forbidden — but the RFB reader saw EOF
    before ssh had finished exiting, so only the VNC stream was closed by the node surfaced.

Install: dsh plugin --profile web add dsh-pve-vm (or github:taxah92/dsh-pve-vm) — then enable
the bundle in the profile and restart the harness.

See README.md for requirements (root ssh,
AcceptEnv LC_*, guest agent) and CHANGELOG.md
for details, including the known 5-second QMP timeout on long guest commands.

dsh-pve-vm 0.1.0 — first public release

Choose a tag to compare

@taxah92 taxah92 released this 13 Oct 13:25

Proxmox VE VM control for DeepSeek Harness: 11 console tools (VNC/RFB: frame, pointer, keyboard, batch, Unicode clipboard) plus 5 guest-agent tools, over a single ssh connection, with zero runtime dependencies.

Install: dsh plugin --profile web add github:taxah92/dsh-pve-vm — then enable the bundle in the profile and restart the harness.

See README.md for requirements (root ssh, AcceptEnv LC_*, guest agent) and CHANGELOG.md for details.