Commit Graph
6 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 b9e31178f3 Keyboard and trackpad for the Frame, through its own KDE Connect
Home → Keyboard and trackpad, in every version of Frame Control (Mac,
Windows, Linux, iPhone, iPad) with nothing to install on the device in
your hand. On a phone: a trackpad (drag, tap, two-finger scroll and
right-click) and a field that types on the Frame. On a computer: click
the pad to pass the mouse and keyboard through; Esc to stop.

First-party route: ui/frame_input_agent.py runs on the Frame and talks
KDE Connect's LAN protocol (v7) to kdeconnectd as if it were a phone.
KDE Connect isn't on the image, but Valve's package repository has it;
the agent fetches it and four libraries into ~ (no root, survives
updates), starts it, pairs by itself (accepting over D-Bus), and stops
it again when the last device disconnects. Each device has its own
identity; a stuck KDE Connect is restarted once.

Verified against the real Frame (SteamOS 0.4.1): first-time install,
pairing, pointer moves from the Mac's server and the iPhone app
(Simulator), Mac and iPhone at once, two installs at once, a frozen
daemon replaced, and the daemon stopping when the app quits.

Reviewed by GPT-6 Astra (xhigh) over seven rounds; all findings fixed
except per-event delivery acknowledgement (documented known limit).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:42:19 +10:00
saphidandClaude Opus 5.5 c711e136d4 iPhone app: a first screen that says exactly what to do
The app finds the Frame by itself (Valve's _steamos-devkit._tcp Bonjour
service, else the saved address or frame.local on port 22), so setup is two
numbered steps: wake your Frame (Looking… / Found ✓, and after a few seconds
exactly what to check), then the Developer Mode password and Connect. Manual
address and key options sit under Other ways to connect.

A paired Frame that doesn't answer is almost always asleep: instead of an
error, Waiting for your Frame says how to wake it and connects as soon as its
SSH port answers (checked every 3 s; 4 s after the stand-in came back).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 18:16:14 +10:00
saphidandClaude Opus 5.5 aafd2dbda8 iPhone app: test pairing and power against a Holo Core stand-in
Valve publishes no Steam Frame OS image, so tests/frame-container builds the
Frame's SSH surface on Valve and Collabora's Holo Core aarch64 base: a
steamos user with a password and sudo, OpenSSH with keys and passwords,
Python, and a systemctl that only records requests.

Against it from the Simulator: password pairing, the host-key pin, the power
password check. Found and fixed: a changed host key or a refused login said
"Can't reach the Frame" and retried forever; they now say "Pair with the
Frame again" and offer that. The server's key rejection now says the header
may be wrong, not only missing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 15:44:42 +10:00
saphidandClaude Opus 5.5 14790ac768 Fix the follow-up review's findings
- Pairing saves nothing if it was cancelled while adding the key.
- The ssh stand-in runs under bash: dash refuses job control without a
  terminal, which cost stdin and the process group.
- A server that stops while the tunnel opens fails the attempt (and retries)
  instead of leaving it half-connected.
- The health probe answers within its deadline even when a dead link keeps
  the probe itself waiting.
- A cached version is deleted only if no server runs from it (servers now run
  by absolute path) and it's two weeks unused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:40:17 +10:00
saphidandClaude Opus 5.5 a910f83ac1 Fix the iPhone review's findings
- Cancelling (Change headset, Forget) invalidates the attempt in flight; a
  connection only becomes the app's once every step finished for it.
- A server that stops while the tunnel opens is noticed (exit callbacks are
  synchronised and replayed), and the app isn't left showing a dead page.
- The port is read only once the digits are complete, and range-checked.
- Other versions in ~/.cache/frame-control stay unless untouched for 14 days,
  so a second phone or iPad isn't cut off.
- The key is appended on its own line even if authorized_keys lacks a final
  newline.
- The app checks every 20 s, and on returning to the foreground, that the SSH
  session still answers, and reconnects if not.
- The ssh stand-in runs the command as its own process group and passes a
  TERM on to all of it, so a live-video ffmpeg stops with its stream.
- Touch screens show the library's Play buttons (the rule now follows the
  base one); the failure screen only says it's retrying when it is; the page
  says the app reconnects rather than naming a desktop menu.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:30:40 +10:00
saphidandClaude Opus 5.5 13187e8f6a iPhone and iPad app: the same features, served from the Frame
An iPhone can't run Python or ssh, but the Frame can. The app (ios/, SwiftUI)
connects with its own SSH key (Citadel), copies the server and helpers to
~/.cache/frame-control/<version> on the Frame once per version, starts
ui/server.py there with FRAME_LOCAL=1 on the Frame's 127.0.0.1, and shows the
page through an SSH tunnel. The server exits when the phone disconnects.

Server: FRAME_LOCAL=1 puts ui/local-bin on PATH, whose ssh stand-in runs each
`ssh frame COMMAND` locally (and serves as rsync's transport), so desktop and
phone share one code path. Android display goes through podman exec there, as
the Frame has no adb. FRAME_UI_KEY replaces the fixed X-Frame-UI value with a
per-session key. Power actions take the Developer Mode password via sudo -S.
--port 0 now prints the port it took.

Page: a bottom tab bar and safe areas on phones, Play buttons visible on touch
screens, saving through the share sheet, SSH/SFTP/Steam Link/remote desktop
opening in their iOS apps, and a password dialog for power.

App: pairing with the Developer Mode password once (never stored) or with a
key the user adds; host key pinned on first use; plain-language connection
errors with quiet retries; frame-control://install links; alerts and confirms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:18:15 +10:00