事件接口的设计目标是让所有本地工具使用同一份最小协议:发送一个 JSON 事件,描述来源、事件类型、状态含义、展示文本、生命周期和可选动作。应用负责接收、校验、路由和呈现。
当前主接口是 localhost HTTP:
POST http://127.0.0.1:17321/eventsGET http://127.0.0.1:17321/healthzpetctl 是同一协议的人类友好封装。脚本和 hook 可以直接调用 petctl notify、petctl state、petctl clear,也可以自己发 HTTP JSON。
核心事件对象是 LocalPetEvent:
{ "source": "codex-cli", "type": "task.completed", "level": "success", "title": "Task completed", "message": "Edited 3 files", "state": "review", "ttlMs": 300000, "dedupeKey": "codex:session-id", "cwd": "/Users/example/project", "action": { "type": "open_folder", "path": "/Users/example/project" }}字段语义:
| 字段 | 作用 |
|---|---|
source | 事件来源。空值归一为 unknown。 |
type | 来源自己的事件类型,例如 codex.turn.running。 |
level | 通用严重程度和状态提示:info、running、success、warning、danger。 |
title | 展示标题,也是线程标题的首选来源。 |
message | 展示上下文,通常会被压缩成短预览。 |
state | 直接指定宠物动画状态。存在时优先于 level。 |
ttlMs | 事件存活时间。过期后从路由器移除。 |
dedupeKey | 跨来源或跨 turn 合并同一条逻辑事件。 |
cwd | 当前工作目录,用于显示项目上下文。 |
action | 点击宠物时可执行的受限动作。 |
state 和 level 同时存在时,state 是更明确的指令;只有没有 state 时才从 level 推导动画状态。
状态和级别映射
Section titled “状态和级别映射”事件级别到宠物状态的默认映射是:
level | 推导状态 |
|---|---|
danger | failed |
warning | waiting |
success | review |
running | running |
info 或缺省 | idle |
可直接指定的状态包括:
idlerunningwaitingfailedreviewjumpingwavingrunning-leftrunning-right路由器按状态优先级选择当前可见状态:
failed > waiting > running > review > idle这让失败和等待批准这类需要人处理的状态压过普通运行状态,也让新的运行任务可以压过旧的 review 提醒。
生命周期和去重
Section titled “生命周期和去重”事件进入路由器后会按 ttlMs 过期。如果没有指定 TTL,系统按状态给默认值:失败和等待保留更久,运行状态较短,idle 不进入活动事件集合。
去重有两层:
- 同一个
source的新事件替换旧事件。 - 同一个
dedupeKey的新事件移除旧事件,即使来源不同。
这个模型适合 agent 会话:一次 Codex thread 可以持续产生 running、waiting、review 等事件,但桌面上只保留一条逻辑线程。
动作 Schema
Section titled “动作 Schema”动作对象是可选字段。当前支持四类:
{ "type": "open_url", "url": "https://github.com/org/repo/actions" }{ "type": "open_folder", "path": "/Users/example/project" }{ "type": "open_file", "path": "/Users/example/project/build.log" }{ "type": "open_app", "bundleId": "com.openai.codex" }动作不是命令执行接口。事件源不能提交 shell command;只能请求打开经过策略校验的 URL、文件、目录或 app。
事件接口使用简单 HTTP 状态码表达接收结果:
| 状态 | 含义 |
|---|---|
202 | 事件已接受,并返回当前选中的宠物状态。 |
400 | JSON、字段或请求格式不合法。 |
403 | action 不在该来源的 allowlist 内。 |
413 | 请求体超过大小限制。 |
429 | 来源触发速率限制,响应包含 retryAfterMs。 |
GET /healthz 返回进程存活状态和路由快照,例如当前状态、活动事件数量、当前来源和是否存在可点击动作。它用于区分“宠物进程不可达”和“宠物可达但当前 idle”。
接口只绑定 127.0.0.1,默认不暴露网络 webhook。HTTP body 有大小限制,事件按 source 做内存速率限制,动作按来源策略校验。
配置文件位于:
~/.global-pet-assistant/config.json配置关注的是本地动作权限,而不是鉴权系统:哪些来源可以打开哪些 URL host、哪些路径根目录、哪些 app bundle id。当前做法是本地优先、保守开放。后续如果要让更多工具接入,应优先增加 Unix domain socket、token 或更细粒度的来源命名策略,而不是把接口暴露到局域网。
source 最好表示稳定的集成身份,例如 codex-cli、claude-code、ci;会话级信息更适合放进 dedupeKey。如果需要在 source 里携带实例后缀,例如 codex-cli:<session>,就要确认速率限制和动作 allowlist 是否也按这个粒度配置。