[3.3.5] - 2026-04-03
CLI serve HTTP/WebDAV, GitLab Tier 1, rclone parity, streaming transfers & UX polish
Added
- Native MCP server mode:
aeroftp-cli agent --mcpnow runs a real Model Context Protocol server over async stdio. Exposes 16 curated remote tools, profile/resources discovery, reusable prompts, connection pooling, rate limiting, and audit logging for Claude Desktop, Cursor, VS Code, and other MCP clients - AI stream cancellation: Users can now stop a stuck AI generation at any time. Backend uses
tokio::select!withwait_for_cancel()polling every 200ms - works even when the stream is completely blocked (e.g. Ollama models hanging). GlobalACTIVE_STREAMSregistry withArc<AtomicBool>per stream. Newai_cancel_streamTauri command. Frontend shows a filled square Stop button during any streaming, not just multi-step auto-execution. Conversation switching also cancels backend streams (previously only stopped frontend listening) - Agent mode quick-switch dropdown: Copilot-style dropdown in AeroAgent chat header for instant mode switching between Safe, Normal, Expert, and Extreme. Shows current mode with colored icon + description. Replaces the old badge that only opened settings. Extreme mode locked to Cyber theme with warning
- Anthropic prompt caching (3 levels): Full prompt caching implementation for Anthropic provider - system prompt (already existed), tool definitions (new - caches all 47 tool defs via
cache_controlon last tool), and multi-turn conversation history (new -cache_controlon last user message). Applied to both streaming and non-streaming paths. Up to 90% cost reduction on long conversations - GitLab Releases browser: Full release management modal with list, create, delete, upload/download assets. Assets uploaded via Generic Packages API and linked to releases. Source archives (zip/tar.gz) with direct download. Orange-branded UI with Tag icon in toolbar
- GitLab asset download: Authenticated backend download via PRIVATE-TOKEN header. Works for private repositories (no browser redirect needed)
- GitLab Merge Requests: Create MR from non-default branches with "MR" button in status bar. Auto-detects existing open MR. Guard prevents source==target branch MR
- GitLab write mode: Three-state model (direct/branch/readonly). Status bar shows "Direct" on default branch, branch name + MR button on feature branches, "Read-only" without push access
- GitLab View on GitLab:
gitlab_get_web_urlcommand builds encoded web URLs for files and directories - GitLab CHANGELOG import: Import release notes from CHANGELOG.md in Create Release form. Always reads from repo root regardless of current navigation path
- GitLab self-hosted TLS: Accept self-signed certificates toggle for self-hosted instances (appears when host is not gitlab.com)
- GitLab form improvements: Branch field, token creation link, remote/local path fields, save connection with icon picker
- CLI
serve http: Expose any remote as a local read-only HTTP server. HTML directory listing with navigation, file download, HEAD without download, range requests (HTTP 206 Partial Content withContent-Range),Accept-Ranges: bytes, MIME type guessing, path traversal protection, graceful Ctrl+C shutdown. Supports all 27 providers via URL or--profile. See APPENDIX-W - CLI
serve webdav: Expose any remote as a local read-write WebDAV server. PROPFIND (Depth 0/1, XML DAV: namespace), GET, HEAD, PUT (512 MB cap), DELETE (file + directory), MKCOL, MOVE, COPY (nativeserver_copyor download+upload fallback), OPTIONS with DAV header. Reuses path primitives and state from serve http - Provider range download:
read_range(path, offset, length)for FTP (REST + bounded RETR), S3 (Range header, 206/200 handling), and WebDAV (Range header with server-ignoring fallback). 100 MB per-request safety cap. Newsupports_range_downloadflag inTransferOptimizationHints
Fixed
- MCP request cancellation semantics:
notifications/cancellednow cancels real in-flight requests and suppresses late responses from cancelled work instead of only acknowledging the notification - MCP read preview safety:
aeroftp_read_filenow rejects directories, refuses previews above 1 MiB before allocation/download, and still caps returned text to 5 KiB - MCP delete safety:
aeroftp_deletenow distinguishes files, empty directories, and recursive directory removal. Non-empty directory deletion requiresrecursive=trueinstead of ambiguous fallback behavior - Auto-restart after update: App would close but not relaunch after installing an update. Root cause was a race condition with the DBus single-instance lock - the restarted process would see the name as still taken and silently exit. Replaced
spawn_detached_relaunch+app.exit(0)with Tauri 2'sapp.restart()which guarantees proper plugin cleanup (DBus name release) before relaunching. Added explicittauri_plugin_single_instance::destroy()call. Increased restart helper grace period from 1s to 3s as safety net - ScanningToast missing for provider operations: Folder download, upload, and delete via providers (SFTP, WebDAV, S3, Google Drive, etc.) showed no scanning spinner during recursive scan. Only FTP operations emitted scanning events. Added scanning event emission to
provider_download_folder,provider_delete_dir, and provider folder upload - Health check stuck after navigation: Provider health scan would permanently lock after navigating away during an active scan. The module-level
scanInProgressflag was never reset on component unmount. Added unmount cleanup, scan generation counter to ignore stale events, and 30-second safety timeout - SourceForge SSH label contradiction: "SSH Authentication (Optional) (required)" now correctly shows "SSH Authentication (required)" for SourceForge
- SourceForge filter category: SourceForge now appears under "Dev" filter instead of "FTP / SFTP" in My Servers
- SourceForge docs link: Fixed help URL from
/protocols/sourceforgeto/providers/sourceforge - GitLab branch not working: Branch field value was not passed to backend (only GitHub received it). Now both forges share the branch passthrough
- GitLab can_push fallback: Conservative default (read-only) when branch permission check fails, instead of assuming write access
- GitHub CHANGELOG import from subfolder:
github_read_filenow always reads from repo root, not relative to current navigation directory - Post-restart log: Activity log now shows clean "Update completed via .deb (Verified)" instead of "Verified: false, Mode: VerificationUnavailable"
- Post-restart toast: Shows "SHA-256 Verified" or "Sigstore Verified" instead of blank
- Update marker: SHA-256 verified updates now marked as
verified: truein marker file
Improved
- MCP test coverage: Added focused unit coverage for request-id handling, cancellation extraction, read preview validation, delete mode selection, and schema exposure for recursive deletion
- Activity log for releases: All release operations (create, upload, download, delete, remove asset) now logged in activity panel for both GitHub and GitLab. Previously only GitHub download was logged
- GitLab asset link_type auto-detection: Smart content-type mapping from file extension (archives/installers as "package", images/disk images as "image"). Covers .zip, .tar.gz, .exe, .deb, .rpm, .msi, .dmg, .appimage, .iso, .qcow2, and 20+ more extensions
- Streaming scan+transfer for folder downloads: Both FTP and provider backends now use directory-by-directory interleaving instead of scan-everything-then-transfer. The first file starts downloading after listing just the root directory (~1-2s), not after the full recursive scan (~30-40s for deep trees). Progress shows "(X/Y+)" where "+" indicates the total is still growing. Frontend ScanningToast stays visible during streaming mode without flickering
- Backend logging for GitLab and GitHub: Added
log::info!()to all release operations (create, delete, upload, download assets), commit actions, branch switching, merge requests, and pull requests. Previously GitLab had near-zero logging and GitHub only logged PEM/token operations - Git forge polling stability: Removed
sessionsfromrefreshGitHubContextdependency array to prevent cascading API calls on unrelated state updates. Previously any session mutation would re-trigger get_info + list_branches for the active forge - Jottacloud share links: Disabled unverified implementation. Was returning XML errors against live API.
supports_share_links()now returnsfalseuntil verified - i18n: Added 17 new keys for GitLab, release operations, and AI chat translated across all 47 languages
Downloads:
Windows
.msiinstaller.exesetup.zipportable (no installation required)
Linux
.deb(Ubuntu, Debian).rpm(Fedora, RHEL).AppImage(universal).snaporsnap install aeroftp- AUR (Arch Linux)
macOS (beta - not code-signed, see note below)
.dmgApple Silicon (M1/M2/M3/M4)
macOS note: The
.dmgis not yet signed with an Apple Developer ID certificate. After installing, run:sudo xattr -rd com.apple.quarantine /Applications/AeroFTP.app