`_stream_frames` (the mobile JPEG fallback) retried forever: on `TimeoutError`
it logged and `continue`d, and on `captured is None` it just `continue`d. A
phone unplugged mid-stream, or a dead adb bridge, makes every capture fail at
once, so the loop spun at the frame interval indefinitely — a warning per
iteration, a log flood, and a canvas frozen on the last frame with nothing ever
sent to explain it.
The desktop sibling `desktop/stream.py::_stream_loop` already counts consecutive
misses, warns once, and after 30 sends an error frame and breaks. This mirrors
that: timeouts and `None` both count as misses, the first one is logged once,
and at `_CAPTURE_MISS_LIMIT` (30) the stream sends the
`{"type": "error", "message": ...}` frame the rest of this router already uses
and returns. A successful frame resets the streak, so an occasional dropped
frame still does not tear the stream down.
Folding the timeout branch into the shared counter also removes the
per-iteration warning flood.
Passwordless sudo can install the engine, but /etc/docker/daemon.json and
systemctl restart still need elevation; otherwise the Tencent mirror step
silently skips.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Vendor install-docker.sh (official get.docker.com script with
TencentOS / OpenCloudOS releasever mapping and mirror-domain rewrites)
into scripts/linux/v1.0/ so unsupported-by-online-script distros still
install and we never pipe the network straight into sh; wheel ships
it via the existing **/*.sh package rule.
- auto_install_docker_stream runs the bundled script with the raced
DOWNLOAD_URL env var instead of curl|sh (curl pipe used to swallow
download failures).
- Error compatibility: classify script output tail against known
failure modes (unsupported distro, no root, network/curl, package
manager lock, GPG key, disk full, existing docker) and append a
localized fix hint; dedicated messages for spawn failure, stalled
output (read watchdog), and missing bundled script; restart-failure
message now tells how to start Docker manually.
- Tests: error classification, bundled-script presence, missing-script
stream, friendly-hint emission; full mobile suite green (57).
- New docker_install.py: latency-race install sources (official
download.docker.com + CN mirrors, no geo detection; official wins →
no DOWNLOAD_URL override), run official get.docker.com script,
probe Tencent Cloud registry mirror reachability and merge
registry-mirrors into /etc/docker/daemon.json (backup kept) only
after a fresh install.
- install_mobile_stream: when Docker is missing on Linux with
root/passwordless sudo, attempt the automatic install first and
continue with the container install when the daemon is ready;
otherwise fall back to the manual-install error.
- i18n (backend en/zh + dashboard locales) and install-guide copy
updated; CHANGELOG entry added.
- Unit tests for source selection, daemon.json merge, probe, and the
install stream branches (auto-install ok / fail / no-sudo).
Remote Phone gets a WebSocket-backed adb shell, honest display rotation verification, and a VS Code-style collapsible shell pane on desktop with resizable split and mobile tab switching.
* feat: minimal layout, user email, KB text docs, and remote desktop hub
Add classic/minimal chrome with a unified chat records host, optional user
email (invite/login), in-app markdown/txt knowledge editing, and a combined
remote desktop/phone control surface—plus host path and mobile setup hardening.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(host_dirs): don't jail host-root browse to home drive on Windows
The restrict_to_home=False case allows any absolute host path (no home
jail). On POSIX everything sits under '/'; on Windows the denylist is
empty and windows_neutralize_host_root rewrites root_dir '/' at runtime,
so a drive-relative '/' must stay allowed. The new _path_within_base
containment incorrectly rejected root_dir '/' on Windows when the checkout
drive differed from the home drive, breaking from-expert/local_shell agent
creation.
Also mark test_install_published_expert_accepts_create_options posix_only:
it relies on local_shell workspace file writes unsupported on Windows.
---------
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(mobile): add Remote Android probe, API, stream, and dashboard
Multi-backend mobile support for self-hosted Octop: install-time host
capability probe, gated /api/mobile routes, adb WebSocket stream, and
Control → Remote Android dashboard page for Mac/emulator dev paths.
* feat(mobile): wire harness agent adb tools for Remote Android
Register mobile_screenshot, mobile_tap, mobile_swipe, mobile_launch_app,
mobile_ui_dump, and mobile_handoff_to_user when capabilities.mobile is
enabled, with permission and readiness checks.
* feat(mobile): polish Remote Phone UX and session-bound agent control
Rename the surface to Remote Phone, add quality presets, device info, AI
panel, and chat-dock phone tab; bind agent tools to the active stream
session and cover with unit tests.
* chore(mobile): drop docs/specs/remote-android.md from the PR
* fix(mobile): ruff I001 import formatting in device_info tests
* fix(mobile): resolve adb via PATH and SDK env only
Drop hardcoded per-OS SDK layout guesses; honor PATH, ANDROID_HOME,
and ANDROID_SDK_ROOT (with adb.exe on Windows).
* style(mobile): apply ruff format to mobile modules
CI runs ruff format --check; keep these files format-clean.
---------
Co-authored-by: jubaoliang <jubaoliang@gmail.com>