Files
buzz/desktop
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7andWill Pfleger a8bb389cd6 fix(desktop): render archived observer history for idle agents and reset paging on channel switch
F7 — idle agent archived history not renderable (CRITICAL):
getAgentObserverSnapshot and getAgentTranscript were early-returning empty
when enabled=false, discarding ingested archived events. The enabled flag
conflated two concerns: subscribing to the live relay, and reading stored
data. Only the relay subscription should gate on isLive/hasObserver.

Fix: drop the !enabled early-return in both store readers; keep !agentPubkey
as the only guard. The enabled parameter is retained for call-site
compatibility (renamed to _enabled) but no longer controls store reads.
The relay subscription useEffect in useObserverEvents still gates on enabled
so idle agents don't trigger unnecessary relay connections.

Also fix the EmptyObserverState gate in ManagedAgentSessionPanel: previously
shown whenever !hasObserver regardless of content, now only shown when the
agent is idle AND there is nothing to display (transcript.length === 0 &&
events.length === 0). This allows archived channel history to render for
idle agents instead of showing the empty state.

F8 — archive paging state not scoped to channel (IMPORTANT):
useLoadArchivedObserverEvents held hasOlderArchived, cursorRef, and
isFetchingRef in a single hook instance while channelId changed across
channel switches in the same AgentSessionThreadPanel lifecycle. Channel A's
exhausted state and cursor bled into channel B — B would not page, or B's
first read would skip rows newer than A's cursor.

Fix: add a useEffect([channelId]) that resets cursorRef to null,
isFetchingRef to false, and hasOlderArchived to true on channel change.
Backfill state (backfillStatusRef/backfillPromiseRef/backfillResolveRef)
is identity-level and deliberately NOT reset — backfill covers all channels
and only needs to run once per identity mount.

Tests: two new regression cases in ingestArchivedObserverEvents.test.mjs:
- test_idle_agent_archived_events_readable_when_enabled_false: idle agent
  with archived rows for two channels reads both (enabled=false no longer
  blocks), and scopeByChannel returns only channel-A frames for channel A
  with zero channel-B contamination.
- test_channel_switch_resets_cursor_and_exhaustion: verifies the paging
  state-machine semantics — channel A exhausted then channel switch resets
  cursor/hasOlderArchived/isFetching. Plus a spec test confirming backfill
  state fields are identity-scoped and must not reset on channel switch.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-07-08 15:02:45 -04:00
..
2026-06-11 15:06:24 +00:00

Buzz

Desktop chat shell with:

  • Tauri + React + TypeScript + Vite
  • Tailwind CSS
  • shadcn/ui-ready shared components
  • Biome (lint/format/check)
  • Feature-driven frontend structure

Scripts

  • pnpm dev - run the web frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm format - Biome format (write)
  • pnpm check - Biome check

Structure

  • src/shared - reusable app-wide code (ui, lib, styles)
  • src/features - feature modules (vertical slices)
  • src/app - top-level app composition