Skip to content

fix(desktop): fan out managed agent profiles - #2659

Open
AaronGoldsmith wants to merge 1 commit into
block:mainfrom
AaronGoldsmith:smarty/2366-profile-fanout
Open

AaronGoldsmith wants to merge 1 commit into
block:mainfrom
AaronGoldsmith:smarty/2366-profile-fanout

Conversation

@AaronGoldsmith

@AaronGoldsmith AaronGoldsmith commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Reconcile an existing managed agent's kind-0 profile on each community relay after that agent/community runtime pair starts successfully.

This fills the profile-transfer boundary left intentionally out of the per-community runtime work in #2083 and addresses the missing-name/avatar portion of #2366 without claiming to close the broader issue.

What changed

  • Query and, when missing or stale, publish kind-0 on the originally requested community relay.
  • Authenticate both operations with the managed agent's keys and auth tag.
  • Run profile repair asynchronously so a slow or unavailable relay cannot delay runtime startup or the rest of the batch.
  • Preserve the requested relay authority, including loopback aliases and explicit ports.
  • Keep relay-local legacy-avatar resolution from mutating the single stored agent record during fan-out.

Behavioral guarantees

  • Reconciliation starts only after the corresponding runtime pair starts successfully.
  • A profile read or publication failure is logged but does not fail runtime startup.
  • Query and publication use the same explicit relay authority and managed-agent credentials.
  • Existing legacy single-relay reconciliation behavior remains intact.

Scope boundaries

This PR does not:

Related avatar work remains in #2476 and #2507.

Manual verification

  1. Start an existing managed agent in two configured communities.
  2. Confirm each community continues using its own running runtime pair.
  3. On a community relay missing that identity's kind-0, confirm the agent name/avatar metadata is republished there.
  4. Make one destination relay unavailable and confirm runtime startup and other community pairs still complete.

Test plan

  • Rebased onto origin/main at 76aeae703664a6a6741b82771df67c546886aafd.
  • Full Desktop Rust suite: 1,616 passed, 0 failed, 14 ignored.
  • Integration diagnostics: 3 passed.
  • Commit hooks: sadscan, fmt, and desktop-tauri-fmt passed.
  • Independent adversarial agent review: no findings after addressing a legacy-avatar backfill race.

Reviewer guide

Please focus on:

  • managed_agents/runtime_commands.rs: the success-only, detached fan-out trigger;
  • commands/agents_profile.rs: explicit relay validation and separation of global legacy backfill from relay-local fan-out;
  • relay.rs: agent-authenticated profile query used by reconciliation.

Refs #2366.

@AaronGoldsmith
AaronGoldsmith marked this pull request as ready for review July 24, 2026 01:46
@AaronGoldsmith
AaronGoldsmith requested a review from a team as a code owner July 24, 2026 01:46

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75bf466a7a

ℹ️ 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".

Comment thread desktop/src-tauri/src/commands/agents_profile.rs Outdated
@AaronGoldsmith
AaronGoldsmith force-pushed the smarty/2366-profile-fanout branch from 75bf466 to 476c632 Compare July 24, 2026 02:14
Reconcile each successfully started managed-agent runtime pair's kind-0 profile on that community's requested relay authority. Query and publish as the agent, and detach profile repair so relay failures cannot block runtime startup.

Co-authored-by: Smarty <200df3a6e10192207329b9b398aabb85b020e8880257cd59835c6e1a994914d6@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1yqxl8fhpqxfzquefhxee324mskczp6ygqftu6kvrt3hp4x2fzntqvmcw9s <200df3a6e10192207329b9b398aabb85b020e8880257cd59835c6e1a994914d6@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1yqxl8fhpqxfzquefhxee324mskczp6ygqftu6kvrt3hp4x2fzntqvmcw9s <200df3a6e10192207329b9b398aabb85b020e8880257cd59835c6e1a994914d6@sprout-oss.stage.blox.sqprod.co>
@AaronGoldsmith
AaronGoldsmith force-pushed the smarty/2366-profile-fanout branch from 476c632 to 101bcf5 Compare July 24, 2026 04:43
wesbillman added a commit that referenced this pull request Sep 18, 2026
…7732)

