将本地
opencode封装为 完全 OpenAI 兼容 API,支持流式、非流式、工具调用(tool calling)。 智能体拥有完整能力:读写文件、执行命令、调用工具等。
Reeden / Cursor / NextChat / 任何 OpenAI 客户端
│ POST /v1/chat/completions (OpenAI 格式)
│ stream: true/false, tools: [...]
▼
opencode-session-proxy (127.0.0.1:18081) ← 本仓库的核心
│ 创建 session → 发消息 → 监听 SSE 事件
▼
opencode serve (127.0.0.1:4096) ← opencode 原生 API
│ 完整智能体引擎
设计要点:
- 不用
opencode run(一次性问答,无 agent 能力) - 用
/sessionAPI +/global/eventSSE 流 → 智能体拥有完整能力 - 工具调用:拦截 OpenAI
tools→ 注入系统提示告诉 AI 用[TOOL_CALL: name] {args} [/TOOL_CALL]格式 - AI 响应中解析该格式 → 转换为 OpenAI
tool_calls格式返回 - 无自动重试:信任模型判断,未检测到
[TOOL_CALL:]时视为有效文本响应直接结束。避免因误判导致的无限循环和重复任务提交。 - 防泄漏过滤:内置三层防御机制防止系统指令泄漏到输出中(pre-prompt 提示、流式前缀检测、响应后处理)。
- Delta 超时检测:每 5s 检查一次,内容 30s 无增量则主动结束,替代固定超时。
| 组件 | 版本要求 | 说明 |
|---|---|---|
| mise | 任意 | 包管理器 |
| opencode | v1.14+ | mise install opencode@1.14.46 |
| Node.js | v18+ | 运行 proxy 脚本(可用 mise install node) |
| systemd | 有 user mode | Linux 发行版自带 |
这是基础服务,opencode 的原生 API 服务器。
mise install opencode@1.14.46
mise use -g opencode@1.14.46
opencode --version # 确认安装opencode serve --hostname 127.0.0.1 --port 4096
# Ctrl+C 终止,确认无报错即可首次运行会在
~/.opencode/下创建配置目录。 如果遇到btca CLI not found可忽略(不影响的源码搜索功能)。
mkdir -p ~/.config/systemd/user写入文件 ~/.config/systemd/user/opencode-api.service:
[Unit]
Description=Opencode API Server
After=network.target
[Service]
Type=simple
ExecStart=%h/.local/share/mise/installs/opencode/1.14.46/opencode serve --hostname 127.0.0.1 --port 4096
WorkingDirectory=%h
Restart=on-failure
RestartSec=5
Environment=HOME=%h
[Install]
WantedBy=default.target
%h是 systemd 的 home 目录变量,会自动替换。
# 重新加载 systemd
systemctl --user daemon-reload
# 启动服务
systemctl --user start opencode-api.service
# 查看状态
systemctl --user status opencode-api.service
# 设为开机自启
systemctl --user enable opencode-api.service
# 如果开机不自动启动(用户未登录时),执行:
sudo loginctl enable-linger $(whoami)# 健康检查
curl -s http://127.0.0.1:4096/health
# 应该返回类似:{"status":"ok"}这是 OpenAI 兼容适配层,直接调用 opencode 的 session API。
mise install node@latest
mise use -g node@latest
node --version # 确认 v18+核心文件是仓库里的 session-proxy.js(OpenAI 兼容代理)。
# 复制到运行目录
cp session-proxy.js ~/.opencode-cli-proxy/bin/opencode-session-proxy.js
# 或者直接下载最新版(适合远程部署)
curl -sL https://raw.githubusercontent.com/brucevon/opencode-api-deploy/main/session-proxy.js \
-o ~/.opencode-cli-proxy/bin/opencode-session-proxy.js所有配置通过环境变量设置,无需修改代码:
| 变量 | 默认值 | 说明 |
|---|---|---|
PROXY_PORT |
18081 |
proxy 监听端口 |
OPCODE_PORT |
4096 |
opencode serve 端口 |
OPCODE_HOST |
127.0.0.1 |
opencode serve 地址 |
API_KEY |
sk-gw-demo |
认证密钥 |
MODELS |
opencode/big-pickle,... |
逗号分隔的模型列表 |
写入文件 ~/.config/systemd/user/opencode-session-proxy.service:
[Unit]
Description=Opencode Session Proxy - Full agent via OpenAI API
After=network.target opencode-api.service
Wants=opencode-api.service
[Service]
Type=simple
ExecStart=%h/.local/share/mise/installs/node/latest/bin/node %h/.opencode-cli-proxy/bin/opencode-session-proxy.js
WorkingDirectory=%h
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start opencode-session-proxy.service
systemctl --user enable opencode-session-proxy.service
systemctl --user status opencode-session-proxy.service# 如果重启后服务不启动,执行:
sudo loginctl enable-linger $(whoami)确保两个服务都在运行后:
# opencode 原生 API
curl -s http://127.0.0.1:4096/health
# session proxy
curl -s http://127.0.0.1:18081/v1/models \
-H "Authorization: Bearer sk-gw-demo"curl -s --max-time 180 -X POST http://127.0.0.1:18081/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-gw-demo" \
-d '{
"model": "opencode/big-pickle",
"messages": [{"role": "user", "content": "创建一个 /tmp/proxy-test.txt 文件,写入 hello world"}],
"stream": false
}'智能体应该执行
write工具创建文件,然后返回结果。 首次请求模型需要热加载,可能耗时 60s+,后续请求正常。
curl -N --max-time 180 -X POST http://127.0.0.1:18081/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-gw-demo" \
-d '{
"model": "opencode/big-pickle",
"messages": [{"role": "user", "content": "从 1 数到 5"}],
"stream": true
}'# 非流式 + tools
curl -s --max-time 180 -X POST http://127.0.0.1:18081/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-gw-demo" \
-d '{
"model": "opencode/big-pickle",
"messages": [{"role": "user", "content": "Search for books about artificial intelligence"}],
"tools": [
{
"type": "function",
"function": {
"name": "search_books",
"description": "Search books by query",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
}
],
"stream": false
}'
# 应返回 finish_reason: "tool_calls",含 tool_calls 数组# 流式 + tools
curl -N --max-time 180 -X POST http://127.0.0.1:18081/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-gw-demo" \
-d '{
"model": "opencode/big-pickle",
"messages": [{"role": "user", "content": "Search for books about AI"}],
"tools": [
{
"type": "function",
"function": {
"name": "search_books",
"description": "Search books by query",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
}
],
"stream": true
}'
# 应输出 SSE delta 事件:
# 1. delta: {role: "assistant"}
# 2. delta: {tool_calls: [{...}]}
# 3. delta: {}, finish_reason: "tool_calls"
# 4. [DONE]# 查看状态
systemctl --user status opencode-api.service opencode-session-proxy.service
# 查看日志
journalctl --user -u opencode-session-proxy.service -f
# 重启
systemctl --user restart opencode-session-proxy.service
# 停止
systemctl --user stop opencode-session-proxy.service
# 查看 N 条最近日志
journalctl --user -u opencode-session-proxy.service --no-pager -n 50# 先看日志
journalctl --user -u opencode-session-proxy.service --no-pager -n 50
# 常见原因:
# - node 路径不对 → which node 确认路径,更新 ExecStart
# - opencode-api 没启动 → systemctl --user start opencode-api.service
# - 端口被占用 → netstat -tlnp | grep 18081API Key 不匹配。检查 session-proxy.js 中的 API_KEY 和请求头的 Authorization。
模型冷启动需要时间。重试一次即可。或者先发一个简单的 warm-up 请求:
curl -s --max-time 180 -X POST http://127.0.0.1:18081/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-gw-demo" \
-d '{"model":"opencode/big-pickle","messages":[{"role":"user","content":"hi"}],"stream":false}'opencode/big-pickle 是 agent 模型,约 40% 概率会忽略 [TOOL_CALL:] 指令,直接用内置工具在服务器执行。这种情况下响应中不含 tool_calls,客户端不会执行任何工具。
Proxy 内置了自动重试机制:检测到需要 tools 但模型没输出时,自动发送修正消息重试(同一 session,最多 3 次)。通常第二次即可正确输出 [TOOL_CALL:] 格式。
如果仍有问题,尝试:
- 重新发送请求(重试次数重置)
- 用非流式模式(
stream: false),成功率更高
确认:
- proxy 监听地址改为
0.0.0.0(在session-proxy.js中改PROXY_HOST = '0.0.0.0') - 防火墙放行 18081 端口
- 确保 API Key 匹配
编辑 session-proxy.js 开头的 PROXY_PORT 变量,然后重启服务:
systemctl --user restart opencode-session-proxy.service编辑 session-proxy.js 开头的 API_KEY 变量,重启服务。
编辑 session-proxy.js 开头的 MODELS 数组,添加模型 ID。需要确保 opencode 配置中已有该模型(opencode config)。