102 lines
7.7 KiB
JSON
102 lines
7.7 KiB
JSON
{
|
||
"module": "ocg_router",
|
||
"version": "1.0",
|
||
"purpose": "OCG 路由代理。OpenAI 兼容代理(:19878),背后池化 6 个 OpenCode Go API key,按剩余 quota 智能路由,402/429/5xx 自动故障切换。替代写死的 key3 配置,让所有 OMO 子 agent 自动使用最空闲的 key。",
|
||
"ui_location": "I Tab (Infrastructure) → OCG 路由代理 section (API 用量下方)",
|
||
|
||
"human_help": {
|
||
"title": "OCG 路由代理",
|
||
"description": [
|
||
"把 6 个 OpenCode Go key 池化成一个 OpenAI 兼容的 API 端点(:19878)。",
|
||
"每次请求自动选剩余 quota 最多的 key,用完后自动切下一个。",
|
||
"402(余额不足)、429(限流)、5xx(服务器错误) 自动标记故障 key 并切换,5 分钟后恢复。",
|
||
"取代原来写死 key3 的配置——key3 订阅已取消,不改的话所有子 agent 都会 Insufficient balance。",
|
||
"Dashboard 可以看到当前路由到哪个 key、各 key 用量、命中次数。"
|
||
],
|
||
"usage": [
|
||
"1. 确保 systemd 服务 ocg-router 在运行 (systemctl status ocg-router)",
|
||
"2. OMO 配置指向 http://192.168.1.246:19878/v1(已在 oh-my-openagent.jsonc 和 config.json 配置好)",
|
||
"3. 本区块自动每 10 秒刷新,显示当前路由 key 和池状态",
|
||
"4. 如果代理挂了,Dashboard 会显示「代理未运行」并给出错误信息",
|
||
"5. 每个 key 卡片有「启用/停用」按钮 — 停用的 key 立即从路由池移除(不再参与路由,也不出现在 /api/status 池中),启用后立即恢复。状态写入 accounts.json 的 enabled 字段"
|
||
],
|
||
"troubleshooting": [
|
||
"代理未运行 → ssh 246 systemctl restart ocg-router",
|
||
"所有 key 故障 → 检查 246 到 opencode.ai 网络是否通 (curl https://opencode.ai/zen/go/v1/models)",
|
||
"某个 key 一直在冷却中 → 等 5 分钟冷却期过去,或重启代理清冷却 (systemctl restart ocg-router)",
|
||
"当前路由 key 为空 → 代理刚启动还没收到请求,先发一个请求就会显示"
|
||
]
|
||
},
|
||
|
||
"ai_spec": {
|
||
"apis": [
|
||
{"method": "GET", "path": "http://192.168.1.246:19878/health", "returns": "{ok, time}", "proxied_to": "ocg_router.py status"},
|
||
{"method": "GET", "path": "http://192.168.1.246:19878/v1/models", "returns": "OpenAI 兼容模型列表", "proxied_to": "ocg_router.py → opencode.ai"},
|
||
{"method": "POST", "path": "http://192.168.1.246:19878/v1/chat/completions", "returns": "OpenAI 兼容响应 (含 stream)", "proxied_to": "ocg_router.py → opencode.ai"},
|
||
{"method": "GET", "path": "http://192.168.1.246:19878/api/status", "returns": "代理状态 {current_key, pool, hits}", "proxied_to": "ocg_router.py internal"},
|
||
{"method": "POST", "path": "http://192.168.1.246:19878/api/keys/toggle", "returns": "{ok, key_id, enabled, pool_size}", "proxied_to": "ocg_router.py — 写 accounts.json enabled 字段并立即 reload"},
|
||
{"method": "POST", "path": "http://192.168.1.246:19878/api/reload", "returns": "{ok, keys}", "proxied_to": "ocg_router.py — 立即重载 accounts.json/usage_stats.json"},
|
||
{"method": "GET", "path": "/api/proxy/status", "returns": "代理状态(通过 dashboard 代理)", "proxied_to": "dashboard.py → 19878"},
|
||
{"method": "POST", "path": "/api/proxy/toggle-key", "returns": "{ok, key_id, enabled, pool_size}", "proxied_to": "dashboard.py → 19878 /api/keys/toggle"}
|
||
],
|
||
"dependencies": [
|
||
"ocg_router.py — 代理核心,systemd 常驻 (:19878)",
|
||
"usage_stats.json — 每 2 分钟刷新,提供各 key 用量数据",
|
||
"accounts.json — 提供 key 列表和 API key",
|
||
"dashboard.py — /api/proxy/status 代理端点",
|
||
"dashboard.html — OCG 路由代理 section (id=proxy-router-section)",
|
||
"oh-my-openagent.jsonc — OMO 配置,所有 agent/category 指向 ocg-router",
|
||
"~/.config/opencode/config.json — ocg-router provider 定义"
|
||
],
|
||
"architecture": {
|
||
"flow": "OMO(Windows) → ocg-router(:19878, 246) → 按 usage_stats.json 选最空闲 key → opencode.ai/zen/go/v1",
|
||
"key_selection": "健康度 score = rolling%*0.6 + weekly%*0.3 + monthly%*0.1。score 最低的 key 被选中。订阅取消 score=999,故障冷却期内 score=888,用量采集失败(error) score=500(降权但可用)",
|
||
"failover": "401/402/403/429/5xx → 标记 key 故障 5 分钟 → 自动重试下一个 key",
|
||
"enable_disable": "accounts.json 每 key 支持 enabled 字段(默认 true)。enabled=false 的 key 不加入路由池:不出现在 /v1/models、/api/status、路由候选。Dashboard 卡片按钮或 POST /api/keys/toggle 可切换,立即生效",
|
||
"providers": ["ocg-key1 (staymo7777@gmail.com)", "ocg-key2 (hua65111@gmail.com)", "ocg-key3 (staymo@163.com — 订阅已取消, 不可用)", "ocg-key4 (staywithmo@163.com)", "ocg-key5 (damnedmoon@163.com)", "ocg-key6 (ycdennismo@163.com)"],
|
||
"port": "19878"
|
||
},
|
||
"constraints": [
|
||
"代理必须跑在 246 上 — usage_stats.json 在 246 本地",
|
||
"firewall: ufw allow 19878/tcp from 192.168.1.0/24",
|
||
"pid lock: proc_guard('ocg_router') — 防止重复启动",
|
||
"冷却期 300 秒 — key 被标记故障后 5 分钟自动恢复",
|
||
"用量刷新间隔 120 秒",
|
||
"User-Agent 必须用 Mozilla/5.0 — 否则 Cloudflare 1010 拦截"
|
||
],
|
||
"must_not": [
|
||
"不要把代理跑在 206 上 — 206 是阿里云,到 opencode.ai 的网络被 Cloudflare 按数据中心 IP 拦截",
|
||
"不要绕过代理直接配 ocg-key3 — key3 订阅已取消,会 Insufficient balance",
|
||
"不要改 baseURL 从 http 到 https — 内网走 HTTP 性能更好",
|
||
"不要在 Windows 本机直接拉 usage_stats.json — 数据在 246 上,代理跑 246 避免网络依赖"
|
||
],
|
||
"related_modules": [
|
||
{"module": "usage_monitor", "relation": "提供 usage_stats.json 用量数据,代理依赖它做 key 选择"},
|
||
{"module": "dashboard", "relation": "/api/proxy/status 端点代理到路由器;前端 OCG 路由代理 section 展示状态"}
|
||
],
|
||
"tests": [
|
||
{"id": "ROUTER01", "name": "GET /health returns ok", "endpoint": "GET http://192.168.1.246:19878/health"},
|
||
{"id": "ROUTER02", "name": "GET /v1/models returns model list", "endpoint": "GET http://192.168.1.246:19878/v1/models"},
|
||
{"id": "ROUTER03", "name": "POST /v1/chat/completions non-stream", "endpoint": "POST http://192.168.1.246:19878/v1/chat/completions"},
|
||
{"id": "ROUTER04", "name": "GET /api/status returns pool health", "endpoint": "GET http://192.168.1.246:19878/api/status"},
|
||
{"id": "ROUTER05", "name": "Dashboard /api/proxy/status proxies correctly", "endpoint": "GET http://192.168.1.246:5803/api/proxy/status"}
|
||
],
|
||
"known_issues": [
|
||
"Cloudflare 1010: opencode.ai API 需要真实 User-Agent(Mozilla/5.0),代理已内置",
|
||
"阿里云到 opencode.ai: 数据中心 IP 可能被 Cloudflare WAF 拦截,所以代理必须跑在 246(家庭宽带 IP)",
|
||
"key3 订阅已取消: accounts.json 已标 subscribed=false,不会出现在路由池",
|
||
"用量采集失败(usage error): 只降权不排除 — key 仍可用,只是无法按用量排序(2026-08-03 修复,避免采集超时误杀所有 key)"
|
||
],
|
||
"related_files": [
|
||
"gateway/scripts/ocg_router.py — 代理核心",
|
||
"gateway/scripts/dashboard.py — /api/proxy/status",
|
||
"gateway/scripts/templates/dashboard.html — proxy-router-section",
|
||
"gateway/scripts/specs/ocg_router.json — 本 spec 文件",
|
||
"gateway/temp/usage_stats.json — 用量数据源",
|
||
"gateway/scripts/usage_monitor/accounts.json — key 配置",
|
||
"~/.config/opencode/oh-my-openagent.jsonc — OMO 配置",
|
||
"/etc/systemd/system/ocg-router.service — systemd 服务定义"
|
||
]
|
||
}
|
||
}
|