Commit graph

22 commits

Author SHA1 Message Date
hermes-seaeye[bot]
8c36cd4670
fmt(js): npm run fix on merge (#72411)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-27 02:52:53 +00:00
Andy
651a313d2b fix(desktop): suspend decorative work when inactive 2026-07-26 21:05:55 -05:00
Ho Lim
7a5d534f5b fix(desktop): gate idle renderer loops
Signed-off-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-07-26 21:05:55 -05:00
ethernet
e026fd61d8 lint(desktop): ban atom-mirrored refs via no-restricted-syntax eslint rule
A ref synced from a nanostores atom via useEffect lags the atom by one
render. Callbacks that read the ref instead of the atom get stale values —
cancelRun sent session.interrupt to the wrong session (#66485), and
steerPrompt/restoreToMessage/editMessage had closure-priority stale reads.

The rule catches the three shapes of this antipattern:
  - useEffect(() => { ref.current = value }, [value])
  - useEffect(() => { ref.current = value; ... }, [value])
  - useEffect(() => { setMutableRef(ref, value) }, [value])

All 79 existing hits get eslint-disable-next-line with a comment. The
legitimate ref writes (DOM instances, mount flags, request tokens,
prev-value tracking, prop mirrors) stay suppressed; the 11 real bug
sites will be fixed in the next commit so their suppressions can be
removed.

Rule is scoped to apps/desktop only — ui-tui and tests-js don't use
nanostores and don't have this pattern.
2026-07-25 18:12:48 -07:00
Brooklyn Nicholson
e4b2b77852 refactor(desktop): extract shared Progress primitive; billing uses it
Add components/ui/progress.tsx — one rounded track + animated fill that owns
role="progressbar" + aria. Migrate the hand-rolled bars (updates overlay,
onboarding, install overlay, billing usage, pet hatch) onto it.

- Pet's bar was never a color variant (--primary and --ui-accent are the same
  brand color); its only real difference is the sliding indeterminate, now an
  `animated` prop. Color stays a normal `fillClassName` override.
- Billing usage now uses the plain primitive — dropped the bespoke dither
  track, inset shadow, and danger nub; tone rides `destructive`/`fillClassName`.
- Drop the redundant emoji "no saved card" row description; the page-level
  warn banner is the single explainer.
- Rename pet CSS .pet-progress* -> generic .progress-slide.
2026-07-22 18:53:26 -05:00
Brooklyn Nicholson
1fa3886bce chore(desktop): remove the DEV Shift+H heart preview
The real trigger (core `reaction` event on affectionate messages) is live, so
drop the dev-only hotkey and its always-mounted listener.
2026-07-10 16:09:23 -05:00
Brooklyn Nicholson
3aaf7e3876 feat(desktop): TikTok-style vibe hearts on a reusable particle system
Add a glyph-agnostic ParticleField (float-up + organic sway/bank + springy
pop-in), skinned as pink pixel hearts. Hearts play on the pet when one is out
(in-window or popped out) and celebrate alongside; otherwise they rise from the
composer. A generic $petReaction bus mirrors the burst to the pop-out overlay
window so it reacts even while the app is minimized.

Consume the core `reaction` event to fire hearts on affectionate messages. DEV
Shift+H previews a burst.
2026-07-10 05:42:14 -05:00
ethernet
39d09453f9 feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
Brooklyn Nicholson
715aa3de85 refactor(desktop): adopt shared utils + app-wide cleanups
Route the app off its hand-rolled helpers onto lib/{text,time,format,json-format}
and the new primitives, plus assorted small tidy-ups:
- compactNumber for counts/tokens; normalize/capitalize/asText at the many
  filter/label sites; shared Intl date/time formatters; row-hover + framed
  editor adoption; scrollbar-gutter + padding parity on list surfaces.
- Messaging/Artifacts/Cron search hints + narrow-viewport tab dropdown;
  floating-pet adopts useOnProfileSwitch; number formatting in statusbar,
  command-center, agents.
- Electron: native overlay width + backend spawn tidy.
- Settings > Keys: credential fields read as plain subtext (all-unset) until
  the group is focused or expanded, then take full input chrome with no
  horizontal/vertical shift; inline Remove (trash) + Save mirror SearchField's
  trailing-clear pattern instead of a floating hint that overlapped the card;
  Esc still cancels. Drops the now-dead or/escToCancel i18n keys.
- Shared TabDropdown/ResponsiveTabs (components/ui): PageSearchShell and the
  Command Center log file/level filters reuse the one narrow-width collapse.
- OverlayNav: data-driven pane nav — persistent rail on wide, a single dropdown
  riding the titlebar strip on narrow; Settings and Command Center adopt it, and
  the mobile dropdown carries the same section icons as the rail. Fixes narrow
  vertical centering, redundant mobile section titles, gateway-status wrap, and
  Panel master/detail stacking.
- OverlayIconButton is now the titlebar ghost button, matching the close X at
  every size. Settings sub-view nav opens section + sub-view in one navigate so
  API-keys/accounts actually open on narrow.
- Settings > Model: cube icon (was the {} namespace glyph) and a DOM-shaped
  skeleton in place of the centered spinner.
- Command palette / session switcher clear the macOS traffic lights on small
  screens.
- Prettier/eslint sweep across the touched files.
2026-07-03 13:48:44 -05:00
Brooklyn Nicholson
30cd39dc56 refactor(desktop): collapse stroll-direction coin to a single draw
DRY: the roomier-side bias computed its probability two ways
(STROLL_TOWARD_ROOM and 1 - STROLL_TOWARD_ROOM). One draw XNOR'd against
the roomier side says the same thing more plainly.
2026-06-29 22:53:38 -05:00
Brooklyn Nicholson
b7322f946d feat(desktop): calmer, more realistic pet roam + split roam modules
The floating pet wandered almost constantly: every idle beat picked a new
walk and hops fired ~45% of the time, so it read as nervous rather than
alive. Make movement the exception, not the default, and split the
overgrown roam hook into focused modules.

Behavior (per ambient game-AI: GameAIPro ch.36 + idle/wander state
machines):
- Loaf, don't pace: most decision beats just keep resting (REST_CHANCE
  0.62) instead of always re-walking.
