Commit Graph

43 Commits

Author SHA1 Message Date
Logan Johnson
d5a73b9f35 fix(desktop): derive agent availability from relay presence (#7127)
🤖

## Requested rebase published — ef40744b

Rebased onto fetched main **47d068e2109d077414cbf2f4f1c927f6d051037a**,
published **ef40744b3aeb4baaf8c81416e1a644fb5b315f91** with the exact
expected-old `df7fad6a` force-with-lease. No merge.

Manual conflicts were additive: preserve main's exact-key identity
documentation alongside the availability contract, and retain both
Bestie props and the shared availability reader in
`UnifiedAgentsSection`. Range-diff confirms unchanged lifecycle policy:
exact-key action-time authority, Unknown versus Offline, rejected
shutdown retains record/memberships, and separate local/provider/owner
gates. Main's exact-key profile routing survives. Both test-only CI
synchronization repairs (natural toast expiry and bounded stderr wait)
are byte-identical to the prior head. All ten original
authors/messages/DCO/material coauthor trailers are preserved;
configured signing policy was not changed.

Fresh checks on the rebased candidate:
- TypeScript, Biome on 26 changed TypeScript files, differential
file-size gate, and diff whitespace: pass.
- Focused production-hook/card/profile units: **58/58**.
- Fresh E2E build, availability/deletion browser: **11/11**, no retries.
- Main exact-key profile cases plus failed-DM send/startup retries:
**6/6**, no retries.

Previously reviewed full Desktop/buzz-agent package and mutation
evidence is reused for unchanged behavior; no ceremonial full suite, new
native/provider test, or `just ci` pass is claimed. Local configs,
dependency links, and historical artifacts are preserved.

Hosted observation: **MERGEABLE**, **BLOCKED / REVIEW_REQUIRED**, no
new-head formal review. [CI
33699735990](https://github.com/block/buzz/actions/runs/33699735990) is
running (including Rust and Desktop lanes), not a completed success. DCO
and required Security aggregate passed at the observation; the separate
Codex advisory review was skipped. No completed failing check or new
inline feedback observed. Historical approvals are not new-head
approvals. No reviewer/security authorization or merge action was
performed.

---

## Feature summary and retained pre-rebase evidence

## Summary

In Buzz Desktop, an agent could look online just because it had been
started or deployed, even when there was no current sign it was
connected. Cards and profiles now show availability from the agent's
relay presence rather than a saved launch record, so you can distinguish
an online agent from one that was merely deployed.

Agents cards and profiles use presence reported through the shared
server (the relay). A successful presence read with no online agent
shows Offline; failed/disconnected evidence shows unknown, rather than
retaining a misleading cached Online state.

Lifecycle actions remain separate. An offline agent may still have a
Shutdown action because the deployment record exists. Shutdown reports a
**request**, not proof the process stopped. Offline does not imply that
starting a duplicate agent is safe, and Online does not promise a
response.

### Related issue

Independent base: `main`; no stack parent or child among the
replacements. Extracted from
[#7114](https://github.com/block/buzz/pull/7114), retained as historical
source (`98fe33ec`).

[Behavior
contract](f4bb2ed44e/docs/agent-availability.md).
Originating [Buzz
discussion](buzz://message?channel=f7a9536a-1738-4bad-a888-b3ea25010ef1&id=7aa1f0ab23dce514bd8a0221441cf005bf428914621171472b79747c50820848)
· channel `f7a9536a-1738-4bad-a888-b3ea25010ef1`.

### Testing

The same saved provider-backed agent, with only authored presence
changing. These are mock-browser states, not a before/after deployment
or live relay transport test; production UI is unchanged by the later
fixture repairs.

**No online presence:** gray dot, existing Shutdown control retained.

![Offline presence does not remove the deployment lifecycle
control](https://raw.githubusercontent.com/block/buzz/ed68b1b4597dde47118b7591b1e8ebf3702447ca/pr-7127--offline-deployment.png)

**Online presence:** green dot, same lifecycle control.

![Authored Online presence changes availability without changing the
deployment](https://raw.githubusercontent.com/block/buzz/ed68b1b4597dde47118b7591b1e8ebf3702447ca/pr-7127--online-deployment.png)

[Capture
details](https://github.com/block/buzz/pull/7127#issuecomment-5482264824).
To check manually, compare runtime-only transitions with presence
updates, then disconnect/fail the presence read and verify it does not
stay Online. A Shutdown request should not immediately claim confirmed
termination.

#### Historical pre-rebase evidence and limitations (df7fad6a)

Lifecycle production source remains
**`f4bb2ed44e5a989d93c5f51e93c0bbd2dca941be`**. Current published head
is **`df7fad6ae65dda78508317186a95522d1bb22ed9`**: the prior browser
synchronization at `b78d093e` plus an additive two-file Rust
test-harness synchronization described below. No production bytes,
dependency/configuration files, or prior commits were changed; no
rebase. Current live main `0dbd036f5bff33e7ade75e7639f3218d424a6e73` has
identical failing-test/toaster/send-flow source; the causal browser
comparison used latest successfully tested main
`04babf02655440b4dfd37f2e2df605ead0a030d8`.

**Lifecycle/deletion correction:** both Agents and actual profile
deletion now pass the shared exact-key availability reader, not raw
cached data. It reads the canonical query state and connection at action
time, including after awaited channel discovery.
Failed/disconnected/pending evidence and unqueried persona siblings are
unknown; successful missing means Offline only for a requested key.
Successful background refetch cache remains usable; settled failure
revokes it. No second cache or per-row polling was added.

Provider record + channel + Online/Away/**unknown** awaits shutdown
submission before local removal; rejection preserves record/membership
for retry. Established Offline preserves intentional no-request removal.
No route preserves warned local removal. Local agents retain native
stop-before-remove, independent of presence. Profile consent now
describes a shutdown **request**, not remote deletion or guaranteed
termination. Existing ownership and force gates are unchanged.

**Verified, reused exact-candidate validation:** the independently
approved eleven-file patch (SHA-256
`2f69fe12ef0420e62dea1fd8db28cfa22cde5eecaf8080e656310a3e60d0cf86`) was
committed without byte changes. Desktop **5,921 passed, 0
failed/skipped**, including **26 new mounted production hook/IPC
regressions**; rebuilt availability browser suite **11/11 passed, no
retries**, including four actual profile Delete journeys. Desktop check
(existing 4 warnings/5 infos), typecheck, production/protected-feature
artifact matrix, differential file-size/policy and diff checks passed.
No blanket rerun or new full-repository `just ci` is claimed for this
frontend correction.

Production regressions cover cached Online **and Offline**
failure/disconnection, genuine missing/Offline, pending, successful
inflight refetch versus settled error, retained reader, error during
awaited channel discovery, unqueried persona sibling, shutdown
rejection/order/cancel, no route and local authority. Browser fixtures
use safe mock IPC and a retained provider receipt, not a real
deployment. Three restored mutation controls fail: unknown → skip
shutdown (**15** regressions), Agents raw-cache reader (**6**), actual
profile raw-cache caller (**1 browser journey**, false removal on failed
cached Offline). Independent review approved the exact frozen bytes and
added **4/4 cached-empty failure/disconnection probes** across both
callers. This is local independent approval, not formal GitHub/A Team
clearance.

The prior native propagation/poll-count defects remain closed ([earlier
response](https://github.com/block/buzz/pull/7127#issuecomment-5512278755)).
The prior hover-popover correction at `b55423f6` remains covered by the
full 11-journey browser run: pending/failed/disconnected means no badge
or accessible status, genuine missing/Offline retains an Offline badge.
Its earlier fallback-restoration mutation failed as expected (badge
count 1 rather than 0); that historical witness is reused, not rerun.

**Reused unchanged native/system boundary:** local `just ci` at
`c59067d8` passed workspace/Tauri fmt/clippy, static/policy checks, Rust
unit recipe, native workspace **3,159 passed / 20 ignored**, Web build
and **2,019 mobile tests**. No native implementation changed in this
lifecycle correction. These are historical boundary results, not
new-head native/live certification. [Parent
CI](https://github.com/block/buzz/actions/runs/33650549130) passed with
**14 retry-recovered browser flakes**, not retry-free. Old-head
CI/reviews are not current-head clearance.

**Hosted gates:**
[CI33662151103](https://github.com/block/buzz/actions/runs/33662151103)
on `f4bb2ed4` **FAILED**: smoke shard1 had 322 pass, one failure, one
retry-recovered flaky, two skipped. The failed first-DM retry test timed
out on all three attempts because the error toast intercepted Send. That
failure is preserved, not waived; the scoped test repair below is
published as `b78d093e`.
[CI33668171165](https://github.com/block/buzz/actions/runs/33668171165)
on `b78d093e` subsequently **FAILED** the Rust unit budget regression
described below. Both original failures remain visible; neither was
retried to green. Exact `f4bb2ed4` and `b78d093e` APPROVED reviews cover
unchanged reviewed bytes, not formal approval of the new head. Fresh
exact-head CI and the established automated technical rereview are the
next gates for `df7fad6a`. Historical deletion responses remain
([5092381800](https://github.com/block/buzz/pull/7127#issuecomment-5513759316),
[5092391193](https://github.com/block/buzz/pull/7127#issuecomment-5513763497)).
No formal review dismissed. The [security
notice](https://github.com/block/buzz/pull/7127#issuecomment-5482231278)
and latest-push maintainer/codeowner policy remain separate actionable
gates: eligible Block organization members own current-range
authorization. No merge/security authority exercised.

**CI causal repair (`b78d093e`, test only):** the error `Message failed
to send: Mock first DM send failed.` is deliberately injected by the
existing fixture. CI screenshot and retry trace show the bottom-right
Sonner notification over the actual enabled Send button. `fill()` leaves
the pointer parked there; Sonner pauses its 4-second lifetime while
hovered. A fast run can click before animation settles (unchanged local
test passed in 2.7s; two actual tested-main CI cases passed first
attempt in 3.3s), which does not disprove the failure. Independent
controlled browser runs on `f4bb2ed4` and tested main `04babf` both
reproduced the same toast hit-test at Send `(1203,627,32,32)`,
persistent hover beyond 4s, and intercepted ordinary click with no
second send. Moving the real pointer to the editor allows natural expiry
and successful ordinary retry, preserving all original
DM-channel/recipient assertions. This same synchronization already
exists in the neighboring agent-startup-failure test.

The one-file correction keeps the visible error assertion, scopes its
toast locator, moves the pointer back to the editor and observes normal
toast removal (bounded 10s) before retry. No forced click, direct toast
dismissal, mocked clock, CSS override, skipped test, production behavior
change, or new backend mock. Six focused browser executions pass
(first-send/startup-failure, three repeats each, no retries); the
held-toast control fails on original bytes at the Send click while the
exact repaired test passes. Biome and diff checks pass. Reuse unchanged
5,921 Desktop / 11 availability browser / four independent probes above;
no semantic production change warrants repeating those suites. Original
failed CI attempt/retries, local fast pass, deliberate failing control
and all traces remain in `WORK_LOGS/AVAILABILITY_CI_B9210A40`. Browser
evidence is mock-IPC Chromium, not native/live-relay certification. The
UI still temporarily overlays Send while a notification is hovered; the
test exercises its real move-away/expiry recovery, not immediate
click-through.

**Rust CI causal repair (`df7fad6a`, test only):** [original Rust / Unit
Tests failure,
job100375291370](https://github.com/block/buzz/actions/runs/33668171165/job/100375291370)
tested GitHub merge `223dee91a396d8cb4ebf18b9b8559e5a54951235`.
`context_recovery_budget_exhaustion_surfaces_the_error` failed at
`regressions.rs:2756` in **0.091s** because its immediate stderr
snapshot lacked `context recovery budget spent`. ACP context-error
assertions had already passed. The captured prefix shows all three
budgets **32768 → 16384 → 8192 bytes**, above the 4096-byte floor, and
ends during the third attempt. This is **not evidence of floor
exhaustion**. The collector is an independent Tokio task; a stdout
response is not a stderr barrier. Recovery, harness and test blobs were
identical across the compared base/head/merge parents; no production
regression was implicated.

The shared test Harness now provides a bounded event/condition wait,
registering for collector notifications before reading the buffer to
avoid lost wakeups. The budget and adjacent terminal floor assertions
wait for their own diagnostic and retain the matching snapshot. The
budget test still requires the provider's ACP context error and exactly
three recovery rungs, now corroborated by **exactly four provider
calls** and no floor diagnostic. Timeout remains a real failure with
captured stderr. No fixed sleep, weaker assertion, skip,
provider-limit/logging change, dependency/config edit, or production
change.

**Deterministic causal control:** the same real agent/HTTP-provider/ACP
scenario holds only stderr collection behind a one-shot gate until after
stdout responds. The old immediate snapshot fails the original budget
assertion (intentional exit101); the repaired wait explicitly remains
Pending while held, then passes after release. No scheduler-speed
assumption or fixed sleep. This reproduces the observation race under
controlled delay, **not the exact historical CI schedule**. A
missing-diagnostic test proves the wait actually times out. Original
failure and deliberate failing-control logs/patch remain in
`WORK_LOGS/RUST_TRIAGE_06E32D2D` and `WORK_LOGS/RUST_SYNC_BC5758B9`.

**Final candidate validation:** focused recovery **9/9**, floor **1/1**,
absent-diagnostic timeout **1/1** pass. One full touched-package run,
`cargo test --locked -p buzz-agent`: **695 passed, 0 failed, 1 existing
ignored**, including all **54 regressions**. Local nextest was
unavailable, so this uses the repository-supported cargo-test fallback,
not a claim of nextest reproduction. `cargo fmt --check`, package-scoped
Clippy all-targets with `-D warnings`, differential file-size/policy and
diff checks pass. Previously reviewed availability production and the
Desktop/browser evidence above are unchanged and reused; no all-native
blanket rerun. The test-only delta was self-reviewed against collector
ordering, timeout and falsification evidence. Existing production
approval remains valid for those bytes; exact-new-head technical/CI
clearance is not assumed. The required **Security aggregate** is
distinct from optional Codex advisory feedback; no security
authorization, human review contact, or merge was requested.

**Remaining policy limits:** shutdown submission is not harness
acceptance or process termination; confirmed Offline/no-route local
removal may leave a remote process; route discovery is best effort,
membership cleanup uses `Promise.allSettled`, and multi-instance
deletion is sequential/non-atomic. No distributed singleton,
provider-health, tenant-switch cancellation, live relay TTL or packaged
WebView/VoiceOver certification is claimed. The pre-existing DM-header
raw-presence fallback (`ChannelScreenHeader`/`useActiveChannelHeader`)
remains outside this repair and uncertified. Screenshots above remain
historical mock-browser illustrations, not new deletion or native
transport evidence.

---------

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
2026-09-02 21:53:15 -04:00
Kalvin C
0affe527e8 fix(model-capabilities): humanize databricks goose model names (#7135)
🤖
## Summary
- add curated human-readable labels for Databricks Goose models that
otherwise render as fully qualified identifiers
- render `data_workflow_tools.goose.goose-glm-5-3` as `GLM-5.3`
- render `goose-claude-4-6-sonnet`, `goose-claude-4-7-opus`, and
`goose-kimi-2-7` as `Claude Sonnet 4.6`, `Claude Opus 4.7`, and `Kimi
2.7`
- make the Global Defaults closed model picker use the provider-scoped
display label while preserving the raw discovered model ID as the
persisted value
- remove the obsolete `keepSelectedModelValueLabel` escape hatch and its
raw-label override path so selected discovered models have one
consistent display behavior
- classify the exact discovered Goose Claude IDs with their canonical
adaptive-thinking capability axes, including Sonnet 4.6's exclusion of
`xhigh`
- expand Rust and TypeScript alias coverage and regenerate the shared
139-vector capability corpus

## Test plan
- `cargo test -p buzz-agent --lib` — 517 passed, 1 ignored
- `cd desktop && pnpm test` — 5,821 passed
- Desktop TypeScript typecheck — passed
- Biome on the changed component — passed
- `git diff --check` — passed
- targeted Playwright Global Defaults regression — passed on the
preceding implementation head; the subsequent commit only removes dead
picker-prop plumbing

Verified at `b9609d12696173aa309d2dbaf4f093a502756c36`. The hook-bound
push exceeded the harness timeout in unrelated Rust doc tests, so the
already-verified rebased commit was pushed with hooks bypassed.

Follow-up to #6955.

---------

Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Co-authored-by: am <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
2026-08-31 17:13:59 -07:00
tulsi
cb3144999b add public descriptions to agent personas (#7126)
**Category:** new-feature
**User Impact:** People can add a short public description to an agent
and see what it does directly on agent cards and profiles.

**Problem:** Agent cards previously showed only a model label, so people
had to open an agent and inspect its instructions to understand its
purpose. Public metadata also needed one trustworthy lifecycle across
local edits, relay catalogs, profiles, and portable snapshots.

**Solution:** Add an optional owner-authored description with a
280-character visible-text policy, publish it as profile `about`, and
prefer it on agent cards while retaining the model fallback. Description
metadata is excluded from the spawn-content hash, remains
definition-owned, and is validated independently at every untrusted or
persistence boundary.

<details>
<summary>File changes</summary>

**desktop/src-tauri/src/commands/agent_config_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/agent_discovery/relay_directory.rs**
Updates relay-directory profile test publication for the expanded
profile contract.

**desktop/src-tauri/src/commands/agent_models_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/agent_models_update.rs**
Preserves the effective `about` value when instance edits republish a
complete profile event.

**desktop/src-tauri/src/commands/agents.rs**
Carries the effective authored description into initial managed-agent
profile publication.

**desktop/src-tauri/src/commands/agents_profile.rs**
Adds `about` to profile reconciliation and keeps description, name, and
avatar synchronized against relay state.

**desktop/src-tauri/src/commands/agents_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/card.rs**
Materializes the definition-owned description before minting a portable
agent card snapshot.

**desktop/src-tauri/src/commands/personas/create.rs**
Normalizes and validates raw authored descriptions before persona
persistence.

**desktop/src-tauri/src/commands/personas/delete_cascade_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/inbound.rs**
Validates descriptions at inbound relay ingress and applies accepted
values to local definitions.


**desktop/src-tauri/src/commands/personas/inbound/catalog_reconcile_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/inbound/inbound_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/mod.rs**
Centralizes raw-byte validation followed by trim/empty normalization for
description writes.

**desktop/src-tauri/src/commands/personas/pending.rs**
Revalidates descriptions before preparing public persona publications.

**desktop/src-tauri/src/commands/personas/sharing.rs**
Carries the optional public description through this managed-agent
compatibility path.

**desktop/src-tauri/src/commands/personas/snapshot.rs**
Materializes definition-owned descriptions into portable instance
snapshots without creating a second persisted authority.

**desktop/src-tauri/src/commands/personas/snapshot/fidelity_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/snapshot/import.rs**
Restores snapshot descriptions onto imported definitions while keeping
linked instance copies absent.

**desktop/src-tauri/src/commands/personas/snapshot/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/personas/update.rs**
Persists persona description edits, republishes linked profiles, and
preserves legacy avatars during complete kind:0 replacements.


**desktop/src-tauri/src/commands/personas/update/name_propagation_tests.rs**
Proves description-only profile sync does not write instance state or
clear a legacy avatar.

**desktop/src-tauri/src/commands/team_snapshot.rs**
Round-trips member descriptions through team snapshots and imported
definitions.

**desktop/src-tauri/src/commands/team_snapshot/tests.rs**
Covers team member description export and import fidelity.

**desktop/src-tauri/src/commands/teams/adopt/apply.rs**
Starts adopted team catalog members without synthesizing an unauthored
description.

**desktop/src-tauri/src/commands/teams/adopt/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/teams/pending/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/commands/teams/sharing/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/egress_guard_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/event_sync_team_catalog_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/agent_description.rs**
Defines the canonical Rust description resolution used by profile
publication and reconciliation.

**desktop/src-tauri/src/managed_agents/agent_events.rs**
Updates managed-agent record construction for the optional public
description field.

**desktop/src-tauri/src/managed_agents/agent_snapshot.rs**
Includes descriptions as snapshot profile `about` metadata and validates
them at decode ingress.

**desktop/src-tauri/src/managed_agents/agent_snapshot_envelope.rs**
Updates managed-agent record construction for the optional public
description field.

**desktop/src-tauri/src/managed_agents/agent_snapshot_tests.rs**
Covers snapshot description export and rejection of unsafe or overlong
imported metadata.

**desktop/src-tauri/src/managed_agents/config_bridge/reader_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/definition_validation.rs**
Adds the shared 280-character visible-text policy for public
descriptions.

**desktop/src-tauri/src/managed_agents/discovery/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/effective_config/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/global_config/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/mod.rs**
Exports the description resolution and validation helpers to
managed-agent consumers.

**desktop/src-tauri/src/managed_agents/nest/render_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/parallelism.rs**
Updates managed-agent fixtures for the optional description field
without changing runtime configuration behavior.

**desktop/src-tauri/src/managed_agents/persona_events.rs**
Adds description to persona event content while deliberately excluding
it from the spawn-relevant content hash.

**desktop/src-tauri/src/managed_agents/persona_events/tests.rs**
Pins description event round-tripping and proves description-only edits
do not change the restart hash.

**desktop/src-tauri/src/managed_agents/personas.rs**
Initializes built-in persona records without authored descriptions for
backward-compatible defaults.

**desktop/src-tauri/src/managed_agents/personas/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/readiness.rs**
Updates managed-agent fixtures for the optional description field
without changing runtime configuration behavior.

**desktop/src-tauri/src/managed_agents/restore.rs**
Includes the effective description in launch-time profile
reconciliation.

**desktop/src-tauri/src/managed_agents/runtime/test_fixtures.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/runtime/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/spawn_snapshot/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/team_catalog/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/team_snapshot.rs**
Updates managed-agent record construction for the optional public
description field.

**desktop/src-tauri/src/managed_agents/teams_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/managed_agents/types.rs**
Adds optional description metadata to persona and managed-agent records
and their compatibility projections.

**desktop/src-tauri/src/managed_agents/types/requests.rs**
Accepts optional descriptions on persona create and update IPC requests.

**desktop/src-tauri/src/managed_agents/types/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/migration_avatar_tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src-tauri/src/persona_catalog.rs**
Parses and validates descriptions at the untrusted community-catalog
boundary.

**desktop/src-tauri/src/persona_catalog_tests.rs**
Covers valid catalog descriptions plus rejection of malformed,
invisible, and overlong values.

**desktop/src-tauri/src/relay.rs**
Publishes and queries kind:0 `about` so relay profiles preserve authored
descriptions.

**desktop/src-tauri/src/relay/tests.rs**
Updates managed-agent/persona fixtures for the optional description
field while preserving the behavior under test.

**desktop/src/features/agents/AGENTS.md**
Documents description ownership, validation, snapshot, hashing, and
display invariants for future changes.

**desktop/src/features/agents/lib/agentDescription.test.mjs**
Pins Unicode counting, paste clamping, trimming, and empty
authored-description behavior.

**desktop/src/features/agents/lib/agentDescription.ts**
Provides shared display resolution, Unicode-scalar counting, and paste
clamping for descriptions.

**desktop/src/features/agents/lib/personaCatalogRelay.ts**
Maps validated catalog descriptions into catalog persona projections.

**desktop/src/features/agents/ui/AgentDefinitionDialog.tsx**
Adds the description draft to create and edit submission while
extracting identity fields from the large dialog.

**desktop/src/features/agents/ui/AgentDescriptionField.tsx**
Renders the public description input, helper copy, and Unicode-aware
near-limit counter.

**desktop/src/features/agents/ui/AgentIdentityCard.tsx**
Generalizes the card second line to show a two-line description or the
existing model fallback.

**desktop/src/features/agents/ui/UnifiedAgentsSection.tsx**
Prefers authored descriptions on persona cards and retains model labels
when no description exists.

**desktop/src/features/agents/ui/personaDialogState.test.mjs**
Verifies edit and duplicate drafts preserve authored descriptions.

**desktop/src/features/agents/ui/personaDialogState.ts**
Seeds authored descriptions into edit and duplicate dialog drafts.

**desktop/src/features/agents/ui/usePersonaActions.ts**
Preserves descriptions when copying catalog personas into local
definitions.

**desktop/src/shared/api/personaTypes.ts**
Defines description-bearing persona wire types in a focused module split
from the size-constrained API type file.

**desktop/src/shared/api/tauriPersonas.test.mjs**
Verifies raw persona descriptions map into the frontend model and absent
values become null.

**desktop/src/shared/api/tauriPersonas.ts**
Maps description fields across Tauri and preserves raw authored bytes
for authoritative Rust validation.

**desktop/src/shared/api/types.ts**
Re-exports the extracted persona types without changing consumer import
paths.

**desktop/src/testing/e2eBridge.ts**
Extends mock persona create, update, publication, and catalog parsing
with production-shaped description behavior.

**desktop/tests/e2e/agents.spec.ts**
Verifies an edited description persists and appears on the agent card.

</details>

### Reproduction Steps

1. Open **Agents**, edit a custom or built-in agent, and enter a
sentence in **Description**.
2. Save the agent and confirm the sentence appears as the second line on
its card.
3. Reopen the agent and confirm the authored description is restored;
clear it and confirm the card returns to the model label.
4. Paste more than 280 Unicode characters and confirm the field keeps
the first 280 characters and shows the near-limit counter.
5. Share or export/import the agent and confirm the description survives
in the catalog/profile or snapshot without showing a restart-required
badge for a description-only edit.

### Screenshots / Demo

The focused Playwright flow `built-in persona edits persist` exercises
the edited dialog, persisted value, and resulting card subtitle.
Screenshots can be added after review if the field placement or two-line
card treatment needs visual iteration.

### Verification

- `cargo test --manifest-path desktop/src-tauri/Cargo.toml --lib` —
3,029 passed
- `cd desktop && pnpm test` — 5,805 passed
- `cd desktop && pnpm exec tsc --noEmit`
- Focused Playwright: `built-in persona edits persist` — passed
- Pre-push desktop, Tauri, typecheck, test, file-size, and branch-skew
gates — passed

---------

Signed-off-by: tulsi <tulsi@block.xyz>
2026-08-31 17:12:52 -04:00
Arjun Mahanti
bc006f6708 feat: render agent avatars as squircles (#7106)
## Summary

- render every agent/AI identity as a 30% squircle across desktop and
mobile while keeping human avatars circular
- propagate agent identity through message, thread, profile, reaction,
member, DM, search, workflow, project, huddle, forum, pulse, and
agent-management surfaces
- preserve squircle geometry for fallbacks, focus/status treatments,
add-agent controls, and overlapping avatar outlines (`calc(30% + 2px)`
for the outer background)

### Related issue

None found. This change was requested and visually reviewed in the
originating Buzz thread.

### Testing

- `just desktop-test` — 5,799 passed
- `just mobile-test` — 2,008 passed
- pre-push gates passed at `0d59d77b120dcb90aac2f918e422c11c9fa5353b`:
desktop check, TypeScript typecheck, desktop full test suite, mobile
format/analyze and full test suite, Rust tests, Tauri checks, and
differential file-size gate
- deterministic desktop visual sweep covered channel messages/thread
summaries; thread, subthread, and sub-subthread depths; reactions and
reactor popovers; hover/full profiles; added-to-channel activity;
channel members/settings; agent library/team overlaps; agent creation;
mention autocomplete; and DM header/sidebar/settings

### UI evidence

The complete labeled visual matrix is available in the originating Buzz
review thread. GitHub-hosted copies will be added in a follow-up PR
comment using the repository screenshot script.

---------

Signed-off-by: Fizz <dae5f6af70b8695a8b83c8deae555f63be41630ec2b8cd493e41a439c9527dd8@buzz.block.builderlab.xyz>
Co-authored-by: Fizz <dae5f6af70b8695a8b83c8deae555f63be41630ec2b8cd493e41a439c9527dd8@buzz.block.builderlab.xyz>
2026-08-31 13:31:33 -04:00
Will Pfleger
2f66ee24a0 feat(desktop): add team sharing to community catalog (#3995)
Stack: [#5112](https://github.com/block/buzz/pull/5112) → this PR

Stacks on the team catalog backend PR (#5112). Contains the `desktop/**`
changes that turn the add-agent surface into a single Community Catalog
browsing both shared agents and shared teams.

## Owner catalog sync pipeline

`usePersonaSync.ts` gains a hydration pipeline in `startPersonaSync` so
a fresh device that comes online after another already published the
owner's 30178 catalog head reconstructs the complete state without
falsely retracting it. The owner's
persona/team/managed-agent/30178/deletion history is backfilled up front
(a live-only subscription gets no history — reconnect-replay's
since-cursor is undefined until the first live event), then a live
subscription takes over.

Four properties keep a fresh sync from purging the owner's valid shared
head:

- **Paged backfill with a safe termination guarantee.** The relay serves
each REQ newest-first and clamps `limit` to its advertised `max_limit`,
so a large owner's history overflows one page — a newer 30178/30176
could return in-page while an older required 30175 constituent falls
beyond it. `fetchOwnerHistoryToExhaustion` pages the full window with
the `until` time cursor (the only cursor the WS REQ filter exposes; the
DB `before_id` keyset is REST-only), deduping the inclusive-boundary
rows. A short page terminates normally. A full page whose oldest event
cannot advance the time-only cursor is a **dense boundary** — more than
one page of events share one `created_at` second, which the WS filter
has no `(created_at, id)` cursor to escape — and raises
`PersonaHistoryDenseBoundaryError` rather than silently completing as if
the history were exhausted and dropping the older constituents behind
it.
- **Constituents-before-catalog ordering.** Over the complete batch,
`orderCatalogHeadsLast` stably defers every 30178 head past its
30175/30176 constituents. Reconciling a 30178 head before its personas
hydrate makes the inbound team refresh fail member resolution and queue
a dominating false tombstone; deferring the heads guarantees the
constituents are all applied first, while newest-wins order within every
other coordinate is untouched.
- **Hydration boundary for concurrent live events.** The backfill fetch
and the live subscription start concurrently into one reconcile chain. A
live or replayed 30178 that arrives before the backfill reconciles its
constituents would reproduce the same false-tombstone purge, so live
events are buffered until the ordered backfill is dispatched and then
drained in arrival order. Steady-state live events (after hydration
completes) reconcile immediately.
- **Explicit backfill failure policy.** A transient history-fetch
rejection is retried with bounded backoff. When backfill cannot complete
— retries exhausted, or a deterministic dense boundary — the pipeline
enters a **degraded-live** state rather than leaving the subscription
permanently inert with live events accumulating in the buffer: the
hydration boundary still opens so buffered and future live events keep
reconciling, but the whole catalog dependency set is dropped — the 30178
head, its 30175/30176 constituents, and any kind-5 deletion carrying a
dependency-targeting `a` tag (classified by scanning *all* `a` tags,
matching the backend's deletion router, which `find_map`s across every
tag and routes the first signer-owned coordinate — so a malformed or
foreign first `a` tag ahead of an owned 30176 cannot slip a destructive
deletion through) — because backfill never fully hydrated the owner's
constituents. Dropping only the 30178 head is not enough: the backend
refreshes the catalog head after every team/persona save, and live
delivery is newest-first, so a 30176 edit that adds a *new* member would
reach the backend before that member's 30175 and falsely tombstone a
witness-holding device's valid team. Holding the prior hydrated run's
constituents on disk only proves the *old* revision is resolvable — it
says nothing about a new member — which is why the entire dependency set
is held rather than just the head. 30177 managed-agent runtime policy
stays live (it drives no catalog refresh). A degraded device stays stale
on team/persona edits until it self-heals on the next effect re-run
(restart, or an identity/community switch) — the correct trade against
destroying valid shared state.

## Data layer

Relay paging, signature verification, NIP-33 head selection, and
untrusted-content parsing for the kind `30178` team catalog live
natively in the `fetch_team_catalog` Tauri command (`team_catalog.rs`),
structurally mirroring `fetch_persona_catalog` (`persona_catalog.rs`). A
catalog refresh crosses IPC once and never verifies a signature on the
webview thread. `teamCatalogRelay.ts` is now a thin presentation and
local-linkage layer over the verified projection — it shapes entries for
display and links each to a local team, and never parses or verifies.

Parsing is all-or-nothing, identical to the add-time re-fetch in
`add_team_from_catalog`: a team with any invalid member fails to parse
and the publication is dropped from the catalog, matching persona
behavior. **Behavior delta:** the previously reviewed partial-render of
invalid-member teams — a warning banner on an entry that could never be
added — is removed. Invalid publications are dropped entirely rather
than surfaced as un-addable.

## Hooks

`useTeamCatalogRelay.ts` mirrors the persona catalog hook: a
community-keyed query over `fetch_team_catalog`, live invalidation on
kind `30178`, share/unshare, and add-from-catalog (which invalidates
both the teams and personas stores, since adopting a team copies its
members as local personas).

## CommunityCatalogDialog

Single unified surface replacing the former separate dialogs. Agents and
Teams appear as labeled sections with type-tagged selection and a
teams-preferred launch. `TeamsSection`'s discover entry and the
new-agent card both open this one dialog. `PersonaCatalogDialog.tsx` is
removed; persona browsing now lives inside the unified dialog.

## TeamShareDialog

Publishes and unshares team catalog entries via `set_team_shared`.

## e2e + screenshots

`team-catalog.spec.ts` covers the browse + adopt flow;
`team-catalog-screenshots.spec.ts` produces the pixel-regression set.
`e2eBridge.ts` gains `mockTeamCatalogPublications`, which mirrors the
native command's head selection and shared gate and performs only a
shallow `v`/`name`/`members`-array shape check; per-member validation
stays in the Rust command.

## Follow-ups

None. The shared agent-definition text-safety policy
(Unicode-control/bidi/zero-width rejection) already covers the team
surface: #5112's `validate_team_catalog_content` chokepoint gates every
field delivered verbatim to the harness on both the publish and adopt
paths, and this PR's parse layer consumes that verified projection
rather than re-validating on the webview thread.

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-08-28 14:51:25 -04:00
klopez4212
7e2651791d Add font size and conversation density preferences (#5644)
## Summary

- Add separate **Font size** and **Conversation density** controls in
Appearance.
- Use a 13 / 14 / 15px conversation text ramp for Smaller / Default /
Larger while scaling interface typography through a shared virtual-rem
system.
- Keep layout geometry fixed while typography changes, and compose Cmd
+/- text zoom on top of the selected preference.
- Let Compact, Comfy, and Spacious control conversation row spacing plus
paragraph and list rhythm in Markdown content across Buzz.
- Preview font size and density together with click-and-drag comparison;
interrupted scrubbing restores the saved preference.
- Synchronize preferences across open Buzz windows, including full
local-storage clears during sign-out or dev reset.
- Promote the segmented control to shared UI and make Settings rows
adapt to their card width.

## Validation

- `just ci`
- 4,965+ desktop unit tests across the final merged branch
- 1,465 mobile tests through the full repository gate
- Focused Playwright coverage for font-size/density independence, drag
preview cancellation, Inbox geometry, thread rendering, keyboard zoom,
and cross-surface typography
- Fresh E2E build against the final merged branch

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: morgmart <98432065+morgmart@users.noreply.github.com>
2026-08-18 15:24:09 -07:00
Will Pfleger
e2ade93f02 fix(desktop): downscale large avatars for agent-share PNG body (#6260)
Sharing an agent encodes a `.agent.png` snapshot with the avatar as the
PNG image body. Non-PNG avatars were transcoded at full resolution and
already-PNG avatars were carried through unchanged, so a large source
avatar could produce a PNG that exceeds the 10 MiB
`MAX_SNAPSHOT_PNG_BYTES` cap and fail the send. A 2764×4096 webp avatar
encoded to ~26 MB — over 2.5× the ceiling — which is why sharing that
agent hung for a few seconds (fetching and transcoding the image) and
then failed.

The share dialog compounded the problem: on failure it discarded the
pipeline's real error (`Snapshot exceeds the 10 MiB size limit…`) and
toasted a generic `Couldn't send … Try again.`, hiding the actual cause.

## Changes

- **Downscale the avatar for the snapshot PNG body.** The body is only a
card thumbnail, so raster avatars are now downscaled to a 512px longest
edge (`MAX_PNG_BODY_EDGE`) before PNG re-encoding, mirroring the
frontend SVG rasterizer's 512×512 cap in `snapshotAvatarPng.ts`.
Already-PNG avatars over the dimension cap route through the same
downscaling transcode path instead of a straight tEXt-chunk injection.
The manifest's `avatar_url`/`avatar_data_url` source reference is
untouched — only the PNG image body is downscaled.
- **Surface the real error in the share dialog.** `PersonaShareDialog`
(used by `SnapshotShareDialog`/`TeamShareDialog`) and
`AgentCardViewerDialog` now toast the send controller's actual error
message, falling back to the generic string only when it is empty. A
`getCurrentError()` accessor reads the error through a ref because the
render-captured `state.error` is stale in the closure immediately after
`beginSend` resolves.

A unit test pins the invariant: an oversize (2764×4096) avatar produces
a snapshot that stays far under the cap with body dimensions clamped to
512px.

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-08-18 15:18:48 -07:00
klopez4212
076081bfc6 Rename Bumble agent to Pollen (#5864)
## Summary
- Rename the built-in Bumble agent to Pollen across desktop, onboarding,
docs, and test fixtures.
- Migrate existing stock definitions and instances in place while
preserving customized fields and the stable persona coordinate.
- Reserve the Pollen name by removing it from Fizz's generated-name
pool.

## Validation
- Pre-push desktop checks, typecheck, 4,791 frontend tests, Tauri
clippy, and 2,432 native tests
- Desktop E2E build

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-08-17 10:49:03 -07:00
klopez4212
34a7f2fb91 Unify agent profile content (#5788)
## Summary

- remove synthetic preview runtime and configuration data so profiles
show only real agent content
- simplify model settings to the effective values and restore bare
section icons
- make owned-agent profiles resolve to the same current persona instance
from every entry point

## Why

Agent profiles opened from DMs or channels could fall back to a partial
declared-owner view instead of the full managed-agent profile shown on
the Agents page. Test preview content and configuration provenance also
remained visible after the redesign.

## User impact

Owned agent profiles now expose the same actions, runtime, channels,
memories, and configuration regardless of where they are opened.
Profiles no longer synthesize preview data, and model settings use the
same simple title/value hierarchy as the rest of the panel.

## Validation

- `pnpm --dir desktop check`
- `pnpm --dir desktop build:e2e`
- focused unit tests: 10 passed
- profile entry-point integration tests: 2 passed
- configuration screenshot suite: 7 passed, with six visually distinct
captures

Snapshots are attached in a PR comment.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
2026-08-14 16:29:50 +01:00
Alex Rosenzweig
a96af89526 Harden shared agent instruction review (#4220)
## Summary

- render shared-agent instructions as literal text so Markdown cannot
conceal spoiler contents, link destinations, or image sources
- reject non-reviewable Unicode controls at every agent-definition
boundary while preserving legitimate rendered emoji sequences
- verify shared catalog event IDs and signatures before trusting
authorship, coordinates, pagination, or executable content
- preserve the exact system-prompt bytes between review and execution
instead of silently stripping or normalizing content

## Security rationale

Shared system prompts are executable configuration. Previously, catalog
prompts were projected through the chat Markdown renderer, which could
hide text, replace link destinations with benign labels, and turn image
syntax into remote loads. Zero-width and bidirectional controls could
also make reviewed text differ from what the agent executes.

This change establishes a review invariant: the prompt a user sees is
the prompt the agent executes. Definitions that cannot be reviewed
faithfully are rejected rather than rewritten. Catalog events must also
pass Nostr ID/signature verification before they can claim a publisher,
coordinate, or cursor.

## What changed

- catalog instructions render as exact literal text rather than rich
Markdown
- catalog relay events are verified on a fresh wire-shaped object before
paging, coordinate selection, attribution, or projection
- forged content, pubkeys, signatures, and invalid newer heads are
ignored and cannot shadow a valid signed definition
- TypeScript catalog parsing rejects unsafe remote definitions before
they reach the UI
- shared Rust validation covers persona create/update/import, inbound
relay sync, definition-less managed-agent sync, and catalog publication
paths
- definition-less managed agents now fail closed on local create, local
update, and publication before persistence or relay retention
- linked managed agents validate their local name while treating the
persona definition as authoritative; their inert record-level prompt is
not executed or published
- names reject layout controls; prompts retain ordinary newlines and
tabs
- legitimate emoji composition is supported, including contextual VS16,
ZWJ, skin-tone, family, flag, and keycap sequences
- detached selectors/joiners, bidirectional controls, tag characters,
zero-width concealment, and other default-ignorables remain rejected
- names are bounded to 128 characters and prompts to 64 KiB
- contributor guidance documents the byte-for-byte review requirement
for future sharing paths

Validation reports the offending code point and never silently removes
it.

## E2E recording


[buzz-shared-agent-security-e2e.webm](https://github.com/user-attachments/assets/44d6b75f-0877-490f-bda4-a716fae3f700)

The recording demonstrates:

- a safe definition remains visible
- a prompt containing zero-width `U+200B` is rejected
- a name containing bidi override `U+202E` is rejected
- the prompt is preserved exactly
- spoiler, link, and image syntax remains literal and does not render or
load

## Verification

Passed locally:

- `just test`: all 10 unit and Docker-backed integration stages
- desktop frontend unit suite: 4,295 tests
- persona catalog relay unit suite: 32 tests, including forged-event and
cursor-shadowing cases
- focused Rust definition-validation coverage: 3 local create/update
tests and 6 publication-filtered tests
- complete desktop Tauri library suite after rebase: 2,263 passed, 14
ignored, 0 failed
- desktop Tauri clippy with warnings denied and Rust formatting
- complete agent Playwright spec: 34 tests
- the exact formerly failing `inbox-edit` immediate-attachment smoke
test after rebase: 1 test
- focused shared-agent publish, literal-review, hidden-control,
signature, and cross-member import Playwright coverage
- desktop E2E production build and TypeScript typecheck
- changed-file formatting/lint and file-size ratchet
- pre-commit secret scan and DCO signoff

The branch was rebased onto current `main`, which includes the upstream
attachment-button label fix. Fresh post-rebase GitHub CI is green for
every required and selected check: Desktop Core, all four Desktop Smoke
E2E shards, both Desktop E2E Integration shards and their aggregate,
Desktop E2E Relay, Desktop Build (macOS), Windows Rust, Rust Lint, DCO,
security scanners, and Desktop Release Candidate. The previously failing
`Desktop Smoke E2E (3)` shard now passes.

The repository-wide desktop check also reports existing CSS
formatting/`!important` findings in `components.css` and `terminal.css`;
neither file is changed by this PR. GitHub's Desktop Core lint and
format stage passes on the rebased branch.

---------

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
2026-08-13 13:11:45 +10:00
klopez4212
63f961c7e4 Refine channel settings and profile panels (#5574)
## Summary

- simplify channel settings into concise detail, member, canvas, and
action sections
- align human and agent profiles around shared rows, segmented tabs, and
top-level actions
- add agent runtime presentation, sticky glass behavior, and
scroll-linked action transitions

## Snapshots

### Channel settings

![Channel
settings](https://raw.githubusercontent.com/block/buzz/72d3958374a6f31c0f15912a8307101415eed084/pr-5574--01-channel-settings.png)

### Agent info

![Agent
info](https://raw.githubusercontent.com/block/buzz/72d3958374a6f31c0f15912a8307101415eed084/pr-5574--02-agent-info.png)

### Agent runtime

![Agent
runtime](https://raw.githubusercontent.com/block/buzz/72d3958374a6f31c0f15912a8307101415eed084/pr-5574--03-agent-runtime.png)

## Validation

- `pnpm -C desktop check`
- `pnpm -C desktop test` (4,604 passed)
- `pnpm -C desktop build:e2e`
- focused channel settings and agent profile Playwright tests

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
2026-08-12 08:25:04 -07:00
Taylor Ho
02f640bc45 feat(desktop): unify add agent flows (#5015)
**Category:** improvement
**User Impact:** Users can create, discover, and import agents from one
consistent Add agent dialog.

**Problem:** Agent creation, discovery, and import were split across a
dropdown and separate dialogs, making the Add agent flow fragmented. The
existing E2E suite also continued targeting the deleted dropdown after
the flows were unified.

**Solution:** Route the new-agent card directly into a unified dialog
with dedicated Create, catalog, and Import navigation, then update the
affected E2E coverage to exercise that interface and its current empty
state.

<details>
<summary>File changes</summary>

**desktop/src/features/agents/ui/AgentDefinitionDialog.tsx**
Supports rendering the agent definition form inside the unified Add
agent experience while retaining the standalone dialog behavior.

**desktop/src/features/agents/ui/AgentDefinitionDialogShell.tsx**
Adds the shared shell used to present agent-definition content
consistently in embedded and standalone contexts.

**desktop/src/features/agents/ui/AgentDialog.tsx**
Passes the revised dialog state and close behavior through the existing
agent dialog entry point.

**desktop/src/features/agents/ui/AgentsView.tsx**
Connects the Agents page to the unified Add agent dialog and opens newly
added catalog agents in their profile panel.

**desktop/src/features/agents/ui/PersonaCatalogDialog.tsx**
Combines catalog browsing, agent creation, and snapshot import behind
persistent navigation, including dirty-navigation confirmation.

**desktop/src/features/agents/ui/UnifiedAgentsSection.tsx**
Replaces the new-agent dropdown with a direct Add agent entry point and
adjusts the responsive card grid.

**desktop/src/features/agents/ui/personaLibraryCopy.ts**
Updates catalog-facing copy for the unified experience.

**desktop/src/features/agents/ui/usePersonaActions.ts**
Returns the resolved local persona after catalog activation so the
caller can open the added agent.

**desktop/tests/e2e/agent-readiness-screenshots.spec.ts**
Opens the embedded create pane directly for readiness screenshots.

**desktop/tests/e2e/agents.spec.ts**
Covers unified Create, catalog, and Import navigation and asserts the
current shared-agent empty state.

**desktop/tests/e2e/global-agent-config-screenshots.spec.ts**
Updates global configuration screenshot setup for direct create-pane
entry.

**desktop/tests/e2e/inline-custom-harness.spec.ts**
Updates custom harness setup for the embedded create form.

**desktop/tests/e2e/persona-env-vars.spec.ts**
Updates environment-variable and model-provider scenarios for direct
create-pane entry.

**desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts**
Updates model combobox screenshot setup for direct create-pane entry.

**desktop/tests/e2e/smoke.spec.ts**
Updates agent-creation smoke coverage for the unified Add agent dialog.

**desktop/tests/e2e/where-to-run-config.spec.ts**
Updates provider-selection coverage for the embedded create form.

</details>

## Reproduction steps

1. Open the Agents page and select the new-agent card.
2. Confirm the Add agent dialog opens directly on Create without an
intermediate dropdown.
3. Use the left navigation to browse shared agents and open Import.
4. Select a catalog agent and confirm the dialog closes and the added
agent's profile panel opens.
5. Run the affected desktop Playwright smoke and integration specs and
confirm all scenarios pass.

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
2026-08-07 16:25:49 -07:00
klopez4212
6ca9641a95 Refine agent runtime controls (#5026)
## Summary
- replace ambiguous avatar play controls with centered Start and Restart
pills
- preserve avatar clipping while smoothly morphing actions into the
running status dot
- use accessible warning contrast and real restart behavior without a
duplicate status badge

## Validation
- `just ci`
- focused Playwright coverage for morphing, shared geometry, and
light/dark contrast

Signed-off-by: kenny lopez <klopez4212@gmail.com>
2026-08-06 08:21:35 -07:00
Will Pfleger
02be413b82 feat(catalog): resolve publisher display name in catalog detail pane (#3640)
The catalog detail pane hardcoded "Community member" for every non-own
catalog entry. The publisher pubkey (`catalogSource.ownerPubkey`) was
already on every entry — it just was not being resolved to a name.

## What changed

**`desktop/src/features/agents/ui/PersonaCatalogDialog.tsx`**

`PersonaCatalogDetail` now calls `useUsersBatchQuery([ownerPubkey])`
when the selected entry is a community (non-own) catalog agent. The
label derivation is extracted into the exported pure function
`resolveCatalogOwnerLabel` and uses truthy fallbacks to handle empty or
whitespace-only kind:0 fields:

- Own entry → `"You"` (unchanged)
- `displayName` present and non-blank → the display name
- `displayName` absent/blank but `name` present and non-blank → the name
- Loading, unresolvable, or both candidates blank → `"Community member"`
(fallback preserved)

The batch query is disabled (`enabled: false`) when the entry is not a
community entry, so there is no extra network call for own entries or
built-in agents.

**`desktop/src/features/agents/ui/personaCatalogOwnerLabel.test.mjs`**

Unit tests for `resolveCatalogOwnerLabel` covering: populated
`displayName` wins; whitespace-only `displayName` falls through to
`name`; both candidates empty/whitespace/null/undefined all fall through
to `"Community member"`.

**`desktop/tests/e2e/agents.spec.ts`**

- Updated the existing assertion — it previously checked for the
hardcoded fallback; now asserts the resolved mock display name
`"alice"`.
- Added "catalog detail shows Community member when the publisher
profile cannot be resolved" — installs a catalog event from an unknown
pubkey and asserts the fallback still renders.

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1g8493u0xfsjrvflg4n08ezd7vec99mnwzlv0qgwpr9d7gvjwhuzqx59rhw <41ea58f1e64c243627e8acde7c89be667052ee6e17d8f021c1195be4324ebf04@buzz.block.builderlab.xyz>
2026-07-30 11:38:28 -04:00
klopez4212
9a386a0def Refine agent sharing dialog (#3699)
## Summary

- Refine the agent share dialog around recipient sharing, link copying,
catalog sharing, and export.
- Show memory settings only when a linked agent has memories to include.
- Use a catalog toggle for custom agents and keep built-in agents out of
the catalog flow.

## Validation

- `pnpm typecheck`
- Focused Playwright share and catalog flows

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-07-30 15:23:16 +00:00
klopez4212
73589408db fix: align responsive agent views (#3688)
## Summary
- Keep the Agents header full width while cards reflow independently.
- Collapse header actions into an overflow menu at the compact layout
threshold.
- Apply the same responsive grid rules to Agent Teams.

## Validation
- `pnpm -C desktop build:e2e`
- Focused Agents Playwright coverage
- Pre-push desktop checks and unit tests

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
2026-07-30 15:58:48 +01:00
Wes
f7a3988ba1 fix(desktop): preserve shared agent fidelity (#3553)
## Summary

Fixes two distinct fidelity failures in direct agent sharing:

- The sender now puts the same effective avatar shown on the agent card
into People-share and file-export snapshot PNGs, including
profile/kind:0 fallback avatars.
- The importer now persists the visible PNG body as the portable avatar
instead of ignoring it in favor of sender-local manifest references.
- Export materializes inherited runtime, provider, and model identifiers
verbatim, while preserving explicit definition values. It does not
translate or substitute configuration for a different recipient setup.
- Sharing waits for a profile-only fallback avatar query, preventing an
early-click race.

The PNG import path keeps the existing safety invariant: decode is
capped at 2048×2048 / 32 MiB and re-encoded avatars above the 2 MiB
inline limit fall back to the manifest reference. The exact transparent
1×1 no-avatar placeholder is ignored.

The original Tyler↔Wes screenshot demonstrates both stages: Wren's
attachment had an avatar that disappeared after **Add agent**
(receiver/import failure), while Pinky's attachment was already blank
(sender/projection failure).

### Related issue

N/A — reported and traced in the linked Buzz conversation.

### Testing

- `cargo test --manifest-path desktop/src-tauri/Cargo.toml
commands::personas::snapshot` — 57 passed
- `pnpm exec tsc --noEmit`
- Biome check on changed frontend/E2E files
- Pre-push hooks:
  - desktop check
  - desktop tests
  - desktop Tauri tests — 1853 passed, 14 ignored
  - file-size ratchet

The People-share E2E regression asserts that a profile-only avatar
reaches `avatarPngDataUrl` in the real encode command payload.

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-07-29 08:13:54 -07:00
klopez4212
a35771fc44 feat(desktop): refine agent catalog sharing (#2439)
## Summary

- add custom-agent catalog sharing and hide built-ins from discovery
- let owners publish later catalog updates from Share or while saving
edits — the save always persists locally, and the publish reports
`published` or `queued` (flushed automatically once the relay is
reachable again)
- preserve agent type, model, and runtime across snapshot import/export
- simplify agent and team entry points and tighten catalog layout
- migrate the legacy global retention queue into the owner's active
scope so pending catalog publishes survive the upgrade
- keep the agent list and edits usable in recovery mode by degrading to
unshared projections when scope resolution or the retention DB fails
- track catalog provenance on copied personas, so adding an
already-added foreign agent resolves to the existing copy instead of
creating a duplicate
- scope inbound persona events to the community relay they arrived on
- page the catalog read past the relay's 1,000-row query clamp
- unify the share dialog's memory-level choice into a single "What's
included" selector that drives both DM-send and copy-link delivery (all
six combinations preserved), group the delivery rows above the option
rows, and label the catalog toggle "Not shared" / "Shared"
- keep emoji avatars on catalog entries — they persist as inline
percent-encoded SVG, which the catalog projection's http(s)-only URL
guard used to drop, so a shared agent showed initials instead of its
avatar
- drop the "Active in communities" card from Agents settings, superseded
by the per-channel runtime controls in the members sidebar

## Screenshots

### Agent actions

![Agent
actions](https://raw.githubusercontent.com/block/buzz/4643581cd0882d8b101b04e3d8be290ea7e39f08/pr-2439--01-agent-menu.png)

### Team avatar stack

![Team avatar
stack](https://raw.githubusercontent.com/block/buzz/4643581cd0882d8b101b04e3d8be290ea7e39f08/pr-2439--02-team-menu.png)

### Catalog sharing

![Catalog
sharing](https://raw.githubusercontent.com/block/buzz/648d6eaf6df7d4daa5b7375948ed221f723793d6/pr-2439--03-share-to-catalog.png)

### Publish while editing

![Publish while
editing](https://raw.githubusercontent.com/block/buzz/bd4eb473ff456f6e665173054dc5a0f764594d1e/pr-2439--01-edit-agent-publish-updates.png)

### Publish from Share

![Publish from
Share](https://raw.githubusercontent.com/block/buzz/648d6eaf6df7d4daa5b7375948ed221f723793d6/pr-2439--02-share-dialog-publish-updates.png)

### Catalog details

![Catalog
details](https://raw.githubusercontent.com/block/buzz/4643581cd0882d8b101b04e3d8be290ea7e39f08/pr-2439--04-agent-catalog.png)

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
2026-07-28 15:01:03 -04:00
Luke Tornquist
313f793c87 feat(desktop): add search to agent emoji picker (#2630)
## Why
The agent avatar picker disables Emoji Mart search, making emojis
difficult to find when creating or editing an agent.

## What
- Enable sticky search in the shared agent avatar picker
- Focus the search field when the Emoji tab opens
- Add end-to-end coverage for search, focus, and selection

## Risk Assessment
Low — this is limited to the desktop agent avatar picker and does not
change avatar persistence or agent configuration.

## References
- `pnpm --dir desktop test` — 3,448 passed
- `pnpm --dir desktop typecheck` — passed
- `pnpm --dir desktop exec playwright test tests/e2e/agents.spec.ts` —
20 passed

---
**Update Jul 24, 16:28 EDT:** Completed `CONTRIBUTING.md` validation.

### Manual test
1. Create an agent and open Add avatar → Emoji.
2. Confirm the search field is focused and filters results.
3. Select an emoji and confirm it becomes the avatar.
4. Repeat while editing an existing agent.

### Validation
- `just ci` — passed
- `just test` — passed

### Follow-up work
None.

Generated with Codex
2026-07-27 09:47:31 -07:00
Wes
836cf5f6ed Remove additional agents gallery (#2098)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-18 16:37:52 -07:00
Clay Delk
3e80b76666 feat(desktop): clean up Agents page copy and streamline agent defaults (#2031)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 18:22:30 +00:00
Cameron Hotchkies
256542da41 fix(e2e): replace flaky frame-count assertion with stable height check (#2011)
Signed-off-by: Cameron Hotchkies <chotchkies@block.xyz>
Co-authored-by: npub1cn4wxjqpz52r62hvt88u2kfxvlkpy3dvqdu7sagdzd6fwdahlz0q24c648 <c4eae3480115143d2aec59cfc5592667ec1245ac0379e8750d13749737b7f89e@sprout-oss.stage.blox.sqprod.co>
2026-07-16 20:31:45 -07:00
Tyler
74f3f29758 feat(desktop): ensure starter channels during onboarding (#1937)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-16 15:40:48 -04:00
Jordan Mecom
c540ec9678 [codex] Prevent actor-tag UI impersonation (#1931)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-16 15:07:26 -04:00
morgmart
2910ea45de Redesign agent AI configuration and defaults (#1935)
Signed-off-by: npub1d6t84ajeg9skp2609l2k6axgcme8x7g7u7luj352r03hcwreg7lqnxcsex <6e967af659416160ab4f2fd56d74c8c6f273791ee7bfc9468a1be37c387947be@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1s654z6utm59mkg4tjdqw69tlen05y2hrrwajlck4n2ar0jyx7hfsmp60kf <86a9516b8bdd0bbb22ab9340ed157fccdf422ae31bbb2fe2d59aba37c886f5d3@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1d6t84ajeg9skp2609l2k6axgcme8x7g7u7luj352r03hcwreg7lqnxcsex <6e967af659416160ab4f2fd56d74c8c6f273791ee7bfc9468a1be37c387947be@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1s654z6utm59mkg4tjdqw69tlen05y2hrrwajlck4n2ar0jyx7hfsmp60kf <86a9516b8bdd0bbb22ab9340ed157fccdf422ae31bbb2fe2d59aba37c886f5d3@sprout-oss.stage.blox.sqprod.co>
2026-07-16 04:08:47 +00:00
Wes
202201f3aa fix(desktop): allow editing built-in agents (#1928)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-15 18:49:17 -07:00
Wes
dbf2cfc21e fix(desktop): remove superseded built-in agents (#1929)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-15 17:09:25 -07:00
klopez4212
2f3fa586f3 Polish agent and team sharing and snapshots (#1852) 2026-07-15 17:19:03 +00:00
Will Pfleger
1580046b3c feat(desktop): add buzz-agent-snapshot v1 export, import, sender-native send, and recipient card/import (#1753)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-12 19:30:21 -04:00
Wes
41b187f936 copy(desktop): the word "persona" leaves the UI (Phase 1B.4) (#1646)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
2026-07-08 17:33:26 +00:00
klopez4212
ed84a87358 feat(desktop): emoji avatar picker for agents + reliable picker scroll (#1576)
Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1n6taw59js7ztz8pt9vma9uqx6g3gcvrwg37nmx9m8lq88yla0tjqfy2ncn <9e97d750b28784b11c2b2b37d2f006d2228c306e447d3d98bb3fc07393fd7ae4@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
2026-07-07 07:16:31 -07:00
klopez4212
228122fddc Add agent catalog modal (#1302)
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
2026-07-02 16:26:31 -07:00
klopez4212
826d735fe6 Revamp new agent dialog (#1201) 2026-06-29 06:35:00 -07:00
klopez4212
ccf1bfe3a0 Simplify agents and teams cards (#1199)
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Bart Simpson <bart@buzz.local>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@sprout-oss.stage.blox.sqprod.co>
2026-06-26 23:24:23 +00:00
klopez4212
5130a6a0b6 Improve global search (#1195) 2026-06-23 14:31:06 -07:00
klopez4212
89ae31d203 Polish direct message and members modals (#1054) 2026-06-15 22:24:07 +01:00
Wes
ea5a0a9b40 Replace built-in personas with Fizz (#987)
Signed-off-by: Wes <wesb@block.xyz>
Signed-off-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1gjuws2a2dc8z2nszprtg7v6u9q7ffeah3hgl5yx45jwn7y7aqs6s5e9xj6 <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
2026-06-11 13:50:14 -07:00
Wes
8f580f308c Rename desktop app to Buzz (#960)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-06-11 15:06:24 +00:00
Wes
efbdc7bfd5 feat(desktop): persona-first agent UX + bug fixes (#570)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 15:13:41 -07:00
Wes
27bcd45cc9 Refresh built-in personas: Solo, Kit, Scout + Kit & Scout team (#499)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:22:26 +00:00
Wes
05ba08412c fix(desktop): header UX polish and member list improvements (#447)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-01 18:51:30 +00:00
Wes
d26fda9e4d refactor(desktop): standardize UI with shadcn components (#379)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 13:03:48 -07:00
Wes
4d44f4741f Restore chooser-based persona catalog flow (#275) 2026-04-08 21:04:09 -07:00