Repository navigation
Closed
Labels
area:fullstackEnd-to-end Host and Client implementationEnd-to-end Host and Client implementationarea:ui-uxInteraction and visual experience; may accompany a code-layer areaInteraction and visual experience; may accompany a code-layer areaenhancementNew feature or requestNew feature or requestfeature:avatarPersonaBot avatar media and activity framePersonaBot avatar media and activity framefeature:profilePersonaBot Profile surface (popover, view, cards)PersonaBot Profile surface (popover, view, cards)scope:tracerHuman-testable implementation sliceHuman-testable implementation slice
Milestone
Description
Part of #425(T2)· Moves: v1.1 → v1.0
Scope
自定义 PersonaBot 头像的完整流程:上传 → 裁切 512×512 → 持久化 → 读取 → 删除回退,全程有类型 / 大小 / 路径 / 资源上限与测试。
Decisions (2026-09-29)
- 存储:有界 data URL 存进
bot.json的avatar字段(唯一权威);随 profile 文件天然可携带,export 不会悬空(export UX 仍归 Tracer: publish a Memory Git repo and import through a Bot link #17 / Design: Profile Backup / Restore / Transfer UX #76)。见 ADR-0086。 - 参数:输入 PNG / JPEG / WebP;裁切为 512×512;输出 WebP(质量 0.85 起自适应下调);解码后硬上限 128 KiB;只接受
data:image/(png|jpeg|webp);base64,;magic-byte 嗅探;拒绝远端 URL。 - 读取:
botharness/list/get/sessionOwner返回受认证的读取 URL(新增 DSH fetch route,带 ETag),避免消息驱动的 roster 刷新重传 base64。 - 回退:缺失 / 非法 / 损坏 → 确定性 identity-seeded Blobatar。
- 客户端:复用
PersonaBotAvatar(src已支持图片)与群头像裁剪交互;入口在 Profile view(Tracer 1: Profile popover + Profile view 表面与名字内联编辑 #426 之后)。
Acceptance criteria
- 用户可在默认 Blobatar 与自定义图片之间切换,并能预览、裁切、保存和删除。
- 持久化后 Host restart 与客户端重连均恢复。
- 删除 / 损坏 / 不可用资产确定性回退 Blobatar。
- 文件类型、尺寸、路径与资源耗尽攻击有明确限制和测试(host 侧校验 + route)。
- 读取 route 有缓存校验,且不把 base64 内联进列表响应。
- 自定义图片在 Activity Frame 内保持静态(thinking / working 仍可访问地表达)。
- Motion preference 遵守 UI Foundation: BotHarness motion preference(System / Reduce / Full) #128,不自行读取或持久化。
- light / dark 与无障碍路径通过 Human 验收。
Related
- Bot activity: shared snapshot and live DM presence #120 shared Avatar / Activity Frame(motion 交互;不再阻塞上传本体)
- Tracer: publish a Memory Git repo and import through a Bot link #17 / Design: Profile Backup / Restore / Transfer UX #76 export 语义(bot.json 自带字节,无悬空引用)
- ADR-0086, ADR-0081(群头像先例)
Metadata
Metadata
Assignees
Labels
area:fullstackEnd-to-end Host and Client implementationEnd-to-end Host and Client implementationarea:ui-uxInteraction and visual experience; may accompany a code-layer areaInteraction and visual experience; may accompany a code-layer areaenhancementNew feature or requestNew feature or requestfeature:avatarPersonaBot avatar media and activity framePersonaBot avatar media and activity framefeature:profilePersonaBot Profile surface (popover, view, cards)PersonaBot Profile surface (popover, view, cards)scope:tracerHuman-testable implementation sliceHuman-testable implementation slice
Type
Projects
- StatusShow more project fieldsDone
- StatusShow more project fieldsDone
Activity
[-]v1.1: 自定义头像(预设 / 上传 / 裁切)[/-][+]Future: 自定义头像资产(上传 / 裁切 / 持久化 / Export)[/+]DoodleBears commentedon Sep 20, 2026
Triage result: keep this as the independent future custom-avatar asset pipeline. It has been detached from the M3 parent/project and narrowed to upload, crop, persistence, deletion, fallback, and export semantics. Shared activity rendering belongs to #120; custom image pixels remain static inside that Activity Frame.
9 remaining items
[-]Future: 自定义头像资产(上传 / 裁切 / 持久化 / Export)[/-][+]自定义头像资产:上传 / 裁切 512 / 持久化 / Blobatar 回退[/+]DoodleBears commentedon Sep 28, 2026
Agent work claim
opencode/local/feat-58-personabot-avatar(branch-scoped reference)feat/58-personabot-avatar(worktreeBotHarness-profile, based on origin/main)DoodleBears commentedon Sep 28, 2026
Agent work status
opencode/local/feat-58-personabot-avatarfix(host): honor RFC 9110 If-None-Match matching for avatars
docs: align the bridge table and keep profileActivity in its own slice
PersonaBot avatars: bounded custom image storage and crop (#438)
DoodleBears commentedon Sep 28, 2026
Agent work outcome
opencode/local/feat-58-personabot-avatar