已验证

通过本机 Hermes CopilotACPClient 的底层 _session() 启动 /usr/bin/opencode acp,在同一个 ACP session 内连续调用两轮 session/prompt:

  • 模型目录包含 opencode-go/cat-jam-free。
  • session/set_config_option 返回 currentValue=opencode-go/cat-jam-free,确认实际选择,不依赖模型自述。
  • 第一轮发送随机测试 token,第二轮不再携带 token;第二轮准确返回它。
  • 两轮均 stopReason=end_turn,均报告 cachedReadTokens=12800。
  • 测试 session:ses_ec5b73a54ffehmFBqmwTZbCSDA。
  • 可复现实验脚本:${HOME}/.hermes/profiles/alaya/cache/scratch/probe_opencode_acp.py(临时目录,不作为长期安装入口)。

关键限制

本机 agent/copilot_acp_client.py 的标准 chat.completions.create() 经 _run_prompt() 每次进入 _session();该上下文每次启动子进程、请求 session/new,退出时终止子进程。因此现成 copilot-acp provider 能调用 OpenCode,但并不按用户要求持久复用 OpenCode session。标准 shim 的 usage 还填零,不能用其统计判断实际缓存和额度。

本次只验证持续存活的同一 ACP session 的两轮推理,没有验证重启后 session/load、CLI 既有 session 接续、Hermes 外层工具调用回路或权限隔离。实验禁止文件桥请求并要求不用工具,不是操作系统沙盒。

后续实现与重启续接实测

新增可运行原型 ${HOME}/.hermes/profiles/alaya/tools/opencode_acp_lane.py:显式要求 --cwd 与 --session,初始化先检查 loadSession 能力,再调用 session/load;续接失败直接报错,绝不默默创建新 session;实际核对模型选择响应,并透传 ACP 原始 usage。

在原测试 session 上依次运行独立进程:

  1. 重启后准确回忆此前随机 token:缓存读取 12864 tokens。
  2. 新进程写入额外标记,回复 ACK:缓存读取 12928 tokens。
  3. 再次新进程续接并准确回忆额外标记:缓存读取 1984 tokens,inputTokens 11149。

说明 session 跨进程恢复有效,但缓存命中不保证稳定,更不能将 session 复用等同于零额度消耗。

客户端拒绝 permission 请求和客户端文件/终端回调;这不是 OS 沙盒,不能证明 OpenCode 自带的已授权工具无法运行。原型仅用于无工具推理验证,尚未接入 Hermes 正式 provider,也未验证编码工具回路。

运行形式:python3 ${HOME}/.hermes/profiles/alaya/tools/opencode_acp_lane.py --cwd <工作区> --session <已有ID> '<消息>'。

缓存优化与对照实测

原型新增 --stream:同一进程逐行接收 JSON { "prompt": "..." },只加载 session、选择模型一次;后续持续复用。模型已选中时跳过重复 set_config_option,不添加时间戳或重复历史到每轮输入。

同一原 session,固定模型/工作目录/短提示,交错执行 4 次重启与 4 次持续模式,全部回复 CACHE_OK。原始样本保存于 Alaya scratch/acp_cache_bench.json,复现脚本为 scratch/acp_cache_bench.py。

  • 重启:缓存读取合计 52928,inputTokens 合计 413,耗时中位数 3.569 秒。
  • 持续:缓存读取合计 52800,inputTokens 合计 522,耗时中位数 1.887 秒。
  • 若 inputTokens 与 cachedReadTokens 为互斥统计,缓存输入占比分别 99.23% 与 99.02%;这是计算口径假设,不是账单结论。
  • 此轮两组都高命中,未证明持续模式提升缓存比例;持续模式主要降低进程/会话恢复开销。测试仅短文本,历史逐轮增长,没有控制上游路由,不能外推为长期/编码场景保证。

OpenCode Go 官方文档要求固定 x-opencode-session 便于路由/缓存;ACP 原型固定 harness session ID,让 OpenCode 负责上游请求,不伪造 header 或缓存统计。

当前采用策略

不修改 Alaya provider、gateway、配置或 Hermes 核心源码。AZone 编码继续使用 OpenCode CLI 显式 --session 续接已有工作会话。若接入 ACP 作为正式后端,先做持久进程/session 生命周期、重启恢复、工具权限和实际 usage 接入的独立实现及验收,不能将本实验称为生产部署完成。