diff --git a/gateway/scripts/specs/hermes_gateway.json b/gateway/scripts/specs/hermes_gateway.json new file mode 100644 index 0000000..7c15431 --- /dev/null +++ b/gateway/scripts/specs/hermes_gateway.json @@ -0,0 +1,50 @@ +{ + "module": "hermes_gateway", + "version": "1.0", + "purpose": "Hermes AI Gateway — 运行在 246 Linux,为每个 Hermes Agent(莫荷、知微)提供 OpenAI 兼容 API 端点。Mohe 端口 8642,Zhiwei 端口 8643。", + "ui_location": "F Tab → AI网关 → Hermes网关-莫荷 / Hermes网关-知微", + + "human_help": { + "title": "Hermes AI 网关", + "description": [ + "这是 Hermes Agent 的 API 服务器,提供 OpenAI 兼容的 /v1/chat/completions 接口。", + "每个 Hermes Agent 对应一个独立的实例:莫荷(8642)和知微(8643)。", + "Gateway 负责接收 LLM 请求、管理 session 上下文、调用底层 AI Provider。", + "所有 Agent 间的消息路由和 AI 处理都通过 Hermes Gateway 完成。" + ], + "usage": [ + "状态在 F Tab 的 AI网关 层查看,健康检查通过 /v1/health 端点检测。", + "如果状态 stopped:检查 systemd 服务 hermes-gateway@mohe 或 hermes-gateway@zhiwei", + "查看日志:journalctl -u hermes-gateway@mohe -n 50 --no-pager" + ], + "troubleshooting": [ + "如果 Hermes 不回复消息:检查 Gateway 进程是否运行 — curl http://127.0.0.1:8642/v1/models", + "如果 session 上下文丢失:检查是否误开了 session 自动重置(正常应关闭)", + "如果 Provider 报错:检查 ~/.hermes/config.yaml 中的 provider 配置是否正确" + ], + "related": "依赖 ejabberd XMPP 服务器进行 Agent 间通信;依赖 AI Provider(如 ocg-new、volcengine)进行 LLM 推理" + }, + + "ai_spec": { + "apis": [ + {"method": "GET", "path": "/v1/models", "returns": "模型列表", "desc": "查询可用模型"}, + {"method": "GET", "path": "/v1/health", "returns": "{ok, version, uptime}", "desc": "健康检查"}, + {"method": "POST", "path": "/v1/chat/completions", "body": "OpenAI chat completion 格式", "returns": "OpenAI 格式响应", "desc": "LLM 推理主端点"} + ], + "dependencies": [ + "ejabberd 192.168.1.246:5222 — XMPP 服务器", + "AI Provider 配置 (ocg-new / volcengine)", + "~/.hermes/config.yaml — 主配置" + ], + "constraints": [ + "每个 Gateway 实例绑定唯一端口(8642/8643),不可共享", + "sisyphus session 永不自动重置,api_server session 可能自动重置", + "Gateway 必须通过 systemd 管理(hermes-gateway@.service 模板)" + ], + "related_files": [ + "~/.hermes/config.yaml — 主配置", + "deploy/linux/hermes-gateway@.service — systemd 模板", + "gateway/scripts/specs/hermes_gateway.json — 本 spec" + ] + } +} diff --git a/gateway/scripts/specs/omlx_server.json b/gateway/scripts/specs/omlx_server.json new file mode 100644 index 0000000..720bae2 --- /dev/null +++ b/gateway/scripts/specs/omlx_server.json @@ -0,0 +1,46 @@ +{ + "module": "omlx_server", + "version": "1.0", + "purpose": "OMLX 推理服务 — 运行在小果(Mac 192.168.1.122:18003),提供本地 LLM 推理能力。通过 OMLX 框架加载本地模型,为 Agent 提供低延迟推理。", + "ui_location": "F Tab → AI网关 → OMLX推理服务(小果)", + + "human_help": { + "title": "OMLX 本地推理服务", + "description": [ + "小果(Mac Mini)上运行的本地推理服务,使用 OMLX 框架加载 GGUF 格式的本地模型。", + "提供 OpenAI 兼容接口,延迟低、无需网络、不消耗云端配额。", + "适合轻量推理、快速响应场景;复杂推理仍走云 Provider。" + ], + "usage": [ + "状态在 F Tab 的 AI网关 层查看(小果的远程服务标记为 remote)", + "Dashboard 运行在 246 Linux,无法直接检测 Mac 端口 → 通过 ejabberd 在线状态推断" + ], + "troubleshooting": [ + "如果 OMLX 服务不可达:检查小果的 omlx_server 进程是否运行", + "如果 Mac 离线:检查 EasyTier VPN 是否连通", + "日志在小果本地:~/omlx/server.log" + ], + "related": "依赖 EasyTier VPN 连通 246 ↔ Mac;依赖本地 GGUF 模型文件" + }, + + "ai_spec": { + "apis": [ + {"method": "GET", "path": "/v1/health", "returns": "{ok, model_loaded}", "desc": "健康检查 + 模型加载状态"}, + {"method": "POST", "path": "/v1/chat/completions", "body": "OpenAI chat completion 格式", "returns": "OpenAI 格式响应", "desc": "本地 LLM 推理"} + ], + "dependencies": [ + "EasyTier VPN — 跨平台网络", + "本地 GGUF 模型文件", + "OMLX 框架" + ], + "constraints": [ + "仅能在 Mac(192.168.1.122)上运行", + "首次加载模型较慢(冷启动)", + "Dashboard 只能通过 XMPP 在线状态间接监控" + ], + "related_files": [ + "gateway/scripts/specs/omlx_server.json — 本 spec", + "config/agents.yaml — agent-003 定义" + ] + } +} diff --git a/gateway/scripts/templates/dashboard.html b/gateway/scripts/templates/dashboard.html index 34c4de3..accb850 100644 --- a/gateway/scripts/templates/dashboard.html +++ b/gateway/scripts/templates/dashboard.html @@ -168,13 +168,14 @@ async function fHealth(){try{ M.wechat_bridge={n:'莫荷微信桥接',l:'通信层',i:'微信消息收发中断',spec:'wechat_bridge'}; M.article_processor={n:'文章抓取服务',l:'辅助服务',i:'微信长文章无法读取',spec:'article_processor'}; // 兼容层:/api/services 返回的旧名称仍然映射到友好标签 - M.xmpp_bot={n:'XMPP消息收发',l:'通信层',i:'消息收发中断'}; - M.hermes_gateway={n:'Hermes网关',l:'AI网关',i:'Hermes Agent不可用'}; + M.xmpp_bot={n:'XMPP消息收发',l:'通信层',i:'消息收发中断',spec:'xmpp_bot'}; + M.hermes_gateway={n:'Hermes网关',l:'AI网关',i:'Hermes Agent不可用',spec:'hermes_gateway'}; M.ejabberd={n:'XMPP服务器',l:'通信层',i:'所有XMPP连接不可用'}; - M.gateway_mohe={n:'Gateway-莫荷',l:'AI网关',i:'莫荷智能体不可用'}; - M.gateway_zhiwei={n:'Gateway-知微',l:'AI网关',i:'知微智能体不可用'}; - M.dashboard={n:'管理门户',l:'辅助服务',i:'Dashboard无法访问'}; + M.gateway_mohe={n:'Gateway-莫荷',l:'AI网关',i:'莫荷智能体不可用',spec:'hermes_gateway'}; + M.gateway_zhiwei={n:'Gateway-知微',l:'AI网关',i:'知微智能体不可用',spec:'hermes_gateway'}; + M.dashboard={n:'管理门户',l:'辅助服务',i:'Dashboard无法访问',spec:'dashboard'}; M.watchdog={n:'进程看门狗',l:'辅助服务',i:'异常进程无自动恢复'}; + M.ejabberd={n:'XMPP服务器',l:'通信层',i:'所有XMPP连接不可用',spec:'ejabberd'}; M['agents-health-check']={n:'健康检查(5min)',l:'定时任务',i:'5分钟级健康检测未运行'}; M['agents-daily-health']={n:'日报健康检查(每日)',l:'定时任务',i:'日报统计未运行'}; var layerOrder=['通信层','AI网关','辅助服务','定时任务']; @@ -236,7 +237,8 @@ async function fHealth(){try{ var rawN=(M[s.name]||{}).n||s.name; if(!layers[rawL])layers[rawL]=[]; var hStatus=s.health&&s.health.ok?'running':'down'; - layers[rawL].push({name:s.name,label:rawN,port:s.port,status:hStatus,critical:false});}} + var mSpec=(M[s.name]||{}).spec||''; + layers[rawL].push({name:s.name,label:rawN,port:s.port,status:hStatus,critical:false,spec:mSpec});}} h+='

全部服务

'; for(var li=0;li