Files
oc_session/README.md
T

4.1 KiB
Raw Blame History

compaction-cn — 让 OC 对话压缩摘要输出简体中文

OpenCode 原生压缩(compaction)提示词硬编码在 opencode.exe 二进制里,摘要默认纯英文; 后续任务里模型很容易被前面那段英文摘要带偏。本插件在压缩请求发出前往 system 追加 中文输出指令,让摘要内容用简体中文、标题原样保留英文(标题不能译,原因见下)。

分支名:compaction-cn | 文件:compaction-cn.ts


一、安装

源码真源 / 本机生效 / WSL 生效三份同步(MD5 必须一致):

源码真源 : D:\桌面\源码\oc_session\compaction-cn\compaction-cn.ts
本机生效 : C:\Users\ypshidifu\.config\opencode\plugins\compaction-cn.ts
WSL 生效 : /root/.config/opencode/plugins/compaction-cn.ts

插件在 session 初始化时加载(不是进程启动时),装好后新建一个会话即可生效, 已开会话不会热加载。


二、为什么只能这样干预(2026-09-25 实测定稿)

候选干预点 结论
V1 hooks(default 对象上的字段,含官方文档的 experimental.session.compacting) ❌ 2.0.15 V2 运行时零消费者,探针 24 次 setup 全成功、A.* 日志全空;且 named export 返回 hooks 对象会被当 cleanup 调用 → TypeError: Ae is not a function 整批插件崩
opencode.config.compaction ❌ schema 只有 {auto, buffer, keep.tokens},没有 prompt 覆盖字段
ctx.session.hook("model.request", cb) ❌ payload 是 [sessionID, agent, model, kind, baseURL, headers],没有 messages,只能识别(kind="compaction")不能改写内容
ctx.session.hook("compaction", cb) ✅ 唯一可行。payload = [sessionID, model, system, messages, options, agent, tools],system 会带进最终压缩请求

压缩请求时序(二进制逆向):

compaction hook(prep)  →  [...messages, 模板 Zt.user(z$(...))]  →  model.request(kind="compaction")

模板是在钩子之后才追加进 messages 的,所以钩子改不到模板本身,只能改 system。

关键约束:小节标题绝对不能翻译

输出校验 ww = (e) => e.split("\n").some(a => U$.includes(a.trim())), U$ 是模板按行过滤出的英文标题行。摘要里必须整行命中这些英文标题,否则压缩直接失败:

## Objective / ## Requirements / ## Decisions / ## Work State /
### Completed / ### Active / ### Blocked /
## Next Move / ## Relevant Files / ## Important Context

所以本插件只加规则「内容中文、标题原样英文」,外加路径/代码/URL/报错原文不翻译。


三、工作方式

setup(ctx) 里向 ctx.session.hook("compaction", cb) 注册一个回调,往 g.system 数组 push 一段带 <compaction-language> 标记的文本。带标记是为了幂等判重—— 多 location、多次 reload 可能重复注册钩子,已注入过就不再加。

日志(不进 stdout,避免污染 TUI):

C:\Users\ypshidifu\.config\opencode\compaction-cn.log     # Windows
/root/.config/opencode/compaction-cn.log                   # WSL

正常会看到:

compaction 钩子注册完成 registration=[...]
已注入中文输出指令 sessionID="ses_xxx" system段=5 messages=N

四、V2 插件契约(与 ai-mcp 同款,勿破坏)

  • default 导出 必须给 { id, setup }(缺了报 Plugin must export a default definition...)
  • setup 必须返回 void,绝不抛异常(返回 hooks/truthy 对象 → Ae is not a function 整批崩)
  • named export 用逗号表达式安全形态:export const X: any = async (_ctx: any) => (await ({} as any), undefined as any)
  • 本插件所有异常都在内部吞掉并落日志,绝不影响同批其它插件

五、效果对比

压缩前(原生英文输出):

## Objective
- Respond to the user with "收到".

装插件后(e2e 实测,has_en_headers=True、英文标题原样保留、正文全中文):

## Objective
- 按用户要求回复"收到"。
## Requirements
- 回复内容必须为"收到"。
...