mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 00:02:29 +00:00
* feat(mobile): draw the last known tab strip while a session reconnects Reopening a workspace the phone has already visited threw away everything it knew. The route clears its tabs on mount, so until the reconnect lands and the first snapshot is applied the session screen has an empty header and a bare spinner, even though the strip it is about to be handed is the one it drew a minute ago. Persist the four fields the strip actually draws -- id, type, title, agent -- per host and workspace, and add a reconnecting-with-cache shape to the route state so those rows render immediately, disabled, under the ids the live snapshot will reuse. Live tabs always outrank the cache, so a mid-session drop keeps its mounted terminals; an exhausted retry loop or a rejected pairing outranks it the other way, because a strip the user cannot reach is worse than the existing offline affordance. With nothing cached the screen behaves exactly as before. The body stays a placeholder. Replaying stored scrollback into the terminal WebView would double-render the same rows once the live stream replays them, so the strip is the cached content and the body waits for the stream. * fix(mobile): keep shell titles and unpaired hosts out of the cached tab strip Review of the reconnect strip cache found two ways it leaked. A terminal's title is whatever the shell last set, which is routinely the command line: a psql URL with an inline password, a curl with a bearer token. Both fit well inside the 64-character cap and both were written to plaintext AsyncStorage verbatim. Browser tabs carried their page title the same way. Terminals and browsers now collapse to a fixed label, with a resolved agent naming itself because that lookup is a closed enum. The rule lives in the storage module rather than its caller, so it holds for entries an older build already wrote, and a tab type this build cannot draw is dropped instead of having its title trusted. The cache also survived forgetting a host. Nothing expired an entry, and the module-global memory map meant a later save from any surviving host serialized the forgotten host's rows straight back to disk. Both cleanup paths now evict by host, dropping the in-memory rows and rewriting storage, with a pending debounced write cancelled so it cannot restore them. Also: the storage key digests the workspace id, which ended in a filesystem path, and cached rows carry the same de-emphasis as the disabled tab-bar buttons beside them, so an inert row does not pass for a live one.