## 设计总结 — 完整方案

Section 4/4：去掉 intensity 后的最终设计

### 标签协议（简化为）

`[表现:emotion]` 或 `[表现:emotion,动作:action]`

| emotion | action（可选） | blendshape 权重
--- | --- | --- | ---
取值范围 | joy, sad, surprised, angry, neutral | wave, nod, celebrate, surprised_react | 统一 0.7（有 emotion 时）

### 示例

[表现:joy,动作:wave]
太棒了！我一直在等你！
→ 先播 wave（一次性）→ celebrate（持续）+ blendshape happy=0.7
[表现:sad]
对不起，我查不到这个信息...
→ sad.vrma（持续）+ blendshape sad=0.7
[表现:neutral]
让我想想...
→ 清除 blendshape，回退到 petState fallback 动画

### 后端改动

正则简化为 `^\[表现:(\w+)(?:,动作:(\w+))?\]\n?`

`BehaviorParser.Feed()` 返回 `(text, emotion, action)`，buffer 上限 60 字节

emit `chat:behavior` → `{emotion: "joy", action: "wave"}`（action 空串即纯情绪）

保留旧 `chat:emotion` 兼容（Live2D 暂时继续消费）

### 前端改动

监听 chat:behavior 替代 VRMPet 内的 useEmotionEvents

applyBehavior({emotion, action}) 替代 applyEmotion()：

1. 如有 action → playAnimation(action, loop=false)，播完回退
2. 如有 emotion（非neutral）→ 设置 blendshape 0.7 + 切换持续动画
3. 如 neutral → 清除 blendshape，回退 petState fallback

petState watch 瘦身：只负责 mouth blendshape（speaking）、error 表情、idle 时清除 emotion

### Live2D 兼容

聊天空时从前端 emit `chat:emotion`（兼容事件）→ Live2DPet 现有的 useEmotionEvents 继续工作，无需改动。