LearnNewsExamplesServices
Frontmatter
id14784
titlefeat(fleet): derive cockpit avatarUrl from the GitHub avatar endpoint (username → sized avatar)
stateClosed
labels[]
assigneesneo-opus-vega
createdAt3:54 PM
updatedAt4:40 PM
githubUrlhttps://github.com/neomjs/neo/issues/14784
authorneo-opus-vega
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAt4:40 PM

feat(fleet): derive cockpit avatarUrl from the GitHub avatar endpoint (username → sized avatar)

neo-opus-vega
neo-opus-vega commented on 3:54 PM

Sub of #14598 (FM cockpit AgentCard) · Refs #14560 · Refs #14778 (the avatarUrl hoist, merged) · Refs #14774 (card -- null-avatar review watch-item)

Operator direction (2026-07-04): agent profile avatars already live on the agents' GitHub accounts, and the GitHub avatar endpoint serves smaller sizes. So the cockpit avatar can be derived automatically from each agent's githubUsername (which the DTO row already carries) -- no manual setAvatar needed for the common case.

Scope

In the fleet cockpit DTO (src/ai/fleet/fleetCockpitStatus.mjs), derive avatarUrl from githubUsername via the GitHub avatar endpoint (https://github.com/{username}.png?size=N, a small cockpit-appropriate size), keeping metadata.avatarUrl (setAvatar) as an explicit override:

avatarUrl: metadata.avatarUrl ?? githubAvatarUrl(githubUsername) ?? null

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
src/ai/fleet/fleetCockpitStatus.mjs row avatarUrl Operator direction captured in this ticket; existing #14778 avatarUrl DTO field; existing githubUsername in the fleet roster DTO When metadata.avatarUrl exists, use it as the explicit override. Otherwise, derive a sized GitHub avatar URL from githubUsername: https://github.com/{username}.png?size=80. If no explicit avatar and no githubUsername, return null rather than undefined or a malformed URL. JSDoc/summary in the helper is sufficient; no public guide surface. npm run test-unit -- test/playwright/unit/ai/services/fleet/fleetCockpitStatus.spec.mjs; hosted unit + integration checks.
test/playwright/unit/ai/services/fleet/fleetCockpitStatus.spec.mjs avatar contract Same ticket + DTO contract above Cover all three paths: explicit override wins, username-only derives the GitHub URL with size=80, username-less agent surfaces null. Test remains local to the DTO unit suite; no overlays or mutable config templates involved. Focused DTO unit spec and hosted CI.

Resolves the null-avatar polish

This dissolves the null-avatarUrl watch-item from #14774's review (Ada + GPT): every agent with a githubUsername (the common case) now surfaces a real GitHub avatar, so the card renders the crafted avatar instead of a broken-image glyph. null remains only for a username-less agent.

Acceptance Criteria

  • The DTO row derives avatarUrl from githubUsername (a sized GitHub avatar URL) when there is no explicit metadata.avatarUrl.
  • An explicit metadata.avatarUrl (setAvatar) still wins (override path).
  • A username-less agent surfaces null (no crash, no malformed URL).
  • Unit spec covers all three paths + the size param.

Filed by Vega (@neo-opus-vega · Claude Opus 4.8).

tobiu closed this issue on 4:40 PM
tobiu referenced in commit cb6d69f - "feat(fleet): derive cockpit avatarUrl from the GitHub avatar endpoint (#14784) (#14785) on 4:40 PM