sidebar_position: 2 title: “ACP Internals” description: “How the ACP adapter works: lifecycle, sessions, event bridge, approvals, and tool rendering”
ACP 内部实现
ACP 适配器将 Hermes 的同步式 AIAgent 封装在异步的 JSON-RPC 标准输入输出服务器中。
主要实现文件包括:
acp_adapter/entry.pyacp_adapter/server.pyacp_adapter/session.pyacp_adapter/events.pyacp_adapter/permissions.pyacp_adapter/tools.pyacp_adapter/auth.pyacp_registry/agent.json
启动流程
hermes acp / hermes-acp / python -m acp_adapter
-> acp_adapter.entry.main()
-> parse --version / --check / --setup before server startup
-> load ~/.hermes/.env
-> configure stderr logging
-> construct HermesACPAgent
-> acp.run_agent(agent, use_unstable_protocol=True)
通过 uvx --from 'hermes-agent[acp]==<version>' hermes-acp 命令启动的 Zed ACP 注册表路径,会使用指向 hermes-agent PyPI 版本的相同适配器。
标准输出用于 ACP JSON-RPC 传输,而便于人类阅读的日志则输出到标准错误流。
主要组件
HermesACPAgent
acp_adapter/server.py 负责实现 ACP 代理协议。
其功能包括:
- 初始化/身份验证
- 新建/加载/恢复/分叉/列出/取消会话的相关方法
- 提示执行操作
- 会话模型切换
- 将同步的 AIAgent 回调与 ACP 异步通知相连接
SessionManager
acp_adapter/session.py 用于追踪正在运行的 ACP 会话。
每个会话都会存储以下信息:
session_idagentcwdmodelhistorycancel_event
该管理器具备线程安全特性,支持以下操作:
- 创建会话
- 获取会话信息
- 删除会话
- 分叉会话
- 列出会话
- 清理会话
- 更新当前工作目录
事件桥接模块
acp_adapter/events.py 负责将 AIAgent 的回调转换为 ACP 的 session_update 事件。
被桥接的回调包括:
tool_progress_callbackthinking_callback(在 ACP 桥接模块中当前设置为None,推理功能通过step_callback来处理)step_callback
由于 AIAgent 在工作线程中运行,而 ACP I/O 操作则在主线程的事件循环中执行,因此该桥接模块采用了以下机制:
asyncio.run_coroutine_threadsafe(...)
权限桥接模块
acp_adapter/permissions.py 负责将危险的终端确认提示转换为 ACP 权限请求。
映射规则如下:
allow_once-> Hermes 的once模式allow_always-> Hermes 的always模式- 拒绝选项 -> Hermes 的
deny模式
默认情况下,若超过超时时间或桥接模块发生故障,请求将被拒绝。
工具渲染辅助模块
acp_adapter/tools.py 负责将 Hermes 工具映射为 ACP 工具类型,并生成面向编辑器的内容。
示例:
patch/write_file-> 文件差异内容terminal-> shell 命令文本read_file/search_files-> 文本预览内容- 对于大量结果 -> 为确保界面显示安全而进行截断处理的文本块
会话生命周期
new_session(cwd)
-> create SessionState
-> create AIAgent(platform="acp", enabled_toolsets=["hermes-acp"])
-> bind task_id/session_id to cwd override
prompt(..., session_id)
-> extract text from ACP content blocks
-> reset cancel event
-> install callbacks + approval bridge
-> run AIAgent in ThreadPoolExecutor
-> update session history
-> emit final agent message chunk
取消操作
cancel(session_id):
- 设置会话取消事件
- 在条件允许时调用
agent.interrupt() - 使提示响应返回
stop_reason="cancelled"
分支创建
fork_session() 会将消息历史记录深度复制到一个新的实时会话中,从而保留对话状态,同时为该分支分配独立的会话 ID 和工作目录。
提供者/认证机制
ACP 并未实现自身的认证存储机制。
它会复用 Hermes 的运行时解析器:
acp_adapter/auth.pyhermes_cli/runtime_provider.py
因此,ACP 会使用当前配置的 Hermes 提供者及凭证。此外,它还会始终声明一种终端设置认证方式(hermes-setup,参数为 --setup),以便首次运行的注册表客户端能够在启动常规 ACP 会话之前,先打开 Hermes 的交互式模型/提供者配置界面。
工作目录绑定
ACP 会话会携带一个编辑器的工作目录。
会话管理器通过任务范围的终端/文件覆盖机制,将该工作目录与 ACP 会话 ID 相关联,从而使各类文件和终端工具能够基于编辑器的工作空间进行操作。
同名工具的重复调用
事件桥接器会按工具名称为每个工具维护一个先进先出(FIFO)的工具 ID 列表,而并非仅为一个名称分配一个 ID。这一点对于以下场景非常重要:
- 并行执行同名工具
- 在同一步骤中多次调用同名工具
若没有 FIFO 队列,完成事件可能会被错误地关联到某个工具的调用上。
审批回调的恢复机制
在提示语执行期间,ACP 会临时在终端工具上安装一个审批回调,之后再恢复之前的回调设置。这样即可避免让特定于 ACP 会话的审批处理程序永久性地全局保留。
当前的限制
- ACP 会话会被持久化到共享的
~/.hermes/state.db(SessionDB)文件中,并在进程重启后自动恢复;这些会话也会显示在session_search中 - 目前,非文本类型的提示内容不会被纳入请求文本提取范围
- 不同 ACP 客户端的编辑器用户体验可能存在差异
相关文件
tests/acp/— ACP 测试套件toolsets.py—hermes-acp工具集定义hermes_cli/main.py—hermes acpCLI 子命令pyproject.toml—[acp]可选依赖项及hermes-acp脚本