feat(cli): mirror Desktop mention delivery - #3330
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4e2ea785b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
4e2ea78 to
fe84df9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe84df979f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
fe84df9 to
84b9afe
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84b9afe510
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz>
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
84b9afe to
6eb8350
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6eb83503dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0dfaed5e27
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
…dance * origin/main: fix(mobile): keep TLS on relays joined by invite (#3139) Improve emoji autocomplete matching (#3571) Fix shared agent avatar import profiles (#3578) Fix inline raster avatars in agent catalog (#3581) revert(acp): remove dead GOOSE_ACP_SCHEDULER_DISABLED env injection (#3576) feat(agent): make Gemini and MLflow-route models usable through databricks_v2 (#3569) fix(cli): mask credential env values in --help output (#3570) Serialize Tauri pre-push checks (#3567) chore(release): release Buzz Desktop version 0.5.1 (#3566) Run Tauri clippy in pre-push (#3555) perf(desktop): move observer-feed archive and decrypt commands off main thread (#3415) fix(desktop): preserve shared agent fidelity (#3553) Polish mobile navigation and menus (#3486) feat(agent): route Claude/GPT model families to their native gateway wire (#3538) Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a40f44ae4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d14fdd0b40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…-style * origin/main: feat(tracing): correlate trace IDs in relay logs (block#3608) chore(ci): bump Linux AppImage build container to ubuntu:24.04 (block#3602) feat(cli): mirror Desktop mention delivery (block#3330) Signed-off-by: Joah Gerstenberg <joah@squareup.com>
## Buzz Desktop release v0.5.2 ### Changes since v0.5.1: - feat(cli): mirror Desktop mention delivery ([#3330](#3330)) ([`7adc46268`](7adc462)) - fix(desktop): deduplicate relay outage notification ([#3579](#3579)) ([`66e705492`](66e7054)) - fix(desktop): reconcile thread arrivals at bottom ([#3585](#3585)) ([`b42a8d447`](b42a8d4)) - Improve emoji autocomplete matching ([#3571](#3571)) ([`259de6afb`](259de6a)) - Fix shared agent avatar import profiles ([#3578](#3578)) ([`324bd6b46`](324bd6b)) - Fix inline raster avatars in agent catalog ([#3581](#3581)) ([`7e9b77f72`](7e9b77f)) - feat(agent): make Gemini and MLflow-route models usable through databricks_v2 ([#3569](#3569)) ([`4a1ebf25c`](4a1ebf2)) **To release:** merge this PR. The tag and build will happen automatically. Signed-off-by: Wes <wesbillman@users.noreply.github.com>
* origin/main: (29 commits) feat(replica): portable heartbeat-token fence with snapshot-local reader routing (#3268) fix(git): channel binding tooling + author remediation for unbound repos (#3626) feat: configure S3 URL addressing style (#3400) feat: add first-class OpenRouter provider support (#1975) feat(agent,acp): wire provider total_tokens through NIP-AM publish chain (#3593) chore(release): release Buzz Desktop version 0.5.2 (#3624) docs: add Linux rendering troubleshooting guide (#3573) fix(desktop): discover bun-installed agent CLIs in ~/.bun/bin (#3343) feat(tracing): correlate trace IDs in relay logs (#3608) chore(ci): bump Linux AppImage build container to ubuntu:24.04 (#3602) feat(cli): mirror Desktop mention delivery (#3330) fix(desktop): deduplicate relay outage notification (#3579) fix(desktop): reconcile thread arrivals at bottom (#3585) fix(mobile): keep TLS on relays joined by invite (#3139) Improve emoji autocomplete matching (#3571) Fix shared agent avatar import profiles (#3578) Fix inline raster avatars in agent catalog (#3581) revert(acp): remove dead GOOSE_ACP_SCHEDULER_DISABLED env injection (#3576) feat(agent): make Gemini and MLflow-route models usable through databricks_v2 (#3569) fix(cli): mask credential env values in --help output (#3570) ... Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
* feat(storage): add Azure Blob conformance adapter Signed-off-by: Ross Hartmann <RossHartmann@users.noreply.github.com> * Improve emoji autocomplete matching (block#3571) ## Summary - Show all colon emoji autocomplete matches - Rank exact and prefix shortcodes before weaker matches - Add a regression test and screenshot ## Validation - `pnpm test` - `pnpm build` - `pnpm exec playwright test --project=smoke tests/e2e/custom-emoji.spec.ts --grep "exact standard shortcode"` - `just desktop-tauri-clippy` Native Tauri tests were attempted but could not link because the local disk filled during compilation. --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> * fix(mobile): keep TLS on relays joined by invite (block#3139) ## Summary Communities joined via an invite link never connect: the app dials `ws://` on port 80 instead of `wss://` on 443 and sits on "Reconnecting…" indefinitely. `RelayConfig.baseUrl` is documented as an HTTP origin, but the two onboarding flows disagree on what they persist: - **Device pairing** validates and stores `https://` — `pairing_provider.dart:657` throws on anything else. - **Invite join** stores the relay URL straight off the invite link, and `deep_link.dart:165` always emits `ws://` or `wss://`. `wsUrl` only special-cased `https://`, so a `wss://` base fell through to the plaintext branch: ```dart final scheme = uri.scheme == 'https' ? 'wss' : 'ws'; // 'wss' is not 'https' ``` The claim request itself succeeds, because `_claimUrlFromRelay` (`invite_join_provider.dart:242`) maps `wss → https` explicitly. Only the socket path is missing that conversion — which is why the community appears, correctly named, and then never loads. The same `baseUrl` also feeds `/query` (`relay_session.dart:136`), media upload (`media_upload.dart:765`), Blossom auth (`media_auth.dart:128`) and `relayClientProvider` (`relay_provider.dart:113`), so those requests were malformed too. Where port 80 *does* answer, it is additionally a silent TLS downgrade after `validateInviteRelayUri` insisted on `wss://`. This folds the websocket schemes back to their HTTP equivalents in `baseUrl` itself, so every consumer is correct by construction rather than needing a second getter remembered at each call site, and communities **already persisted** with `wss://` are repaired on read without a migration. `community_icon_provider.dart:46` already performs this same conversion locally. One subtlety worth flagging for review: the normalization is derived in the getter rather than applied in the constructor, so the constructor stays `const`. The compile-time fallback at `relay_provider.dart:77` relies on const canonicalization for a stable identity across rebuilds, and Riverpod's `defaultUpdateShouldNotify` is `previous != next` (`element.dart:361`), which falls back to identity for this class. A `factory` constructor here yields a fresh instance per rebuild, which tears down and resubscribes every listener — `channels_provider_test.dart` catches it as an unexpected unsubscribe during reconnect. ### Related issue Fixes block#2662. ### Testing `flutter test` — **705 passed, 1 skipped, 0 failed** `flutter analyze` — No issues found `dart format --set-exit-if-changed .` — 249 files, 0 changed Run against the Hermit-pinned SDK (Flutter 3.41.7 / Dart 3.11.5), matching CI. 10 new unit tests in `mobile/test/shared/relay/relay_config_test.dart` covering both onboarding schemes, `http`/`https` passthrough, non-default ports, and agreement between the invite and pairing paths for the same relay. Verified end-to-end against a self-hosted relay behind `tailscale serve`, which terminates TLS on 443 and leaves port 80 closed. Relay logs show the invite claim succeeding over HTTPS at the moment of joining, while no WebSocket connection ever arrives — no `WebSocket connection established`, no NIP-42 auth, no `kind:0` profile, no push registration — across the relay's entire history, even though the member row is present and correct. Port-80 refusals are not logged by `tailscaled`'s netstack, which is why the retries leave no trace server-side. Reproduced on both iOS and Android. --------- Signed-off-by: Krishna C <github@kumb.uk> * fix(desktop): reconcile thread arrivals at bottom (block#3585) ## Summary - reconcile stale native-scroll anchors when a reply arrives at the physical floor - clear the thread new-message affordance instead of incrementing it from stale cached state - preserve the existing mid-history path and add direct lifecycle regression coverage ## Why PR block#3411 fixed geometry-driven reconciliation, but the reply-arrival branch still trusted a cached `message` anchor without checking the rendered position. Native anchoring could return a short thread to the floor without another scroll/resize callback, then the next reply incremented the pill anyway. ## Verification - Desktop checks passed - Desktop typecheck passed - focused lifecycle test passed (6/6) - push hook full Desktop unit suite passed (3,770/3,770) - `git diff --check` passed Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> * fix(desktop): deduplicate relay outage notification (block#3579) 🤖 ## Summary - Keep the relay reconnect notification dismissed across repeated connection retries during one continuous outage. - Re-arm the notification after recovery or relay lifecycle replacement, including switches between communities that use the same relay URL. - Preserve the existing dedicated path for authentication and other application-level errors. ### How an outage is tracked The AppShell-owned relay-card hook treats an outage as one contiguous runtime episode rather than assigning it a persisted ID. A hook-local `outageActiveRef` is armed by the first qualifying unreachable/degraded observation. While it is armed, intermediate retry states (`connecting`, `reconnecting`, `stalled`, and `disconnected`) belong to that same episode, so retry churn cannot clear dismissal or emit another notification. The hook receives the same lifecycle identity used by community initialization: community ID plus `reinitKey`. This distinguishes multiple communities even when they share a relay URL, and it also changes when the active community is explicitly reinitialized. The latch and dismissal are reset when that identity changes or when the relay singleton reports its authoritative `idle` teardown state. A successful `connected` state also closes the episode and re-arms the next outage. These boundaries deliberately bias toward re-notifying rather than suppressing a later outage: recovery, community switch/reinit, or relay teardown cannot leave the hook stuck believing an old outage is still active. No outage state is persisted beyond the mounted hook lifecycle. ### Related issue None found. ### Testing - `pnpm --dir desktop typecheck` - `pnpm --dir desktop test` — 3,769 passed - `pnpm --dir desktop check` - `pnpm --dir desktop build:e2e` - `pnpm --dir desktop exec playwright test tests/e2e/sidebar-relay-card.spec.ts --project=integration` — 11 passed --------- Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> * feat(cli): mirror Desktop mention delivery (block#3330) 🤖 ## Summary Agent-authored mentions currently depend on matching visible `@Name` text to channel profiles. That makes notification delivery ambiguous when names collide or profiles change, and it encourages an extra post-send lookup just to confirm that the intended `p` tags were emitted. This change makes `buzz messages send` mirror Desktop's existing model: the message keeps a readable name in its content while the recipient pubkey is supplied separately. ```bash buzz messages send \ --channel <UUID> \ --content '@alice could you review this?' \ --mention <alice-hex-or-npub> ``` `--mention` is repeatable. The CLI normalizes and deduplicates explicit pubkeys, merges them with any names it can resolve from the channel, and gives explicit identities priority under the existing 50-mention limit. Before uploading attachments, signing, or publishing, the command checks every resulting pubkey against the channel's current membership: - Members are mentioned normally. - Non-members stop the send and produce an actionable error. - `--allow-non-member-mentions` deliberately sends notifying `p` tags without adding anyone to the channel. Sending a message never changes membership. On success, `mention_pubkeys` is read from the exact signed event and returned with the relay response, so callers can verify the emitted recipients without another query. Managed-agent guidance teaches this single-command mention flow. Desktop mention behavior and the Nostr event schema are unchanged. Forum guidance is intentionally handled separately in block#3596. ### Related issue None found. This replaces the earlier guidance-only approach in this PR with the underlying CLI behavior it required. ### Testing - `cargo test -p buzz-sdk` - `cargo test -p buzz-cli` - `cargo test -p buzz-acp` - `cargo test --manifest-path desktop/src-tauri/Cargo.toml` --------- Signed-off-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> * chore(ci): bump Linux AppImage build container to ubuntu:24.04 (block#3602) ## What and why The Buzz AppImage is built on `ubuntu:22.04`, which links WebKitGTK against FreeType 2.11.1. Because `libfreetype.so.6` is on the linuxdeploy community excludelist, the bundled WebKit loads the **host's** FreeType at runtime instead of the bundled one. FreeType 2.13.0 (released 2023-02-09) added `FT_Bool read_variable` to `FT_ColorStopIterator`, growing the struct from 16 to 20 bytes. Any host running FreeType ≥ 2.13 (Fedora 42+, Ubuntu 24.04+) has a struct-layout mismatch with the 22.04-compiled WebKit. The mismatched offsets corrupt color-stop index arithmetic inside Skia's COLRv1 renderer, producing the assertion abort in issues block#2548 and block#2982: ``` stl_vector.h:1123: Assertion '__n < this->size()' failed. ... colrv1_configure_skpaint(FT_Face, ...) ... ``` ## Fix Bump the build container to `ubuntu:24.04` (noble), which ships FreeType **2.13.2**. Noble's struct layout matches every crash-affected host. The ABI mismatch disappears and the crash is eliminated at root. WebKitGTK also advances from **2.50.4** (jammy backport) to **2.52.3** (noble backport). ## Glibc floor change | Build base | glibc floor | Oldest supported AppImage distro | |---|---|---| | ubuntu:22.04 (before) | 2.35 | Ubuntu 22.04 LTS, Debian 12 | | ubuntu:24.04 (after) | 2.39 | Ubuntu 24.04 LTS, Fedora 40+ | Ubuntu 22.04 LTS and Debian 12 users lose AppImage support. Both distributions continue to receive first-class `.deb` / `.rpm` packages, which use the system WebKit and are unaffected. The crash-affected users (Fedora 42/44, Ubuntu 24.04+) all have glibc ≥ 2.39. ## Changes - `.github/workflows/linux-canary.yml:24` — container pin updated to `ubuntu:24.04@sha256:4fbb8e6a…` - `.github/workflows/release.yml:479` — same container pin updated - `.github/workflows/release.yml:501` — comment version string updated from 22.04 to 24.04 `fix-appimage.sh` and `desktop/src-tauri/**` are untouched. The block#3573 fontconfig stopgap remains active; retirement is a separate follow-on PR once this fix is verified on a shipped build. ## Sequencing `docs/linux-rendering-troubleshooting.md` (introduced in block#3573) will receive a glibc-floor callout section once block#3573 merges — adding it here would conflict with block#3573's open branch. Context: block#2548, block#2982. Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> * feat(tracing): correlate trace IDs in relay logs (block#3608) ## Summary Correlates trace + span IDs with logs, allowing traces and logs to be bridged seamlessly ### Related issue none found ### Testing Unit tests Signed-off-by: David Grochowski <dgrochowski@squareup.com> Co-authored-by: Amp <amp@ampcode.com> * feat(storage): productionize Azure Blob backend Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(acp): bridge Buzz to exact-user Kiingo Compute Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(deploy): add Azure production packaging Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(acp): complete Buzz identity linking Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(acp): execute scoped Buzz actions locally Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(acp): preserve terminal stop reasons Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> * feat(desktop): add Kiingo subscription enrollment release * test(storage): run conformance against private Azure * build(storage): add private Azure conformance job * test(storage): rehearse Azure version recovery * fix(ci): keep Buzz desktop and Rust checks green * fix(deploy): keep Azure secrets inside Key Vault * test(deploy): verify Key Vault CSI delivery * fix(ci): resolve mesh checkout from Cargo metadata * fix(ci): keep fork pull requests read-only * fix(ci): fetch the exact mesh source when Cargo is sparse --------- Signed-off-by: Ross Hartmann <RossHartmann@users.noreply.github.com> Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Krishna C <github@kumb.uk> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Signed-off-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: David Grochowski <dgrochowski@squareup.com> Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com> Co-authored-by: Ross Hartmann <RossHartmann@users.noreply.github.com> Co-authored-by: klopez4212 <klopez4212@gmail.com> Co-authored-by: Krishna C <github@kumb.uk> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Co-authored-by: Logan Johnson <loganj@squareup.com> Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Co-authored-by: Dave Grochowski <ThePumpingLemma@users.noreply.github.com> Co-authored-by: Amp <amp@ampcode.com>
🤖
Summary
Agent-authored mentions currently depend on matching visible
@Nametext to channel profiles. That makes notification delivery ambiguous when names collide or profiles change, and it encourages an extra post-send lookup just to confirm that the intendedptags were emitted.This change makes
buzz messages sendmirror Desktop's existing model: the message keeps a readable name in its content while the recipient pubkey is supplied separately.--mentionis repeatable. The CLI normalizes and deduplicates explicit pubkeys, merges them with any names it can resolve from the channel, and gives explicit identities priority under the existing 50-mention limit.Before uploading attachments, signing, or publishing, the command checks every resulting pubkey against the channel's current membership:
--allow-non-member-mentionsdeliberately sends notifyingptags without adding anyone to the channel.Sending a message never changes membership. On success,
mention_pubkeysis read from the exact signed event and returned with the relay response, so callers can verify the emitted recipients without another query.Managed-agent guidance teaches this single-command mention flow. Desktop mention behavior and the Nostr event schema are unchanged. Forum guidance is intentionally handled separately in #3596.
Related issue
None found. This replaces the earlier guidance-only approach in this PR with the underlying CLI behavior it required.
Testing
cargo test -p buzz-sdkcargo test -p buzz-clicargo test -p buzz-acpcargo test --manifest-path desktop/src-tauri/Cargo.toml