- Memoryless dwell: pauses now draw from an exponential distribution
  (mostly short rests, the occasional long loaf) instead of a uniform
  1.8-5.2s window, so the cadence never reads as a metronome.
- Hops dialed back 0.45 -> 0.2 (the jumpiest, noisiest motion).

Structure (no god-file; a hook should own one narrow job):
- roam-behavior.ts - what to do & when (dwellMs, chooseMove,
  pickStrollTarget) + tuning. Pure, rng-injectable.
- roam-geometry.ts - where it can stand (snapshotLedges, overlayLedge,
  resolveLedge, overlapsX, groundTop). DOM measurement + pure ledge math.
- use-pet-roam.ts - the physics/RAF loop only.

Tests: deterministic, rng-seeded unit coverage for the decision + geometry
helpers (behavior contracts, not snapshots).
2026-06-29 22:51:09 -05:00
Brooklyn Nicholson
a1e699ae55 feat(desktop): roaming pet patrols the base of an open overlay
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.
2026-06-29 14:57:26 -05:00
Brooklyn Nicholson
0e2a5a3206 feat(desktop): ground the roaming pet — sprite-paced walk + feet on surface
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.
2026-06-29 14:47:37 -05:00
Brooklyn Nicholson
7d3c1d55f4 feat(desktop): wire roaming into the floating pet 2026-06-29 14:26:02 -05:00
Brooklyn Nicholson
a8f1d9cc76 feat(desktop): add surface-aware pet wander loop
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).
2026-06-29 14:26:02 -05:00
Brooklyn Nicholson
964ec680cc feat(desktop): pick directional run row from travel direction
roamWalkRow() prefers running-left/running-right rows, falling back to the generic running row with a mirror for pets that lack them.
2026-06-29 14:26:02 -05:00
Brooklyn Nicholson
62fe9fd101 style(desktop,tui): fix all lint/type/formatting issues
Bring apps/desktop and ui-tui to a clean state for typecheck, eslint,
and prettier:

