Skip to content

opencode 插件模式下 render tag 注入消息正文,模型回显漏网后原样渲染进 TUI(元数据与正文同层问题) #933

Description

@jensenojs

现象

opencode 2.x TUI 会话正文里能看到原始 render tag 被渲染出来,例如 ``。这些是压缩协议的消息引用元数据,不是会话内容。

根因链(已取证)

  1. 请求侧注入acp-kernelrenderMessage(dist/index.js:1704-1720)在把会话历史发给模型前,给消息文本前插一行 ``——renderTags: "text-only" 策略下 text 消息逐条插。server.ts 每轮 `processTurn` 后重建请求体(`src/server.ts:1853/1980/2159`)原样带标签上发。
  2. 模型回显:标签进入模型上下文后,模型会在输出里照抄(本会话 bili.log 当日 212 条 [tag-echo] stripped model-emitted render tag 记录为证)。
  3. 响应侧 strip 是止血不是根治tag-echo-filter.ts偶尔重复输出 <acp tokens="177" type="text">m00155</acp> #206/[bug] #644 follow-up (post-#646, v0.1.97): typo'd render-tag echo (<acip …) bypasses the strip regex and passes through as a 43-char degenerate end_turn turn — agent stalls mid-orchestration until manual nudge #673 以来的累计修复)在输出流上剥标签,只覆盖 text/content/reasoning_content/reasoning/thinking 字段。凡模型把标签写进工具调用参数、代码块内文本、或命名错误变体等形态,strip 拦不住(#361 已承认 tool-call XML 只 warn 不剥;#673 已承认 typo 变体漏网)。
  4. 可见性:opencode 的 TUI 渲染的是会话消息的原文。注入发生在请求侧消息文本里,模型回显后若 strip 漏掉,该文本即进入会话存储并被原样渲染——用户看到的就是这个。

为什么这是架构问题而不是单个 bug

renderMessage 的注入策略把「协议元数据」写进了「消息正文」。协议元数据应该只存在于瞬态请求载荷(wire payload),一旦它以文本形式进入消息正文,就有三条暴露路径:模型回显、工具调用参数回带、decompress/压缩块摘要回灌。响应侧 strip 需要穷举所有回显形态才能堵住,而 #206/#361/#468/#673/#717 的迭代史证明穷举不完。

建议

  1. 主修复:把 render tag 从「消息正文前缀」挪出消息文本——例如改用 host 不可见的元数据通道(header/单独字段),或注入只作用于瞬时序列化视图、绝不落回 host 会话存储。
  2. 次选:若必须保留文本注入,给用户一个完全关闭注入的开关(现已有 ACP_RENDER_NONE / renderTags: "none",但默认值仍是 text-only——建议把 opencode 插件模式默认改为 none,因为 opencode 插件自己有 sessionID 绑定能力,模型端不需要靠正文标签识别消息)。
  3. 止损:文档明示 ACP_RENDER_NONE=1 可关闭。

复现

  • 长会话 + 开启压缩(renderTags 默认 text-only)
  • 任意一次压缩后,模型回显历史中的标签
  • 观察 bili.log [tag-echo] stripped 之外仍有漏网标签进入 TUI 正文

环境

  • opencode 2.0.3(Bun 编译二进制)
  • billion-context feat/pi-native-plugin 分支(本地构建)
  • 插件模式部署(plugins/billion-context + 代理自持)

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