Skip to content

feat(desktop): refresh Agents tab live on inbound relay sync#1256

Merged
wpfleger96 merged 3 commits into
mainfrom
duncan/persona-sync-live-refresh
Jun 25, 2026
Merged

feat(desktop): refresh Agents tab live on inbound relay sync#1256
wpfleger96 merged 3 commits into
mainfrom
duncan/persona-sync-live-refresh

Conversation

@wpfleger96

Copy link
Copy Markdown
Collaborator

Inbound persona/team/managed-agent relay events are reconciled to disk on the receiving device, but nothing signaled the live UI — so another device's edit or deletion only appeared after an app restart. This wires the live refresh: the Agents tab now updates without a restart.

Changes

  • Backend (commands/personas.rs): both inbound reconcile paths — reconcile_inbound_persona_event (upserts, all three kinds) and reconcile_inbound_tombstone (deletions) — emit a coarse agents-data-changed Tauri event after their disk write commits. These are the only inbound writers to the agents stores, so two emit sites cover the full inbound surface.
  • Frontend (useAgentsDataRefresh.ts, new): a root-mounted listener invalidates the four agents React Query keys (personasQueryKey, teamsQueryKey, managedAgentsQueryKey, relayAgentsQueryKey) on that event.

Design notes

  • The listener mounts identity-agnostic at the AppShell root, not inside the pubkey-keyed usePersonaSync hook. Folding it in would re-register the listener on every identity switch and leak one per switch; invalidation is global and has no reason to be pubkey-scoped.
  • The listener debounces with a 200 ms trailing coalesce. A one-shot backfill feeds up to 500 inbound events through reconcile one-by-one, each emitting agents-data-changed; coalescing collapses the burst into a single invalidate rather than depending on React Query's implicit in-flight dedup and paying redundant disk-read IPC.
  • The backend emit is unconditional and coarse — it cannot distinguish a backfill burst from a live burst, so the burst handling lives entirely on the consumer side.

This is part of the persona/team/agent relay-sync arc and is the user-visible follow-on to #939 (which landed the publish + inbound-reconcile-to-disk substrate). The live cross-device round-trip is exercised by an E2E test and manual two-device smoke in the next phase — this PR's unit/lib gates do not prove the render path on their own.

@wpfleger96 wpfleger96 marked this pull request as draft June 24, 2026 23:03
@wpfleger96 wpfleger96 marked this pull request as ready for review June 25, 2026 04:18
@wpfleger96 wpfleger96 force-pushed the duncan/persona-sync-live-refresh branch 7 times, most recently from fa7a1e7 to 4b51bbe Compare June 25, 2026 17:50
@wpfleger96 wpfleger96 closed this Jun 25, 2026
@wpfleger96 wpfleger96 reopened this Jun 25, 2026
@wpfleger96 wpfleger96 force-pushed the duncan/persona-sync-live-refresh branch from 4b51bbe to c0b2988 Compare June 25, 2026 17:59
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 and others added 3 commits June 25, 2026 13:59
Inbound persona/team/managed-agent relay events reconciled to disk but
never signaled the UI, so a device only saw another device's edits after
an app restart. The two inbound reconcile paths now emit a coarse
`agents-data-changed` event after their disk write commits, and a new
root-mounted listener invalidates the four agents query keys.

The listener mounts identity-agnostic (it does not live inside the
pubkey-keyed persona-sync hook, which would leak a listener per identity
switch) and debounces with a trailing coalesce so a backfill burst of up
to 500 events yields a single invalidate rather than leaning on React
Query's implicit in-flight dedup.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
reconcile_inbound_persona_event drives the full inbound path (upsert +
tombstone) and the agents-data-changed emit. Tests verify the record
lands in list_personas, the deletion removes it, and the emit fires on
both paths — covering the Phase 1 wiring that unit tests cannot reach.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…idge

The persona-sync E2E spec calls reconcile_inbound_persona_event via
invokeTauri, but the mock bridge had no case for it — hitting the
default unsupported-command error path and failing both tests.

Add a no-op case that returns undefined, matching the real Tauri
command's Ok(()) return type. The mock doesn't need to parse the event
or update the store; the spec only needs the call to not throw.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96 wpfleger96 force-pushed the duncan/persona-sync-live-refresh branch from c0b2988 to b19ef05 Compare June 25, 2026 18:00
@wpfleger96 wpfleger96 merged commit 9a59e30 into main Jun 25, 2026
24 checks passed
@wpfleger96 wpfleger96 deleted the duncan/persona-sync-live-refresh branch June 25, 2026 18:10
tellaho pushed a commit that referenced this pull request Jun 25, 2026
…ebar

* origin/main:
  fix(sidebar): non-selectable channel names + copy/leave context menu actions (#1260)
  fix(runtime): sweep node wrapper processes hosting managed agent shims (#1296)
  fix(buzz-agent): follow symlinks when discovering skill directories (#1295)
  chore: add grab-emoji.sh to register Slack emoji in Buzz (#1292)
  Fix cross-pod membership notification fanout (#1291)
  fix(buzz-acp): strengthen agent communication rules in base prompt (#1293)
  chore(release): release Buzz Desktop version 0.3.34 (#1289)
  feat(desktop): refresh Agents tab live on inbound relay sync (#1256)
  fix(buzz-acp): inject Codex network allowlist for relay hostname at spawn time (#1287)

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

# Conflicts:
#	desktop/src-tauri/src/commands/agent_models.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant