Skip to content

feat(desktop): roaming pet (opt-in) - #55114

Merged
OutThisLife merged 8 commits into
mainfrom
bb/pet-roam
Jun 29, 2026
Merged

feat(desktop): roaming pet (opt-in)#55114
OutThisLife merged 8 commits into
mainfrom
bb/pet-roam

Conversation

@OutThisLife

@OutThisLife OutThisLife commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an opt-in "roam" mode for the desktop floating pet. Instead of sitting in one spot, the pet wanders the app like a little platformer character: it walks along surfaces, hops up onto the composer / profile rail, drops back down, and patrols the base of any open overlay — with proper directional walk/jump animations, paced to the sprite so it steps instead of gliding.

  • Opt-in via Settings → Appearance → Pet → Roam (off by default). Pure client behavior, persisted in localStorage like the pet's drag position — never runs when the pet is popped out into the OS overlay, and pauses while the agent is working (only roams when at rest).
  • Surface-aware wander (usePetRoam): re-measures walkable ledges from the live DOM each beat — the window floor, the composer (data-slot="composer-surface"), and the profile rail (data-slot="profile-rail") — then walks / hops / falls between them. Tracks the composer growing, the sidebar opening, window resizes, and falls back to the floor when a perch disappears (e.g. dropped mid-air after a drag).
  • Stands on the status bar, not over it: the bottom "floor" rests on the status bar's top edge (data-slot="statusbar") when present.
  • Follows overlays: when a full-screen route overlay (settings / profiles / cron / agents / command-center) is open, the pet's surface swaps to a single ledge at the overlay card's bottom edge so it patrols there; closing it restores the normal surfaces and the pet drops back down. The ledge is derived from OverlayView's shared inset (titlebar-height + padding) via the existing useRouteOverlayActive() signal — no element measuring.
  • Directional animation: roamWalkRow() uses the sprite's running-left / running-right rows for the travel direction, falling back to the generic running row + CSS mirror for pets that lack them. Hops/falls use the jump pose.
  • Grounded, sprite-paced walk: translation speed is derived from the sprite's animation loop + on-screen size (≈ one body-width per loop), so the legs match the motion; the pet also sinks a few px so its feet meet each surface instead of hovering.
  • Cache/render-safe: movement mutates el.style imperatively each frame (no per-frame React re-render, mirroring the existing drag handler); pose + direction publish through small nanostores ($petMotion, $petRoamDir) the canvas already subscribes to. State commits back to React only when the pet settles.

Implementation notes

  • $petState folds in a roam pose only when $petAtRest (agent idle), so a wander can never mask real agent activity.
  • No new core/model-tool surface — desktop-renderer only, plus three data-slot markers.

Test plan

  • tsc --noEmit, eslint, vitest (store/pet.test.ts covers at-rest gating + pose precedence) all green.
  • Toggle Roam on: pet patrols the status bar, strolls across the composer, hops onto the profile rail, drops back down — left/right walk + jump anims, feet flush on each surface.
  • Open an overlay (Settings/Profiles/…): the pet patrols the bottom of the overlay; close it → it drops back to the normal surfaces.
  • Drag into mid-air → it falls promptly to the surface below.
  • Roam off: pet stays put (no gravity), fully draggable.
  • Start an agent turn while roaming → pet stops and reacts in place; resumes on idle.

Opt-in $petRoam (localStorage), $petMotion (run/jump pose) and $petRoamDir (-1/0/1) feed the shared $petState only while the agent is at rest ($petAtRest), so a wander never overrides real activity.
roamWalkRow() prefers running-left/running-right rows, falling back to the generic running row with a mirror for pets that lack them.
usePetRoam re-measures ledges from the live DOM each beat and walks/hops/falls between them, driving DOM position imperatively (no per-frame re-render).
Tag both bars with data-slots; the roam loop stands on the status bar's top edge (not over it) and treats the profile rail as a climbable ledge.
@alt-glitch alt-glitch added type/feature New feature or request comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have labels Jun 29, 2026
…urface

Walk speed is derived from the sprite's animation loop + on-screen size (one body-width per loop) instead of a fixed px/s, so it steps rather than glides; the pet also sinks a few px so its feet meet the surface instead of hovering.
When a full-screen route overlay (settings/profiles/cron/agents/command-center) is up, the pet's walkable surface swaps to a single ledge at the overlay card's bottom edge — derived from OverlayView's shared inset, not measured — so it patrols there; closing the overlay restores the normal surfaces and it drops back down.
@OutThisLife
OutThisLife enabled auto-merge June 29, 2026 19:58
@OutThisLife
OutThisLife disabled auto-merge June 29, 2026 19:58
@OutThisLife
OutThisLife merged commit d417ffb into main Jun 29, 2026
20 checks passed
@OutThisLife
OutThisLife deleted the bb/pet-roam branch June 29, 2026 20:00
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants