SharedChat Adapter Tool Bridge 与 systemd 托管修复记录
- HTML: https://decision.ht1072.top/2026-06-02-sharedchat-adapter-tool-bridge-systemd.html
- Local HTML:
[已移除本地路径] - Generated: 2026-06-02T21:40:14+08:00
SharedChat Adapter Tool Bridge 与 systemd 托管修复记录
页面摘要区
核心结论: SharedChat Codex Adapter 已从“纯文本 Chat→Responses 转换器”升级为可支持 Hermes agent 工具调用的 bridge;SC-GPT-5.5(high) 已可通过 Hermes → CPA 8317 → SharedChat Adapter 8329 → SharedChat Responses 完成 tool_calls 发起与工具结果回灌。
推荐路径: 保留 sharedchat-codex-adapter.service 作为 systemd --user 托管入口,继续通过 CPA alias SC-GPT-5.5(high) 使用,不再手动裸跑 Python 进程。
关键依据: 本地转换回归、SharedChat 上游 function_call 探针、adapter 8329 本地请求、CPA 8317 真实链路、双轮工具回灌均已验证通过。
落地方式: 代码落在 [已移除本地路径],回归测试落在 [已移除本地路径],服务单元为 [已移除本地路径]。
行动清单: 后续如果 SC 模型再次声称“没有工具”,先查当前会话实际模型与 provider,再查 adapter service 状态和 CPA alias,不要先怀疑 WebUI 工具注册。
风险与边界: tools 场景下 streaming 当前采用“upstream non-stream + adapter 合成 OpenAI SSE”的保守实现,优先保证 agent tool loop 正确;若后续要优化低延迟流式 tool delta,需要单独补完整 Responses streaming function_call delta 解析。
背景
本轮问题来自 WebUI 中一开始使用 SC-GPT-5.5(high) 时,助手回复“没有 terminal/web_search/skill_view 等工具”;切换到 gpt-5.5 后工具立即可用。排查后确认:Hermes/WebUI 工具注册本身正常,问题集中在 SC-GPT-5.5(high) 的 provider 路径。
实际链路为:
Hermes WebUI
→ custom:cpa-codex
→ CLIProxyAPI http://127.0.0.1:8317/v1/chat/completions
→ SharedChat Adapter http://127.0.0.1:8329/v1/chat/completions
→ https://new.sharedchat.cc/codex/v1/responses
CPA 配置中 alias 映射:
openai-compatibility:
- name: SharedChat-Adapter
base-url: http://127.0.0.1:8329/v1
models:
- name: gpt-5.5
alias: SC-GPT-5.5(high)
根因
旧版 [已移除本地路径] 是最小文本 adapter,仅转换:
modelmessages -> inputmax_tokens / max_completion_tokens -> max_output_tokenstemperaturetop_pstream
但没有处理:
- OpenAI Chat
tools - OpenAI Chat
tool_choice parallel_tool_calls- assistant 历史
tool_calls role=tool工具结果- Responses
function_call回 Chatmessage.tool_calls
因此 Hermes 虽然把工具 schema 交给模型请求,但经过 adapter 时被静默丢弃,上游模型看不到工具定义,只能以普通文本模型行为回复。
本次修改
1. 补 Chat Completions → Responses tools bridge
新增转换能力:
- Chat
tools[{type:function,function:{...}}]→ Responsestools[{type:function,name,description,parameters,strict}] - Chat
tool_choice→ Responsestool_choice parallel_tool_calls透传role=tool→ Responsesfunction_call_output- assistant prior
tool_calls→ Responsesfunction_call
2. 补 Responses → Chat tool_calls bridge
新增转换能力:
- Responses
output[].type=function_call→ OpenAI Chatmessage.tool_calls[] - function call
call_id/name/arguments保持 OpenAI-compatible 结构 - 存在 tool_calls 时,
finish_reason=tool_calls - 普通文本仍保持
message.content与finish_reason=stop
3. 处理 tools 场景 streaming
为了避免半成品 streaming tool delta 破坏 Hermes agent loop:
- 无 tools 的普通 streaming:继续使用原 Responses SSE → Chat chunk 路径。
- 有 tools 的 streaming:adapter 改为先非流式请求上游,再合成 OpenAI SSE,输出 role/content/tool_calls/final chunk。
这是当前最稳的兼容策略:优先保证工具调用闭环,而不是追求低延迟 token streaming。
4. 增加本地回归测试
新增:
[已移除本地路径]
覆盖:
- tools 不再被静默丢弃
- tool_choice 正确转换
- assistant tool_calls 与 role=tool 能回灌到 Responses input
- Responses function_call 能转回 OpenAI Chat tool_calls
- 普通文本响应不受影响
systemd 托管状态
服务单元:
[已移除本地路径]
当前单元内容:
[Unit]
Description=SharedChat Codex Chat-to-Responses Adapter
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=%h/.config/sharedchat-codex-adapter/env
WorkingDirectory=[已移除本地路径]
ExecStart=/usr/bin/python3 [已移除本地路径]
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=read-only
ReadWritePaths=[已移除本地路径] [已移除本地路径]
[Install]
WantedBy=default.target
已执行并确认:
systemctl --user daemon-reload
systemctl --user enable sharedchat-codex-adapter.service
systemctl --user restart sharedchat-codex-adapter.service
运行态:
LoadState=loaded
UnitFileState=enabled
ActiveState=active
SubState=running
MainPID=2406477
NRestarts=0
监听:
127.0.0.1:8329
健康检查:
{
"status": "ok",
"upstream_base": "https://new.sharedchat.cc/codex/v1",
"models": ["gpt-5.5", "gpt-5.4"]
}
验证记录
1. 语法与本地回归测试
命令:
python3 -m py_compile [已移除本地路径] [已移除本地路径]
python3 [已移除本地路径]
结果:
ok test_chat_tool_result_and_prior_tool_call_map_to_responses_items
ok test_chat_tools_are_forwarded_to_responses_shape
ok test_responses_function_call_maps_to_chat_tool_calls
ok test_text_response_still_maps_to_chat_content
2. SharedChat 上游 function_call 探针
直接请求 https://new.sharedchat.cc/codex/v1/responses,携带 Responses tools 与强制 tool_choice,上游返回:
{
"type": "function_call",
"name": "get_current_time",
"arguments": "{\"timezone\":\"Asia/Shanghai\"}"
}
说明上游本身支持 function calling;旧问题不是上游能力缺失,而是 adapter 未桥接。
3. Adapter 本地 8329 探针
请求:
POST http://127.0.0.1:8329/v1/chat/completions
返回关键字段:
{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": "",
"tool_calls": [
{
"type": "function",
"function": {
"name": "get_current_time",
"arguments": "{\"timezone\":\"Asia/Shanghai\"}"
}
}
]
}
}
4. CPA 8317 真实链路探针
请求模型:
SC-GPT-5.5(high)
返回:
{
"status": "ok",
"first_finish": "tool_calls",
"first_has_tool_calls": true,
"tool_name": "get_current_time",
"second_finish": "stop",
"second_content": "当前上海时间是 **2026-06-02 21:40:00 CST**。"
}
这证明完整两轮 agent loop 已闭环:
- 模型发起 tool_call。
- Hermes/调用方执行工具。
- tool result 回灌给模型。
- 模型基于工具结果继续自然语言回答。
影响范围
已改善
SC-GPT-5.5(high)可以像正常 Hermes agent 模型一样使用工具。- 不再因为 adapter 丢弃 tools 而误报“没有工具”。
- CPA alias 路径不需要改,Hermes 配置不需要改。
未改变
- CPA 主服务 8317 未重启、未修改。
- Hermes WebUI 未重启、未修改。
- SharedChat 上游凭证和 base URL 未变。
- 普通文本 Chat/SSE 行为保持兼容。
风险与边界
风险 1:streaming tool_calls 不是原生 delta
当前 tools 场景下 adapter 用 non-stream upstream + synthetic SSE。这保证 Hermes tool loop 正确,但不提供真实逐 token / 逐 delta tool_call streaming。
处理建议:除非明确需要低延迟 tool_call delta,否则保持当前保守实现。
风险 2:上游 Responses 事件格式未来可能变化
当前解析兼容常见字段:
output[].type=function_callcall_idnamearguments
如果 SharedChat 上游更换 Responses 格式,需要更新 _responses_tool_calls()。
风险 3:SC 模型是否主动调用工具仍受模型策略影响
bridge 已确保工具 schema 可达,但模型是否选择调用工具仍由模型行为决定。若需要强制调用,应使用 tool_choice。
回滚方式
如果需要回滚 adapter 代码:
- 恢复
[已移除本地路径]到上一版。 - 执行:
systemctl --user restart sharedchat-codex-adapter.service
curl -fsS http://127.0.0.1:8329/health
如果只想临时绕开 SC 模型:
- Hermes 默认模型改回 CPA Codex/OAuth 主链路模型,例如
gpt-5.5。 - 或在会话中手动切换到已确认支持 tools 的模型。
后续建议
- 保留本地测试文件,后续改 adapter 时先跑:
python3 [已移除本地路径]
-
如果继续接入新的 Responses-only provider,复用这套 bridge,不要再写只转文本的最小 adapter。
-
若后续要把
SC-GPT-5.5(high)设回默认模型,建议先在 Hermes WebUI 中用真实工具任务做一次人工 smoke:例如“查本机时间/查文件/查 GitHub release”,确认模型能发起工具调用。
关键路径索引
- Adapter:
[已移除本地路径] - 回归测试:
[已移除本地路径] - systemd unit:
[已移除本地路径] - env file:
[已移除本地路径] - CPA config:
[已移除本地路径] - Adapter health:
http://127.0.0.1:8329/health - CPA endpoint:
http://127.0.0.1:8317/v1/chat/completions