fix: F Tab unique keys per instance + spec buttons + dedup + naming rules
This commit is contained in:
@@ -975,9 +975,10 @@ def api_expected():
|
||||
if bot_type == "hermes" and svc_type == "xmpp_bot":
|
||||
continue
|
||||
port = svc.get("port")
|
||||
# key 供前端 M 映射表查找友好标签
|
||||
key = svc_type
|
||||
entry = {"name": f"{display}({host}):{svc_type}", "key": key, "host": host, "expected": "running", "critical": True}
|
||||
# key 供前端 M 映射表查找唯一标签(实例级,不按类型折叠)
|
||||
key = f"{agent['id']}:{svc_type}"
|
||||
spec = svc_type # spec 模块名,供 ?§ 按钮链接 specs/{module}.json
|
||||
entry = {"name": f"{display}({host}):{svc_type}", "key": key, "spec": spec, "host": host, "expected": "running", "critical": True}
|
||||
if port:
|
||||
entry["port"] = port
|
||||
entry["check"] = "tcp"
|
||||
@@ -990,7 +991,7 @@ def api_expected():
|
||||
|
||||
# 2. 从 PLATFORM_SERVICES 生成平台服务的期望
|
||||
for ps in PLATFORM_SERVICES:
|
||||
entry = {"name": f"{ps['name']} ({ps['id']})", "key": ps["id"], "host": ps.get("host", "127.0.0.1"), "expected": "running", "critical": True}
|
||||
entry = {"name": f"{ps['name']} ({ps['id']})", "key": ps["id"], "spec": ps["id"], "host": ps.get("host", "127.0.0.1"), "expected": "running", "critical": True}
|
||||
if ps.get("health_url"):
|
||||
entry["health_url"] = ps["health_url"]
|
||||
entry["check"] = "health_url"
|
||||
|
||||
@@ -158,14 +158,21 @@ async function fL(id){var el=qs('lc-'+id);if(!el||!L.has(id))return;try{var r=aw
|
||||
async function fHealth(){try{
|
||||
// Helpers
|
||||
function isHealthy(st){return st==='running'||st==='online'||(st&&st.indexOf('remote')===0);}
|
||||
// Service metadata: label / layer / impact
|
||||
// Service metadata: label / layer / impact (per-instance key → metadata)
|
||||
var M={};
|
||||
M['agent-001:xmpp_bot']={n:'研发助理-XMPP Bot',l:'通信层',i:'小小莫(Windows)XMPP 消息收发中断',spec:'xmpp_bot'};
|
||||
M['agent-002:hermes_gateway']={n:'Hermes网关-莫荷',l:'AI网关',i:'莫荷智能体(246 Linux)不可用',spec:'hermes_gateway'};
|
||||
M['agent-003:xmpp_bot']={n:'本地推理-XMPP Bot',l:'通信层',i:'小果(Mac)XMPP 消息收发中断',spec:'xmpp_bot'};
|
||||
M['agent-003:omlx_server']={n:'OMLX推理服务(小果)',l:'AI网关',i:'小果(Mac)本地推理服务不可用',spec:'omlx_server'};
|
||||
M['agent-004:hermes_gateway']={n:'Hermes网关-知微',l:'AI网关',i:'知微智能体(246 Linux)不可用',spec:'hermes_gateway'};
|
||||
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.ejabberd={n:'XMPP服务器',l:'通信层',i:'所有XMPP连接不可用'};
|
||||
M.xmpp_bot={n:'XMPP消息收发',l:'通信层',i:'所有Agent消息收发中断'};
|
||||
M.hermes_gateway={n:'Hermes AI网关',l:'AI网关',i:'Hermes Agent不可用'};
|
||||
M.article_processor={n:'微信全文抓取',l:'辅助服务',i:'微信长文章无法读取'};
|
||||
M.wechat_bridge={n:'莫荷微信桥接',l:'通信层',i:'微信消息收发中断'};
|
||||
M.omlx_server={n:'OMLX推理服务',l:'AI网关',i:'本地推理服务不可用'};
|
||||
M.gateway_mohe={n:'Gateway-莫荷',l:'AI网关',i:'莫荷智能体不可用'};
|
||||
M.gateway_zhiwei={n:'Gateway-知微',l:'AI网关',i:'知微智能体不可用'};
|
||||
M.dashboard={n:'管理门户',l:'辅助服务',i:'Dashboard无法访问'};
|
||||
M.watchdog={n:'进程看门狗',l:'辅助服务',i:'异常进程无自动恢复'};
|
||||
M['agents-health-check']={n:'健康检查(5min)',l:'定时任务',i:'5分钟级健康检测未运行'};
|
||||
@@ -217,10 +224,12 @@ async function fHealth(){try{
|
||||
var layers={};
|
||||
var added={};
|
||||
for(var i=0;i<exp.length;i++){var e=exp[i];
|
||||
var ma=M[e.key||e.name]||{n:e.name,l:'辅助服务',i:''};
|
||||
var ma=M[e.key||e.name]||{n:e.name,l:'辅助服务',i:'',spec:''};
|
||||
var ly=ma.l||'其他';
|
||||
if(!layers[ly])layers[ly]=[];added[e.name]=true;
|
||||
layers[ly].push({name:e.name,label:ma.n,port:e.port,status:isHealthy(act[e.name])?'running':act[e.name],critical:e.critical});}
|
||||
if(!layers[ly])layers[ly]=[];
|
||||
added[e.name]=true;
|
||||
if(e.key) added[e.key]=true; // 同时标记 key,防止 services 同名重复
|
||||
layers[ly].push({name:e.name,label:ma.n,port:e.port,status:isHealthy(act[e.name])?'running':act[e.name],critical:e.critical,spec:ma.spec||e.spec||''});}
|
||||
for(var i=0;i<svcs.length;i++){var s=svcs[i];
|
||||
if(!added[s.name]){
|
||||
var rawL=(M[s.name]||{}).l||(s.type==='infra'?'通信层':s.type==='gateway'?'AI网关':'辅助服务');
|
||||
@@ -239,6 +248,8 @@ async function fHealth(){try{
|
||||
h+='<span class="sd '+(run?'g':'r')+'"></span>';
|
||||
h+='<span style=flex:1>'+esc(it.label)+'</span>';
|
||||
if(it.port)h+='<span style=color:var(--dim);font-size:18px>:'+it.port+'</span>';
|
||||
if(it.spec){h+='<span class="help-btn" onclick="showModuleHelp(\''+it.spec+'\',\'human\')" title="使用说明">?</span>';
|
||||
h+='<span class="help-btn ai" onclick="showModuleHelp(\''+it.spec+'\',\'ai\')" title="AI Spec">§</span>';}
|
||||
h+='<span class="tag '+(run?'g':'r')+'">'+(run?'运行中':esc(it.status))+'</span>';
|
||||
h+='</div>';}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user