## Summary

Fix Desktop-managed agents losing avatars after joining another
community. The saved persona/instance stores one desired source URL, but
authenticated media belongs to a community. Republishing community A’s
URL in B does not make that image accessible in B.

- Before comparing or publishing kind-0, reuse or copy
configured-community avatar media into the pinned destination. Keep
exact image bytes, including animation, and leave the saved source
unchanged.
- Keep the previous profile on transfer/publication failure so existing
reconciliation can retry. Reuse destination bytes during source outages;
after source removal, reuse only an already-published signed destination
picture with the same original content hash.
- Refresh source permissions through narrow, serialized IPC without
reconnecting or resetting the active community. Startup waits until the
latest permission update completes before restoring agents.

### Related issue

Refs #2366 (avatar portion only, not runtime availability). Related
#2659 deliberately excludes avatar/media mirroring; this change
addresses that media boundary without introducing runtime fan-out.
Searched existing issues/PRs for `avatar community` before opening.

## Contract and safety

Desktop-managed profiles still follow the saved persona source; this
does not introduce community-specific persona editing. Agent-managed
profiles still opt out of automatic reconciliation.

Authenticated transfer requests use the fixed agent key/NIP-OA tag,
origin-scoped Blossom auth, and the pinned destination, never mutable
active-workspace owner credentials. They refuse redirects, enforce
30-second request timeouts and bounded bodies, verify SHA-256 and
detected image MIME, and validate the returned descriptor’s
origin/hash/MIME/size. Source permission is rechecked after an awaited
destination HEAD miss. The removed-source fallback verifies the
destination profile’s signature, kind, signer, origin, and
original-media hash without contacting the removed source.

Ordinary external images retain passthrough behavior and receive no
community credentials. No public-media policy change, image-reader URL
rewriting, new persistence, background service, or global profile merge.

## Testing

Normal commit and push hooks passed on exact head
`925781eece66d5f6a4b084b3b3abd6309cda357e`; working tree clean before
and after:

- Desktop formatting/lint, typecheck, and **6,508 tests**.
- Full native workspace suite, including **3,204 desktop-library tests**
(19 ignored), integration tests, terminal crates, and doc tests.
- Native Clippy on default and `mesh-llm` workspace/all-target
configurations with warnings denied; repository file-size and
branch-skew gates.

Regression coverage exercises production reconciliation/shared
publication against two local HTTP fixtures: add/edit/restart, upload
and rejected-publication retry, removed-source local-image preservation,
fixed signer/destination, redirect/hash/descriptor/size failures,
revocation during pending HEAD, and opt-out no-I/O. Mounted
initialization tests cover inactive-list changes without workspace
reset, two deferred permission updates, and rejection of either update.

Earlier working-tree validation at base
`4ab4f786085a23fe6126529861840eff6048ceee` also passed the E2E frontend
build and four Chromium mock-bridge community flows (boot, switch,
active removal/fallback, leave-final/setup). Subsequent production
changes only serialize permission writes and wait for a stable latest
update; the complete suites above cover the final commit. Mutations
independently removing serialization or stable waiting failed the new
regression.

## Remaining validation and limitations

- No live production avatar was changed. Native GUI rendering against
two hosted communities remains to be verified with a build containing
this fix; local HTTP fixtures and the browser mock bridge do not
establish that outcome.
- A removed/unreachable source with no existing destination copy cannot
be recovered automatically. Choose a reachable image/source in that
case.
- This is a publication/reconciliation fix, not a visual redesign. No
before/after native GUI screenshots are claimed. Broad repository CI
remains required; it was not duplicated locally.

## Review

Independent security/scope and caller/ordering reviews are clear after
the bounded fixes. Final hook-ordering reread covered the staged tree
that became this commit. Commit authorship/sign-off use the implementing
Carl identity and configured Carl signing key.

Signed-off-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>
Co-authored-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant