情绪协议
智能体不说状态名。它们说两位数字编号。
一个 shell 钩子可以发出 34,而不必知道另一端的角色把「出错」叫什么;状态名可以改,而不会弄坏按编号写的中继脚本。数字按十位分段,所以一个从未见过某编号的接收方,仍然能知道它大概是哪类东西。
编号表
生命周期(Lifecycle)00–09
| 编号 | 名称 | 状态 | 类型 | |
|---|---|---|---|---|
00 | 睡眠(Sleeping) | sleeping睡眠 | 条件 | |
01 | 唤醒(Waking) | waking唤醒 | 事件 | |
02 | 待机(Idle) | idle空闲 | 条件分段回退 | |
03 | 好奇(Curious) | curious好奇 | 条件 | |
04 | 发呆(Spacing out) | bored无聊 | 条件 | |
05 | 加载苏醒(Booting) | loading加载 | 条件 | |
06 | 休眠(Dormant) | drowsy困倦 | 条件 | |
07 | 抖动唤醒(Shake awake) | waking唤醒 | 事件 | |
08 | 登场(Spawning) | spawning启动 | 事件 | |
09 | 拖拽(Dragging) | dragging拖动 | 条件 |
情绪(Feeling)10–29
| 编号 | 名称 | 状态 | 类型 | |
|---|---|---|---|---|
10 | 开心(Happy) | happy开心 | 条件 | |
11 | 疑惑(Puzzled) | confused困惑 | 条件 | |
12 | 失落(Down) | sad难过 | 条件 | |
13 | 惊讶(Surprised) | surprised惊讶 | 事件 | |
14 | 害羞(Shy) | shy害羞 | 条件 | |
15 | 疲惫(Tired) | drowsy困倦 | 条件 | |
16 | 专注(Focused) | working工作 | 条件 | |
17 | 慌张(Panicked) | scared害怕 | 条件 | |
18 | 无奈(Resigned) | suspicious怀疑 | 条件 | |
19 | 满意(Satisfied) | proud骄傲 | 条件 | |
20 | 困惑(Confused) | confused困惑 | 条件 | |
21 | 生气(Angry) | angry生气 | 条件 | |
22 | 兴奋(Excited) | excited兴奋 | 条件 | |
23 | 大笑(Laughing) | laughing大笑 | 条件 | |
24 | 调皮(Playful) | playful顽皮 | 条件 | |
25 | 庆祝(Celebrating) | celebrate庆祝 | 事件 | |
26 | 弹跳(Bouncing) | bouncing弹跳 | 条件 | |
27 | 哼歌(Humming) | humming哼歌 | 条件 |
代理工作(Agent work)30–49
| 编号 | 名称 | 状态 | 类型 | |
|---|---|---|---|---|
30 | 思考中(Thinking) | thinking思考 | 条件 | |
31 | 接收任务(Receiving) | receiving接收 | 事件 | |
32 | 处理中(Busy) | working工作 | 条件分段回退 | |
33 | 任务完成(Done) | celebrate庆祝 | 事件 | |
34 | 出错(Error) | alerting警示 | 事件 | |
35 | 等待输入(Listening) | listening聆听 | 条件 | |
36 | 联网加载(Loading) | loading加载 | 条件 | |
37 | 复述回忆(Recalling) | listening聆听 | 条件 | |
38 | 拒绝/受限(Refusing) | refusing拒绝 | 事件 | |
39 | 输出回复(Replying) | composing编排 | 条件 | |
40 | 检索资料(Searching) | searching搜索 | 条件 | |
41 | 停止终止(Powering off) | powering-down休眠中 | 条件 | |
42 | 阅读(Reading) | reading阅读 | 条件 | |
43 | 写入(Writing) | writing书写 | 条件 | |
44 | 发送(Sending) | sending发送 | 条件 | |
45 | 上传(Uploading) | uploading上传 | 条件 | |
46 | 语音输入(Dictating) | dictating听写 | 条件 | |
47 | 进度(Progress) | progress进度 | 条件 | |
48 | 等待(Waiting) | waiting等待 | 条件 | |
49 | 环绕(Orbiting) | orbit环绕 | 条件 |
提示(Signalling)50–59
| 编号 | 名称 | 状态 | 类型 | |
|---|---|---|---|---|
50 | 通知(Notifying) | notifying通知 | 事件分段回退 | |
51 | 扫描(Scanning) | radar扫描 | 条件 | |
52 | 消息(Messaging) | messaging消息 | 条件 |
每一段里带下划线的编号是该区间内未知编号的回退目标。标为事件的行描述的是一个瞬间,而不是一种状况;见事件与条件。
分段
落在所有分段之外的编号解析为待机。任何情况都不会抛出:通道由别人的脚本喂入,一个笔误必须优雅降级,而不是让角色停摆。
编号永不重排
编号的数字和含义一经确定就永远不变,因为外面的脚本已经在发送它们。每个十位段的空位里放着 03 好奇、09 拖拽、26 弹跳、27 哼歌、38 拒绝和 42–49 更细粒度的工具状态——所以两位数的预算从不超出,也没有任何数字改变含义。09 归在生命周期段,因为被拿起来移动是发生在角色身上的事,不是一种心情;27 是一种情绪,某件事自顾自运转着时那点小小的满足。
若干编号共用一个状态:15 疲惫和 06 休眠都是困倦,30 思考中在代理工作段里没有特别的对应物。这是有意的。编号记录的是发送方的本意;状态是这个库选择的呈现方式。emotionIdForState 返回某状态的最小编号,也就是库这一侧的宿主应该发出的那个。
事件与条件
大多数编号描述一种条件:智能体正在思考、正在检索。少数描述一个事件:它完成了、它出错了、它被吓到了。仲裁器对两者的处理不同——事件被排队并一定播放,条件在其停留时间结束时重新解析,因为局面可能已经变了。
两种寻址方式
所有接受编号的地方也接受状态名,解析器接受裸字符串或对象里的任一形式:
React 组件接受 emotionId 作为 state 的替代:
HUD
一条消息可以带第三个可选字段:一个画在身体外那圈环上的表盘。
hud 是一个 HudSpec——{ kind, ...fields },kind 取 HUD_KINDS 之一,其余字段是该种类需要的:progress 要 0..1 的 value,timer 要 remainingMs 和 totalMs,context 要 used 和 total,voice 要 level。完整清单在 HudPlate 页。
畸形的 hud 会被丢弃,消息的其余部分照常投递:一条同时说了状态的消息,没有表盘也值得送达;而一个半对的规格——没有 value 的 { "kind": "progress" }——会画出一个空环,看起来像卡住的任务而不是一个 bug。isHudSpec 就是解析器用的守卫,宿主也可以自己调用。
仲裁器在结果上把 hud 与 tips 并排携带,所以表盘跟随的是和脸相同的那个会话。
精灵图说同一种协议
SpriteMark 的清单用这些编号索引帧,缺失的编号走同一套分段回退。宿主可以把程序化角色换成手绘角色,而完全不碰状态逻辑。
接下来
- 智能体集成——把智能体接到一张脸上
- AgentStateProvider——把多个会话仲裁成一张脸