Files
agent/docs/event-mapping.md

3.2 KiB
Raw Permalink Blame History

事件映射

三层映射

Pi 发出的事件首先经过 PiEventAdapter 变成经过裁剪和脱敏的 HarnessEvent。Web 的 reducer 再把有序事件投影为 assistant-ui 消息、工具和运行状态。Pi 原始对象不会直接进入浏览器。

Pi / Harness 来源 HarnessEvent Web / assistant-ui 状态
Session 创建 session.started 建立初始 timeline
HTTP message input user.message user message,附件仅为 IDs
Harness 开始 run run.started isRunning=true,显示停止按钮
message_update.text_delta assistant.delta 按稳定 messageId 追加文本
最终 assistant message_end(非 toolUse / error) assistant.completed assistant message complete
tool_execution_start tool.requested 创建工具调用 part
tool_execution_end 成功 tool.completed 自定义工具使用 Pi result.details 展示指标和保存结果
tool_execution_end 失败 tool.failed 工具卡显示安全错误
Broker 请求 approval.required 打开服务器审批 Dialog
Broker 决策 / 超时 / 取消 approval.resolved 关闭 pending 状态
AttachmentStore 成功 attachment.uploaded 保存安全附件元数据
AttachmentStore 拒绝 attachment.rejected timeline / 错误状态
ModelStore 配置 model.configured 更新安全模型摘要
Harness 正常结束 run.completed run 和消息标为 complete
Harness 取消 run.cancelled 消息 incomplete/cancelled
Harness 失败 run.failed 消息 incomplete/error
Session 删除 session.ended 连接回到 idle

Skill 推导事件

skill.requested 和 skill.loaded 不是 Pi SDK 的原生事件。Harness 按下面条件推导:

flowchart LR
  A[Pi read start] --> B[realpath]
  B --> C{是否匹配 SkillIndex}
  C -->|否| D[只保留普通 tool 事件]
  C -->|是| E[skill.requested]
  E --> F{同一 toolCallId read 成功}
  F -->|是| G[skill.loaded]
  F -->|否| H[不发 loaded]

真实路径匹配避免仅凭用户提供的字符串伪造 Skill 活动。事件由 Session 队列串行处理,因此异步 realpath 不会导致 read end 越过 read start。

运行时索引匹配 Session 内的只读 Skill 正文快照,目录面板仍展示来源路径。模型尚未输出文本时,首个工具事件也会建立 assistant 消息,避免工具卡片一直隐藏到最终回复。

顺序、重放与去重

  • 每个 Session 的 sequence 从 1 单调递增。
  • SSE 初次连接可用 afterSequence,重连可用 Last-Event-ID。
  • Server 先重放 cursor 之后的事件,再订阅新事件,并发送 heartbeat。
  • Web 忽略 sequence 小于等于当前值的重复事件。
  • sequence 出现缺口时,Web 不应用该事件,而是重置投影并从 0 重连。
  • timeline 最多保留 500 条客户端状态,界面显示最近 100 条筛选结果。

数据最小化

事件负载经过 redactAndLimit。API Key、authorization、token 等敏感字段被脱敏;工具参数和结果有字节上限。图片事件只含 ID、MIME、字节数和尺寸,不含 base64。错误映射只保留明确 code 和有限长度的安全消息。