Skip to content

feat: 新增 AssistantRender hook 事件——LLM 输出显示层重渲染 #1357

Description

@viggo-pod

发帖前必读

  • 我已经搜索过 现有 Issues,没有找到重复。
  • 这是功能建议,不是 Bug 报告或使用问题。
  • 使用问题请前往 Discussions

要解决的问题

LLM 的文本输出与终端显示强耦合:模型输出的原文直接进渲染层,无法在「显示层」做重渲染。典型场景:

  • <mermaid> 标签 / mermaid ``` 代码块在回合结束后渲染成 ASCII 图就地展示
  • 表格美化、长输出折叠、脱敏展示等显示层变换

现有 hook 事件都无法安全地只改「显示」:在 Stop / PostToolUse 等钩子里改写消息会污染 transcript 与模型上下文,破坏 prompt cache 与对话一致性。

建议方案

新增第 28 个 hook 事件 AssistantRender

  • 触发时机:回合末(Stop hooks 之后)逐条 assistant 消息触发,输入 message_id + text_blocks(非空 text 块原文与 block_index
  • 输出协议hookSpecificOutput.updatedBlocks = [{blockIndex, text}],未列出的块显示原文
  • 仅替换显示层:结果写入内容寻址缓存(sha1(原文)[:16]),transcript 与模型上下文始终保留原文
  • 单脚本语义:仅支持注册一个有效 hook(去重后计数 >1 时发可见警告并整体不渲染)——渲染不是管道,各 hook 拿到的都是原始 text_blocks,多脚本只会重复渲染并互相覆盖
  • 零开销短路:无 hook 注册时不构造输入、不 spawn
  • 安全边界:30s 超时(显示路径钩子收紧);/clear--resume/--continue 时清空渲染缓存

使用示例(settings.json):

{
  "hooks": {
    "AssistantRender": [
      { "hooks": [{ "type": "command", "command": "node ~/plugins/mermaid-inline.mjs" }] }
    ]
  }
}

hook 从 stdin 收到:

{ "hook_event_name": "AssistantRender", "message_id": "msg_...", "text_blocks": [{ "block_index": 0, "text": "<mermaid>...</mermaid>" }] }

stdout 返回:

{ "continue": true, "hookSpecificOutput": { "hookEventName": "AssistantRender", "updatedBlocks": [{ "blockIndex": 0, "text": "ASCII 图" }] } }

即可把该 text 块的终端显示替换为渲染结果。

配套实现:renderCache 模块、MessageRow renderCacheVersion / 重绘纪元重绘机制(解决 OffscreenFreeze 静态定格行的重印)、/clear 缓存清理接线、全类型层注册(HOOK_EVENTS ×4、zod Schema、SDK 生成类型)。

考虑过的替代方案

  • 在 Stop / PostToolUse 钩子里改写消息:污染 transcript 与模型上下文,破坏 prompt cache 与对话一致性,放弃。
  • 把渲染器硬编码进核心:不可扩展,社区无法挂自己的渲染管道,放弃。
  • 多 hook 管道式串联:渲染不是管道(各 hook 只见原始输入,看不到上一个 hook 的输出),串联语义不成立,故采用单脚本语义。

补充信息

  • 测试:新增 3 个测试文件共 13 用例(执行器 0 / 1 / >1 注册三等价类、内容寻址缓存行为、memo 比较器版本号机制),bun test 全过;tsc --noEmit 零错误;biome 通过
  • 真实场景端到端验证过:mermaid 源码块在回合末被渲染类 hook 就地替换为 ASCII 图,transcript 中始终为源码,/clear 后缓存正确失效
  • 实现见配套 PR

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions