- Rebuild the GPUI client against the 1:1 UI spec with all six modules,
terminal context menu, SSE reveal, system tray and standalone windows.
- Add an SFTP session self-healing layer: detect dead channels, drop the
cached session, reconnect and retry across every file and transfer path.
- Add a terminal refresh button that recreates the pane in place, with
proper loading and error feedback in both GPUI and the Web console.
- Route startup and autostart through vps-switch-gpui when it is present,
and make repeated launches wake the existing window via a file lock.
- Strip debuginfo in release, add a GitHub Actions matrix workflow for
macOS and Linux, and refresh the Windows installers and README.
Backend:
- Downloading a file from the local host through the transfer engine always
failed: the download branch had no LOCAL_HOST_ID case, so it opened SFTP
against 127.0.0.1:0 (reproduced: "SSH 连接失败: 地址无效 (os error 10049)").
The file browser's own download button goes through that path, so it was
broken in the UI too. The local branch now reuses stream_upload_to_host,
which already had one, keeping the temp-file/resume/SHA-256 guarantees.
- remove_item only refused the literal "/", so a Windows drive root listed by
the file browser ("此电脑" returns "C:/") could be deleted recursively. New
is_root_like() also covers drive roots, "." and "..", shared with
compress_item, plus unit tests.
- dir_cache grew without bound; capped at 256 entries, oldest evicted first.
- ExecTaskManager capped task count but not buffered bytes: 60 running tasks
could hold 120 MiB. Added a 32 MiB budget that evicts finished tasks only.
- Web sessions were only ever inserted, never expired, and every auth-settings
save minted another one. Now a token->issued map with a 30-day TTL, pruned on
every issue.
Frontend:
- A failed pane creation left the stage spinning "正在连接" forever (no retry,
and the standalone window has no tab bar to escape through). The failure is
now kept on the tab and rendered as an error with a retry button.
- The transfer-queue poller only cleared its 350 ms interval on success, so a
401 or a backend restart left it polling ~3 req/s indefinitely.
- The MCP call detail fetch had no sequence guard, so clicking two rows quickly
showed the wrong call's args and result.
- Only three call sites handled 401. Since the session table lives in memory,
every daemon restart invalidates all sessions, so with auth enabled this is
routine rather than an edge case. All protected requests now go through
apiFetch and return to the login screen.
- check-update read data.message, which the backend never returns (it returns
error), so failures only ever showed a bare "检查更新失败".
Docs: corrected the Claude Code setup commands (missing --transport http, and
x-vps-switch-key is not a header the server reads), fixed the Setup.exe PATH
claim, added measured memory numbers for both platforms, and added a
build-from-source section -- a clean clone cannot compile, since frontend/dist
is ignored while RustEmbed treats its absence as a hard error.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Scrub hardcoded hostnames from MCP descriptions, UI placeholders,
and documentation examples to prevent environment leakage.
- Remove hardcoded development database fallback from src/db.rs.
- Untrack .cargo/config.toml from version control and ignore local mirrors.
- Ignore test artifacts, screenshots, and WiX temporary outputs in .gitignore.
- Add Inno Setup script (installer.iss) for Windows Setup.exe wizard installer.
- Add WiX configuration (wix/main.wxs) for Windows MSI installer.
- Add systemd service template (vps-switch.service) for Linux deployments.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The call log was a bare table crammed into the MCP Server settings tab: no
way to read what an agent actually sent or got back, and no way to narrow
it down.
- mcp_calls gains a `result` column holding the full text returned to the
agent (previously only a one-line summary survived). Args and result are
each capped at 256 KiB, and hitting the cap writes the truncation notice
into the body itself instead of hiding it behind a flag. Existing
databases pick the column up via ALTER TABLE; old rows stay empty.
- GET /api/mcp-calls now filters by host, tool, ok, and a closed-open
time range. Host matching expands comma-joined batch targets, so
`vip-hk` finds "vip-hk,gateway,..." while `hk` still matches nothing.
- The list returns a 400-char args preview only; a new
GET /api/mcp-calls/:id serves one record's full args and result, so a
500-row view cannot pull hundreds of megabytes into the browser.
- Settings gets a fourth category, "调用记录": date range (local-day
boundaries converted to UTC instants), host/tool/result selects, reset,
and rows that expand into the complete args and result with copy
buttons.
Verified on the running build against 686 existing records: host, tool,
result, date and combined filters all narrow correctly, and a 300 KB
output shows the in-body truncation note.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- exec cancel: send an SSH signal and confirm the process group stopped before reporting cancelled
- terminal: reject pane_id whose host does not match the target host (read/send/key/close/reveal)
- auth: enable login by default on Linux/public bind; keep an explicit user choice
- terminal: build the send baseline from the actual PTY write, not from injection output
- exec: mark stdout/stderr explicitly when output exceeds the 1 MiB cap
- web download: deliver to the browser through the transfer engine and clean up staging
- mcp: unfinished tasks report ok=false; batch inspect fails when any item fails
- local: initialize OS metadata per platform and repair legacy Windows metadata on Linux
- cli config: keep PORT and DATA_DIR in the generated Claude/Codex stdio config
- update check: return 502/ok=false with real stdout/stderr/exitCode on failure
- frontend: add vue-tsc typecheck and fix the standardSQL import
- stdio bridge now falls back to in-process handling unless the forward returns a
real JSON-RPC response. A 401 from an API-key / data-dir mismatch used to be
printed verbatim as the tool result, so clients never completed the handshake
- MCP API key is enforced only when bound to a non-loopback address; on 127.0.0.1
it is exempt (local-first, like 1Shell). The remote toggle still governs HOST=0.0.0.0
- vps_terminal "key" action now passes through the command denylist; its fallback
branch could previously carry arbitrary text and bypass the guard
- vps_exec interactive-prompt early-exit now matches only explicit keywords, so
ordinary commands whose last line ends in ':' / '?' are no longer aborted mid-run
- terminal: add a "重新连接" button that recreates a pane in place after the session ends
- file browser: downloads go through the resumable + SHA-256 transfer engine
(default local path = Downloads, runs in background, non-blocking)
- standalone terminal window: hide the dead 文件管理 / 详情图表 buttons
- probe status: an SSH connection means online (probe failure no longer flips to
red); a connect timeout maps to unknown instead of offline; latency now measures
the connect only, not the probe
- transfer: a resumed download fails instead of silently accepting when the remote
hash is unavailable; secret.key is no longer overwritten when corrupt; a per-host
lock serializes pane creation
- CodeMirror 6 online editor (lazy-loaded chunk) with syntax highlighting,
search/replace, Ctrl+S save over SFTP, dark/light glass themes
- Streamed transfer resume: keep <target>.vps-part fragment on interruption,
reconcile source hash on re-issue and continue from fragment end
- Probe self-heals os_info: try recorded OS, fall back to the other family,
write back the real OS/version/arch (fixes hand-added hosts)
- Terminal uses its own SSH connection per host (released when last pane
closes) so the login MOTD is not eaten by the shared status-check session
- Shell-integration injection narrowed to headless MCP panes only; remote
echo off via pty-req ECHO=0 so nothing is drawn (no more line erasing)
- Frontend: roll back optimistic toggles and surface failures on autostart,
MCP settings, host delete/patch, and CLI sync instead of faking success