Files
next-tjwater-frontend/docs/agent-persona-resource.md
T
jiang 2d8506fea0
Generic Container CI/CD / test-build-publish (push) Successful in 2m9s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m39s
feat: add project-aware agent workspace
2026-10-22 18:52:18 +08:00

92 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent 动画资源与离线水纹
Agent 保留原版 Obsidian 图形与运动结构,采用经实际动画对比选定的 02「冰水蓝」配色,并在 Rive 文件内部增加“静水待机”离线设计。在线保留外围水纹光圈;离线关闭外围三层光圈,仅保留球体内部的缓慢流动。在线、离线和交互使用同一个 `default` 状态机。
当前视觉规格、尺寸、标题区与交互约定统一见 [Persona 设计](agent-persona-design.md)。本文维护资源结构、生成过程与缓存实现。
## 文件与再生成
| 文件 | 用途 |
| --- | --- |
| [运行时源数据](../design/agent/obsidian-runtime.json) | 从原版解析的 775 个对象,包含图形、属性、关键帧、状态机和绑定数据 |
| [冰水蓝材质参数](../design/agent/obsidian-material.json) | 已确认的水体、暗部、白色高光和水纹颜色,以及球面底色遮蔽度 |
| [离线设计参数](../design/agent/obsidian-offline.json) | 可编辑的播放速度、振幅、混合时长和三层柔光/反射强度 |
| [生成脚本](../scripts/build-agent-persona.mjs) | 验证原版重编码、修改离线动画,生成本地资源 |
| [应用资源](../public/agent/obsidian-water-v1.riv) | 前端加载的 9,879 字节资源 |
| [缓存版本清单](../src/shared/ai-elements/persona-resource-manifest.json) | 生成脚本同步输出的路径、SHA-256 和字节数,用于客户端缓存更新 |
| [静态帧生成脚本](../scripts/render-agent-persona-stills.mjs) | 从实际资源渲染在线、离线 PNG,供首次加载、减少动态效果和失败兜底使用 |
| [资源对照测试](../tests/browser/agent-persona-resource.e2e.ts) | 真实 WebGL2 运行时定时推进,比较原版与修改版画面 |
在前端仓库运行:
```bash
node scripts/build-agent-persona.mjs
node scripts/render-agent-persona-stills.mjs
node scripts/build-agent-persona.mjs --check
# 将原版还原到一个尚不存在的文件,应用资源不会被替换
node scripts/build-agent-persona.mjs --restore-original /tmp/obsidian-original.riv
pnpm test:browser tests/browser/agent-persona-resource.e2e.ts tests/browser/agent-orb.e2e.ts --workers=1
```
JSON 保存原始运行数据;脚本负责可审查的定制。`--check` 验证原始数据能逐字节恢复,并检查生成结果与应用资源一致。基线 SHA-256 为 `c6ae7d08f5787a560e38d3453ba155c28250acf2db75e6acf2b0d1a0cd6017db`。替换上游基线时需重新解析和验证,不应只修改散列值跳过检查。
配色编辑 `obsidian-material.json`,其中 `bodyColor` 只控制球面底色,`bodyOpacity` 控制它在待机/活动时的遮蔽度,其他蓝色反射沿用 `colors` 映射;离线动画编辑 `obsidian-offline.json`;重新生成 `.riv` 和静态帧后刷新前端。静态帧脚本使用已安装的 Playwright、esbuild 与 Rive WASM,无需访问外部动画服务。`fps` 控制离线时间轴速度,`amplitude` 控制位移与缩放的变化幅度,`transitionMs` 控制在线/离线的混合时长。各层 `opacity` 中的 `rest` 和 `crest` 是相对原始透明度的比例,分别对应循环开始/结束与中点。数值需满足 `0 ≤ rest ≤ crest ≤ 1`;保留循环端点一致,避免接缝。外围三个光圈均固定为 `0`。
`--restore-original` 使用只创建模式,目标文件已存在时会报错,避免覆盖已有编辑。原版还原文件与基线逐字节相同,包含原版离线消失的行为;前端继续加载带离线设计的应用资源。
## 冰水蓝与离线设计
材质采用经原生 Rive 预览选定的 02 方案:水体 `#299FDF`、同色相暗部 `#1482BC`、白色高光 `#FFFFFF`、外围水纹 `#4C9ECC`。外围水纹从初选时的 `#B0E3FF` 加深,以提高浅色地图上的辨识度;光圈粗细、渐变 alpha 和运动保持原定义。球面底色独立设置为 `#DCEFFA`,待机/活动时的不透明度为 94%/98%,同步调整对应的活动状态关键帧。浅色且高遮蔽度的底层减少地图道路穿过球体的现象,蓝色反射仍由原来的运动图层呈现;暗部沿用蓝色调,避免叠加灰黑阴影。渐变位置、羽化、裁剪、运动曲线及其他节点的原有 alpha 保留,不添加 CSS 滤镜或 View Model 绑定。
此前 A「水务蓝」使用灰蓝主体、浅蓝高光与 78%/90% 的底色不透明度,在白底实际动画中显得发灰、浑浊,已被本方案替换。后续调整以同一背景下的真实动画及 40/64px 入口效果为准,不以色卡单独判断材质。
离线以“水面逐渐平静”表达连接不可用:外围三层光圈在 600ms 混合期间消退至完全不可见,内部柔光降低并保持缓慢流动。球体整体透明度和缩放保持完整;悬停不会重新打开离线光圈。恢复在线时重新显现光圈与在线节奏。业务状态仍由入口按钮的可访问名称和提示提供。
| 层 | 柔光强度 | 反射强度 | 循环周期 |
| --- | --- | --- | --- |
| 内层与下侧柔光 | 56%–68% | 0,关闭 | 15 秒 |
| 中层与内部柔光 | 48%–62% | 0,关闭 | 19.25 秒 |
| 外层与上侧柔光 | 60%–72% | 0,关闭 | 31.375 秒 |
上表是设计参数当前值的解释。内部柔光以原版贝塞尔缓动从 `rest` 升到 `crest` 再回落,周期错开,避免同步闪烁;光圈透明度保持为零。40/64px 入口共用同一资源,状态切换不改变布局尺寸。
参数中的图层名称是根据运行时结构补充的语义别名,不是恢复出的作者原始命名。`objectId` 是画板组件编号,不能用 JSON 对象数组的索引替代:绑定记录不占组件编号。
## 解析结果与修改
原版有 1 个 `Obsidian` 画板、20 段动画、13 个状态机层和 5 个布尔输入。`asleep` 动画在第 45 帧将节点 4 的透明度从 1 降至 0,并将节点 3、190、199、208 的缩放降至 0.6–0.8,因此离线时球体消失。
修改版保留原有图形、渐变结构、羽化、裁剪和在线运动,改变以下部分:
- 根据已选定的配色映射 RGB,并独立设置底色填充节点 189 的颜色、节点 186 的静止及活动透明度;原始 JSON 不改动,仍可完整还原银灰原版 `.riv`。
- `asleep` / `wake` 的透明度与缩放关键帧保持 1,避免隐藏或缩小球体。
- 在原有 20 段动画后追加 `offline_loop_1`、`offline_loop_2`、`offline_loop_3`,保持原有动画编号。
- 离线循环复用原版三层水纹,时间轴速率从 60 改为 24,约为原速的 40%;这是时间轴播放速度,不是将屏幕渲染限制为 24fps。
- 位移和呼吸振幅缩至原来的 25%;完整旋转保留首尾角度,避免循环接缝。
- 离线循环增加六个柔光/光圈节点的透明度轨道,其中节点 190、199、208 的光圈透明度固定为零;在线循环对应增加原始透明度常量轨道,确保恢复连接后完整恢复。
- 三个循环层根据既有 `asleep` 输入切换,使用 600ms 状态混合。其他输入、状态层和交互保持原定义。
生成结果包含 957 个对象、23 段动画。调整设计参数后需再生成并运行对照测试;无需修改前端组件或安装额外依赖。
## 前端接入与生命周期
悬停沿用原版节点 110 的反射尺寸,以及节点 129 对指针目标 1 的跟随约束。`Persona` 保留 Rive 监听器,通过外层 Pointer Events 向画布转交鼠标的进入、移动和离开坐标,Rive 自行完成画布与画板坐标转换。画布内部不直接命中鼠标或触摸,只有就绪的外层接收并筛选主指针;不转交触摸和按压,因此手机点击不会触发白色高光。仅手动设置 `hover` 而禁用原生监听,会使目标停在中心,造成中央大片变白。这个问题由事件通路修复,不通过缩小光圈或改变材质补偿。
`persona-resource.ts` 加载同源的 `/agent/obsidian-water-v1.riv?v=<SHA-256>`。同一页面共用下载 Promise,跨刷新、再次打开页面使用浏览器 Cache Storage 的 `tjwater-agent-persona-v1` 缓存;只共享不可变字节,不共享 Rive 实例或 View Model。
读取顺序为页面内存、当前版本的持久缓存、网络。下载及缓存命中均检查字节数和 `RIVE` 文件头;支持 Web Crypto 时进一步验证 SHA-256。损坏缓存重新下载,错误页或不匹配的资源不写入缓存。新版本成功保存后,只删除本缓存中该资源路径的旧版本,不清理其他应用数据。重新生成动画时同步更新版本清单,`--check` 同时验证资源与清单。
持久缓存不可用、被禁用或空间不足时仍可下载并在当前页面复用。Cache Storage 需要安全上下文,生产环境使用 HTTPS,本机 localhost 开发可用;浏览器清理站点数据也可能移除缓存,见 [Cache API 说明](https://developer.mozilla.org/en-US/docs/Web/API/Cache)。缓存测试覆盖真实页面刷新,并阻断资源网络路径验证动画仍能播放。
Agent 服务不可用不妨碍前端读取该资源。这项缓存仅覆盖 `.riv`,Rive WASM、应用代码与其他资源沿用各自的加载策略;不构成整站离线支持。浏览器完全断网且应用或运行时尚未加载时,仍可能无法播放动画。
在线与离线切换不卸载可见的 Rive 实例,由状态机处理过渡。静态帧仅用于首次加载、资源失败、减少动态效果及未挂载动画的情况:在线使用 `obsidian-water-idle.png`,离线使用无外围光圈的 `obsidian-water-offline.png`。两张 192px PNG 均由当前 Rive 材质直接渲染,URL 携带资源版本;首次加载维持 180ms 淡入,不再出现银灰占位图。保留可见性卸载、Strict Mode 延迟初始化和原版悬停;没有重新加入 Motion 按压效果或 View Model 绑定。历史约束见 [Rive 内存记录](rive-persona-incident.md)。
## 验证边界与来源
运行时 JSON 能恢复当前 `.riv`,但不等于作者的 `.rev` 编辑器工程;导出时省略的编辑信息没有凭空恢复。原作者提供可编辑 `.rev` 的说明见 [资源定制文档](https://elements.surge.studio/docs/customization),格式差异见 [Rive 备份说明](https://rive.app/docs/editor/exporting/exporting-for-backup)。
原始图形来源为 [Surge Obsidian 动画](https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/obsidian-2.0.riv)。解析时参考了 [rive-rs-cli 的格式读取实现](https://github.com/George-RD/rive-rs-cli/blob/main/src/validator/parser.rs)及其从 Rive 定义生成的类型/属性表;应用不依赖或包含该工具。原图形的作者归属不因解析和局部修改而改变。
对照测试在同一 WebGL2 运行时以固定时间步推进。就绪、思考、待回复、输出和悬停状态要求与“仅应用相同冰水蓝材质的原版”采样画面逐像素一致,并验证主色由灰变蓝、合成到白底后仍保有蓝色,球体中心采样区域的不透明度不低于 90%。悬停另外比较左右指针位置对应的高光重心,要求局部反射随指针移动且移出后完全恢复。工作台测试验证实际坐标到达原生监听器。离线检查完整球体、持续变化、初始离线和反复恢复;通过外围像素计数验证光圈完全消失,悬停不会重新出现,恢复在线后再次可见。另用相同运动轨迹、取消离线光照变化的对照资源,验证快速切换后在线明暗完整恢复。该检查覆盖固定采样时刻,不是所有设备、运行时间和状态序列的穷举验证。