Skip to content

codex agent hooks: 条目无标识字段,靠 command 匹配带来「唯一 cmd」约束与 teardown 不对称 #266

Description

@m0Nst3r873

背景

#238install_hook_rule / uninstall_hook_rule,实现见 #265)为 codex 落地了 HTTP-source agent hook。claude 格式用条目上的 description 写入专属 marker [teamai:agent-hook:<slug>],卸载时按 slug 精确匹配。但 codex 的单个 hook 条目没有任何可承载 slug 的标识字段,导致两个问题。

问题

1. 「每个 codex slug 必须用唯一 cmd」是一个不友好的对外约束。
codex 条目只能靠 command 字符串区分。若两个不同 slug 用了相同 cmd,卸载其一时会按 command === "..." 误删另一个。目前只能在文档里要求后端「每个 codex slug 用唯一 cmd」来规避。

2. teardown 对 codex 不对称、依赖 manifest 完整性。

  • claude agent hook 靠 [teamai:agent-hook: marker,即使本地 manifest(~/.teamai/local-agent/agent-hooks.json)丢失,reconcileHooks(removeAll) 仍能扫描 marker 清除残留。
  • codex agent hook 无 marker,removeAgentHook / reconcileCodexFormat 只能靠 manifest 里记录的 command 匹配。manifest 丢失/损坏时,codex 残留无法被扫除(claude 不受影响)——「no residue」保证对 codex 不成立。

根因(已核实官方 schema)

查证 codex 官方源码 codex-rs/config/src/hook_config.rs(main):

  • 单个 hook 条目是内部标签枚举 HookHandlerConfig::Command,字段封闭:command / commandWindows / timeout / async / statusMessage / additionalContextLimit没有 id / name / description 等自由标识位。
  • 顶层 HooksFile 标了 #[serde(deny_unknown_fields)],且条目是 internally-tagged enum —— 往文件/条目里塞自定义键(如 _teamai)会导致 codex 解析报错,不是被忽略。官方文档亦印证:"parser is aware of specific known fields and reacts to unexpected values"。
  • 顶层虽有一个 description 元数据字段,但它"doesn't change which hooks run"、不在条目层,无法给单条 hook 打标识。

结论:codex 条目里唯一能承载 [teamai:agent-hook:<slug>] 字符串的字段是 statusMessage —— 而它是"hook 运行时在 UI 显示的提示语",会对用户可见。不存在零副作用的 marker 字段。

候选方案

  • A. 用 statusMessage 当 marker(对齐 claude description 机制)
    • CodexHookEntry 增加 statusMessage? 字段,写入 [teamai:agent-hook:<slug>];按 marker 精确匹配替换/删除,reconcileCodexFormat 的 removeAll 分支也能按 marker 扫除残留。
    • ✅ 取消「唯一 cmd」约束;✅ teardown 不再单靠 manifest(消除不对称)。
    • ⚠️ 代价:该 marker 在 codex 运行该 hook 时会于 UI 显示(内容语义上约等于"teamai 托管的 hook"提示)。
  • B. 维持现状(command 匹配 + manifest)
    • 零 UI 副作用,但保留「唯一 cmd」约束、且 manifest 丢失时 codex 残留扫不掉。

关联

参考

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions