Skip to content

fix(web): skip avatar character-traits fetch when custom image exists (LUM-1764)#31407

Merged
ashleeradka merged 2 commits into
mainfrom
ashlee/lum-1764-drift-avatar-skip-traits-when-image
May 21, 2026
Merged

fix(web): skip avatar character-traits fetch when custom image exists (LUM-1764)#31407
ashleeradka merged 2 commits into
mainfrom
ashlee/lum-1764-drift-avatar-skip-traits-when-image

Conversation

@ashleeradka
Copy link
Copy Markdown
Contributor

Closes LUM-1764 (partial — see "blocked" note below).

Summary

Back-port of vellum-ai/vellum-assistant-platform#7468.

useAssistantAvatar() was unconditionally fetching character traits alongside the components blob and avatar image. When an assistant has a custom avatar image, the traits file is intentionally deleted on the daemon side — so every SSE reconnect (which invalidates SYNC_TAGS.assistantAvatar) produced a fresh 404 on the traits endpoint. AvatarRenderer only reads traits when there is no custom image, so the fetch was pure waste in that branch.

What changed

  • src/domains/avatar/use-assistant-avatar.ts — fetch fetchCharacterComponents + fetchAvatarImageUrl in parallel first; conditionally call fetchCharacterTraits only when there is no image URL.
  • src/domains/avatar/use-assistant-avatar.test.tsx — new unit test mirroring the platform PR's coverage (skip when image resolves; still fetch when no image).

LUM-1764 status

Platform PR Status
#7468 (avatar skip-traits) ✅ this PR
#7494 (remove pro-upgrade-machine endpoint) ⛔ blocked — OSS still has an active caller (compute-upgrade-card.tsx). Platform's caller had already migrated to the unified OrganizationsBillingSubscriptionMachineResize endpoint in earlier PRs of their unify-resize-pvc-machine plan; OSS needs the equivalent migration first. Tracking on the Linear issue.

Verified locally

  • bun test src/domains/avatar/use-assistant-avatar.test.tsx — 2/2 pass.
  • bun run lint — 0 errors.
  • bun run typecheck — clean.

Test plan

  • CI green
  • Manual: open an assistant with a custom avatar image, observe network panel — no data/avatar/character-traits.json 404 on reconnect.

https://claude.ai/code/session_01JPGu4yGPTL4JoLaPuqpEW2


Generated by Claude Code

claude added 2 commits May 21, 2026 00:58
…ssistant/ (LUM-1753.4)

These were sitting in `domains/chat/api/assistant.ts` — the
runtime identity of the assistant has nothing to do with chat.
It's a property of the assistant itself, queried by chat, the
identity tab, contacts, intelligence, onboarding, the sync
router, and several stream handlers. Misplaced since day one.

Now lives at `apps/web/src/assistant/identity.ts`. The `chat`
file is renamed only in its header comment — it now solely owns
chat-context bootstrapping (`getChatContext`, `fetchAssistantId`).
The `domains/chat/api/assistant.ts` filename stays for now to
avoid churn; can be renamed in a follow-up if it bothers anyone.

Import sites updated: identity-tab, use-assistant-identity-init,
chat-page (two lines), chat-route-content, contacts-page,
chat-utils.

Cross-domain allow-list: 119 → 118 imports. Small numeric drop —
the structural win is that `fetchAssistantIdentity` no longer
sits in another feature's folder.

Verified locally: lint, typecheck, tests all green.

https://claude.ai/code/session_01JPGu4yGPTL4JoLaPuqpEW2
… (LUM-1764)

Back-port of vellum-ai/vellum-assistant-platform#7468.

`useAssistantAvatar()` was unconditionally fetching character
traits alongside the components blob and avatar image. When an
assistant has a custom avatar image, the traits file is
intentionally deleted on the daemon side — so every SSE
reconnect (which invalidates `SYNC_TAGS.assistantAvatar`)
produced a fresh 404 on the traits endpoint. 308 of them in
the platform team's local daemon log.

`AvatarRenderer` only reads `traits` when there is no custom
image, so the fetch was pure waste in that branch. Switch to:
- Fetch components + imageUrl in parallel first.
- If imageUrl is non-null, skip the traits fetch entirely.
- Otherwise fall through to the original behavior.

No new APIs, no behavior change for assistants without a
custom image.

Adds a unit test mirroring the platform PR's coverage:
- skips traits fetch when image resolves
- still fetches traits when no image

The other half of LUM-1764 — back-porting platform#7494 (remove
unused pro-upgrade-machine endpoint) — is blocked. The OSS repo
still has an active caller (`compute-upgrade-card.tsx`) that
needs to migrate to the unified machine-resize endpoint first.
Tracking on the issue.

https://claude.ai/code/session_01JPGu4yGPTL4JoLaPuqpEW2
@linear
Copy link
Copy Markdown

linear Bot commented May 21, 2026

LUM-1764

@ashleeradka ashleeradka marked this pull request as ready for review May 21, 2026 01:35
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

Copy link
Copy Markdown
Contributor

@vex-assistant-bot vex-assistant-bot Bot left a comment

Choose a reason for hiding this comment

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

APPROVE

Value: Eliminates a guaranteed-404 network request on every SSE reconnect for assistants with a custom avatar image — pure noise reduction that cleans up the network panel and removes unnecessary daemon load.

What this does: Two changes in one:

  1. The fix (use-assistant-avatar.ts) — fetches components and imageUrl in parallel first, then conditionally calls fetchCharacterTraits only when no custom image exists. Before: all three ran in Promise.all unconditionally. Since the daemon deletes character-traits.json when a custom image is set, the traits fetch was generating a fresh 404 on every SYNC_TAGS.assistantAvatar invalidation (i.e., every SSE reconnect). AvatarRenderer only reads traits when customImageUrl is absent, so this was pure waste.

  2. The refactor (src/assistant/identity.ts) — lifts AssistantIdentity + fetchAssistantIdentity out of src/domains/chat/api/assistant.ts into a new src/assistant/identity.ts module. Identity is a property of the assistant itself, not a chat bootstrapping concern. All six import sites updated; cross-domain allowlist updated correctly (identity-tab.tsx drops chat since it no longer imports from the chat domain — contacts-page.tsx correctly keeps chat because it still uses useAssistantContext).

Checks:

  • Sequential fetch latency trade-off is intentional and correct — we must know imageUrl before deciding on traits. The extra RTT (components+image → traits, in series) only applies to the no-custom-image path, which is where traits are actually needed anyway.
  • assertHasResponse + !response.ok in identity.ts is slightly redundant (the assert may throw first), but it mirrors the platform pattern exactly and is harmless.
  • SSR guard for SDK_BASE_OPTIONS is a no-op in production (SPA, no SSR) but makes the module safely importable in bun test environments.
  • Test correctly uses mock.module before await import — standard bun isolation pattern. Covers both branches: image present → fetchCharacterTraits not called; no image → traits fetched normally.

CI: all 7 checks green ✅ Devin: No Issues Found ✅

Vellum Constitution — Trust-seeking: eliminating predictable 404s on reconnect removes a class of false-alarm errors from network telemetry, keeping the signal-to-noise ratio of diagnostics high.

@ashleeradka ashleeradka merged commit c998fa2 into main May 21, 2026
7 checks passed
@ashleeradka ashleeradka deleted the ashlee/lum-1764-drift-avatar-skip-traits-when-image branch May 21, 2026 01:58
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.

2 participants