- Run prettier across both trees (printWidth/wrap drift; prettier is not
  CI-enforced for these JS projects, so main had accumulated drift).
- Apply eslint --fix for padding-line-between-statements and perfectionist
  import/export sorting.
- Manual fixes for non-auto-fixable rules:
  - remove unused node:net import in electron/main.cjs (uses Electron net)
  - replace inline `typeof import(...)` annotations with top-level
    `import type * as EnvModule` in two ui-tui test files
  - scoped eslint-disable no-control-regex on intentional sentinel/ANSI
    regexes (mathUnicode.ts, text.ts)
  - resolve react-hooks/exhaustive-deps per-case: correct swapped/missing
    deps, collapse redundant session.* members, and justified disables on
    settings mount-only data-load effects to preserve run-once behavior

No behavior changes; test pass/fail counts are unchanged from the main
baseline.
2026-06-26 01:04:33 -05:00
Brooklyn Nicholson
7d1b72a15d feat(desktop): zoom the pet toward the cursor
Alt+wheel now scales about the pixel under the pointer instead of growing from a
corner, so the pet stays put under the cursor instead of running away. In-window
shifts its top-left; the overlay repositions its OS window (cursor-anchored on
wheel, bottom-center for slider-driven changes).
2026-06-26 00:37:45 -05:00
Brooklyn Nicholson
dd980aaba1 feat(desktop): Alt+wheel to scale the pet, never cropped
Hold Alt/Option and scroll over the mascot to resize it (same on Mac and
Windows); the modifier keeps a plain scroll passing through to the page. The
gesture drives the same `display.pet.scale` path as the settings slider.

The popped-out overlay grows its OS window to fit the pet at any scale (anchored
bottom-center) so the sprite is never clipped by the window edge, and the
in-window pet re-clamps against its actual size so growing near an edge can't
crop it. Also makes the overlay click-through per-pixel: only solid sprite
pixels (plus bubble / mail button) are interactive, transparent margins pass
clicks through.
2026-06-26 00:33:22 -05:00
Brooklyn Nicholson
1fe013ee16 feat(pets): polish generate flow and reduce hatch CPU pressure
Ship the final pet-generation UX polish (provider picker behavior, step-2 cancel flow, banner integration, and visual consistency) and make saturated-chroma background removal C-op driven so hatch processing no longer hammers the machine during long runs.
2026-06-24 19:08:06 -05:00
Brooklyn Nicholson
743985bf1e feat(pets): Pokédex generate UI — overlay, animated egg, hatch FX, manage
Dedicated generate modal (Cmd-K → Pets → Generate): prompt → 2×2 draft
grid → egg hatch → preview → adopt, width fits each phase.

- Reuses shared primitives (Button/Input/Dialog/Alert/GenerateButton);
  cards use selectableCardClass; only canvas + range stay raw.
- Animated creme pixel egg + PetStarShower hatch celebration (canvas).
- Live streamed drafts with a real Stop (AbortSignal); clean default name.
- Manage generated pets: badge + top ranking, rename (optimistic), safe
  delete (confirm + drop), export — in both the Cmd-K and Settings lists.
- pet-gallery routes every RPC through profile-scoped petRpc; i18n ×5.
2026-06-24 13:51:34 -05:00
Brooklyn Nicholson
86b990fe0f feat(desktop): floating pet, pop-out overlay + Cmd+K picker
Add the in-window floating pet (sprite, speech bubble, contact shadow,
profile-scoped, resize-safe) and a pop-out always-on-top overlay window
with gestures and notifications. Add the Cmd+K pet picker page plus the
appearance gallery and size slider in settings. Includes the pet stores,
electron overlay wiring, i18n strings, and store tests.
2026-06-20 14:18:40 -05:00