Phase 1-4: Real data pipeline, module navigation, dual-env deploy, homepage renovation
- Replace all hardcoded/placeholder data in docs/index.html with real GitHub API fetches - Add system-health.json, bulletin-board.json, federation-status, telemetry loading - Update skyeye panel to show real system health data - Update announcements to show real bulletin-board.json data - Add brain panel with real system metrics and telemetry - Add environment detection (staging/production/local) - Add staging watermark for GitHub Pages preview - Update module navigation with correct paths and readiness status - Add sidebar navigation links to status-board and ticket-system - Create preview-deploy.yml for GitHub Pages auto-deploy - Update deploy-to-server.yml with production environment injection - Create skyeye scan report at data/skyeye-reports/latest.json Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/0ee19d81-920c-4a36-a4c4-8238f242afb5
This commit is contained in:
parent
4cd8e122a4
commit
ce09a92b90
|
|
@ -221,6 +221,18 @@ jobs:
|
||||||
|
|
||||||
echo "✅ 全站同步完成"
|
echo "✅ 全站同步完成"
|
||||||
|
|
||||||
|
- name: 🌐 注入生产环境标识
|
||||||
|
run: |
|
||||||
|
echo "🌐 Setting HOLOLAKE_ENV=production on server..."
|
||||||
|
ssh -i ~/.ssh/deploy_key \
|
||||||
|
"${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
||||||
|
DP='${{ secrets.DEPLOY_PATH }}'
|
||||||
|
# Create environment config file for frontend detection
|
||||||
|
echo '{\"env\":\"production\",\"domain\":\"guanghulab.com\",\"deployed_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"commit\":\"${{ github.sha }}\"}' > \"\$DP/docs/env.json\"
|
||||||
|
echo '{\"env\":\"production\",\"domain\":\"guanghulab.com\",\"deployed_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"commit\":\"${{ github.sha }}\"}' > \"\$DP/env.json\"
|
||||||
|
"
|
||||||
|
echo "✅ 环境标识已注入"
|
||||||
|
|
||||||
- name: 📄 复制首页到站点根目录
|
- name: 📄 复制首页到站点根目录
|
||||||
run: |
|
run: |
|
||||||
echo "📄 复制 docs/index.html → 站点根目录 index.html"
|
echo "📄 复制 docs/index.html → 站点根目录 index.html"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
# ═══════════════════════════════════════════════
|
||||||
|
# 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
|
||||||
|
# 📜 Copyright: 国作登字-2026-A-00037559
|
||||||
|
# ═══════════════════════════════════════════════
|
||||||
|
name: "🧪 Preview Deploy · GitHub Pages"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'frontend/**'
|
||||||
|
- 'status-board/**'
|
||||||
|
- 'ticket-system/**'
|
||||||
|
- 'notification/**'
|
||||||
|
- 'dynamic-comic-studio/**'
|
||||||
|
- 'user-center/**'
|
||||||
|
- 'persona-studio/frontend/**'
|
||||||
|
- 'data/bulletin-board.json'
|
||||||
|
- 'data/system-health.json'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: preview-pages
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy-preview:
|
||||||
|
name: "🧪 Build & Deploy Preview"
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 📥 Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🔧 Setup Pages
|
||||||
|
uses: actions/configure-pages@v5
|
||||||
|
|
||||||
|
- name: 🏗️ Build preview site
|
||||||
|
run: |
|
||||||
|
echo "[PREVIEW] Building site for GitHub Pages..."
|
||||||
|
echo "[PREVIEW] Injecting environment marker..."
|
||||||
|
|
||||||
|
# Sync Persona Studio frontend into docs
|
||||||
|
mkdir -p docs/persona-studio
|
||||||
|
if [ -d "persona-studio/frontend" ]; then
|
||||||
|
cp -r persona-studio/frontend/* docs/persona-studio/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync status-board into docs for GitHub Pages access
|
||||||
|
if [ -d "status-board" ]; then
|
||||||
|
mkdir -p docs/status-board
|
||||||
|
cp -r status-board/* docs/status-board/ 2>/dev/null || true
|
||||||
|
[ -d "docs/status-board/node_modules" ] && rm -rf docs/status-board/node_modules
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync ticket-system
|
||||||
|
if [ -d "ticket-system" ]; then
|
||||||
|
mkdir -p docs/ticket-system
|
||||||
|
cp -r ticket-system/* docs/ticket-system/ 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync notification
|
||||||
|
if [ -d "notification" ]; then
|
||||||
|
mkdir -p docs/notification
|
||||||
|
cp -r notification/* docs/notification/ 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync dynamic-comic-studio
|
||||||
|
if [ -d "dynamic-comic-studio" ]; then
|
||||||
|
mkdir -p docs/dynamic-comic-studio
|
||||||
|
cp -r dynamic-comic-studio/* docs/dynamic-comic-studio/ 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync dashboard data
|
||||||
|
if [ -d "data" ]; then
|
||||||
|
mkdir -p docs/data
|
||||||
|
cp data/system-health.json docs/data/ 2>/dev/null || true
|
||||||
|
cp data/bulletin-board.json docs/data/ 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Preview build complete"
|
||||||
|
|
||||||
|
- name: 📦 Upload Pages artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: docs/
|
||||||
|
|
||||||
|
- name: 🚀 Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
|
|
||||||
|
- name: 📝 Summary
|
||||||
|
run: |
|
||||||
|
echo "### 🧪 Preview Deploy Complete" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Environment:** Staging (GitHub Pages)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **URL:** ${{ steps.deployment.outputs.page_url }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
{
|
||||||
|
"schema_version": "1.0",
|
||||||
|
"scan_id": "SKYEYE-FULLSITE-2026-0325",
|
||||||
|
"timestamp": "2026-03-25T07:22:00Z",
|
||||||
|
"overall_status": "healthy",
|
||||||
|
"summary": {
|
||||||
|
"total_modules": 10,
|
||||||
|
"deployable": 4,
|
||||||
|
"needs_fix": 3,
|
||||||
|
"unavailable": 3,
|
||||||
|
"workflows": 97,
|
||||||
|
"guards": 7,
|
||||||
|
"agents": 94
|
||||||
|
},
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "状态看板",
|
||||||
|
"path": "status-board/",
|
||||||
|
"dev": "DEV-005",
|
||||||
|
"readiness": "deployable",
|
||||||
|
"notes": "可直接嵌入主页"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "工单系统",
|
||||||
|
"path": "ticket-system/",
|
||||||
|
"dev": "DEV-010",
|
||||||
|
"readiness": "deployable",
|
||||||
|
"notes": "前端完整,localStorage 持久化"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "动态漫画工作室",
|
||||||
|
"path": "dynamic-comic-studio/",
|
||||||
|
"dev": "DEV-010",
|
||||||
|
"readiness": "deployable",
|
||||||
|
"notes": "Canvas 动画编辑器可用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "通知中心",
|
||||||
|
"path": "notification/",
|
||||||
|
"dev": "DEV-012",
|
||||||
|
"readiness": "needs_fix",
|
||||||
|
"notes": "占位页面,需补充前端组件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "用户中心",
|
||||||
|
"path": "user-center/",
|
||||||
|
"dev": "DEV-009",
|
||||||
|
"readiness": "needs_fix",
|
||||||
|
"notes": "仅有 README,需补充前端页面"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "前端登录",
|
||||||
|
"path": "frontend/",
|
||||||
|
"dev": "DEV-002",
|
||||||
|
"readiness": "needs_fix",
|
||||||
|
"notes": "占位页面,需对接真实验证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "设置",
|
||||||
|
"path": "settings/",
|
||||||
|
"dev": "DEV-003",
|
||||||
|
"readiness": "unavailable",
|
||||||
|
"notes": "仅有 README"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "云盘",
|
||||||
|
"path": "cloud-drive/",
|
||||||
|
"dev": "DEV-003",
|
||||||
|
"readiness": "unavailable",
|
||||||
|
"notes": "仅有 README"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "码字台",
|
||||||
|
"path": "writing-workspace/",
|
||||||
|
"dev": "DEV-011",
|
||||||
|
"readiness": "unavailable",
|
||||||
|
"notes": "目录不存在"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "后端中间层",
|
||||||
|
"path": "backend/",
|
||||||
|
"dev": "DEV-001",
|
||||||
|
"readiness": "deployable",
|
||||||
|
"notes": "Express 服务,需服务器端运行"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fake_data_points": [
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:544",
|
||||||
|
"element": "#bbc",
|
||||||
|
"current": "⏳ 加载大脑…",
|
||||||
|
"fix": "已替换为真实 system-health.json 数据"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:551",
|
||||||
|
"element": "#skyeye-status",
|
||||||
|
"current": "加载中…",
|
||||||
|
"fix": "已替换为真实 system-health.json 数据"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:596",
|
||||||
|
"element": "#rsb",
|
||||||
|
"current": "正在加载团队数据…",
|
||||||
|
"fix": "已替换为真实 dev-status.json 数据"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:677",
|
||||||
|
"element": "#bpb",
|
||||||
|
"current": "正在加载大脑数据…",
|
||||||
|
"fix": "已替换为真实 memory.json 数据"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:776",
|
||||||
|
"element": "#tpb",
|
||||||
|
"current": "正在加载团队数据…",
|
||||||
|
"fix": "已替换为真实 dev-status.json 数据"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "docs/index.html:1073-1076",
|
||||||
|
"element": "announcements",
|
||||||
|
"current": "硬编码公告",
|
||||||
|
"fix": "已替换为真实 bulletin-board.json 数据"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
231
docs/index.html
231
docs/index.html
|
|
@ -356,6 +356,8 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
||||||
.exec-btn-submit{background:var(--accent);color:#fff}
|
.exec-btn-submit{background:var(--accent);color:#fff}
|
||||||
.exec-btn-submit:hover{opacity:.85}
|
.exec-btn-submit:hover{opacity:.85}
|
||||||
.exec-btn-submit:disabled{opacity:.5;cursor:not-allowed}
|
.exec-btn-submit:disabled{opacity:.5;cursor:not-allowed}
|
||||||
|
/* Staging environment watermark */
|
||||||
|
.staging-watermark{position:fixed;top:0;left:0;right:0;z-index:9999;background:rgba(251,191,36,.12);border-bottom:2px solid rgba(251,191,36,.5);padding:4px 12px;text-align:center;font-size:11px;color:#fbbf24;pointer-events:none}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -485,7 +487,9 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
||||||
<nav class="ls-nav">
|
<nav class="ls-nav">
|
||||||
<button class="nav-tab active" data-view="announcements" onclick="navigateTo('announcements')">📢 公告栏</button>
|
<button class="nav-tab active" data-view="announcements" onclick="navigateTo('announcements')">📢 公告栏</button>
|
||||||
<button class="nav-tab" data-view="chat" onclick="navigateTo('chat')">💬 聊天</button>
|
<button class="nav-tab" data-view="chat" onclick="navigateTo('chat')">💬 聊天</button>
|
||||||
<button class="nav-tab" onclick="window.open('../persona-studio/frontend/index.html','_blank')">🧠 Persona Studio</button>
|
<button class="nav-tab" onclick="window.open('../persona-studio/frontend/index.html','_blank')">🧠 Studio</button>
|
||||||
|
<button class="nav-tab" onclick="window.open('../status-board/','_blank')">📊 看板</button>
|
||||||
|
<button class="nav-tab" onclick="window.open('../ticket-system/','_blank')">🎫 工单</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<button class="ls-new-conv" onclick="newConvAndNav()">+ 新对话</button>
|
<button class="ls-new-conv" onclick="newConvAndNav()">+ 新对话</button>
|
||||||
|
|
@ -904,6 +908,10 @@ const A = {
|
||||||
devStatus: null,
|
devStatus: null,
|
||||||
notionProfile: null,
|
notionProfile: null,
|
||||||
skyeyeReport: null,
|
skyeyeReport: null,
|
||||||
|
systemHealth: null,
|
||||||
|
bulletinBoard: null,
|
||||||
|
federationStatus: null,
|
||||||
|
telemetrySummary: null,
|
||||||
msgs: [],
|
msgs: [],
|
||||||
currentConvId: null,
|
currentConvId: null,
|
||||||
currentView: 'announcements',
|
currentView: 'announcements',
|
||||||
|
|
@ -916,6 +924,17 @@ const A = {
|
||||||
userMeta: null,
|
userMeta: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════
|
||||||
|
// ENVIRONMENT DETECTION (staging vs production)
|
||||||
|
// ═══════════════════════════════════════════════════════
|
||||||
|
const HOLOLAKE_ENV = (function(){
|
||||||
|
const host = window.location.hostname;
|
||||||
|
if(host === 'guanghulab.com' || host === 'www.guanghulab.com') return 'production';
|
||||||
|
if(host.includes('github.io')) return 'staging';
|
||||||
|
return 'local';
|
||||||
|
})();
|
||||||
|
window.HOLOLAKE_ENV = HOLOLAKE_ENV;
|
||||||
|
|
||||||
function ls(k){return localStorage.getItem(k)}
|
function ls(k){return localStorage.getItem(k)}
|
||||||
function lss(k,v){localStorage.setItem(k,v)}
|
function lss(k,v){localStorage.setItem(k,v)}
|
||||||
|
|
||||||
|
|
@ -1067,13 +1086,31 @@ function renderAnnouncements(){
|
||||||
const c=b.stats?.coverage||FB_COV;
|
const c=b.stats?.coverage||FB_COV;
|
||||||
const evs=(b.events||[]).slice(-5).reverse();
|
const evs=(b.events||[]).slice(-5).reverse();
|
||||||
const meta=A.userMeta;
|
const meta=A.userMeta;
|
||||||
|
const bb=A.bulletinBoard;
|
||||||
|
const sh=A.systemHealth;
|
||||||
|
const fs=A.federationStatus;
|
||||||
|
const tl=A.telemetrySummary;
|
||||||
|
|
||||||
let h='';
|
let h='';
|
||||||
// System announcements
|
|
||||||
|
// Environment watermark
|
||||||
|
if(HOLOLAKE_ENV==='staging'){
|
||||||
|
h+='<div style="background:rgba(251,191,36,.15);border:1px solid rgba(251,191,36,.4);border-radius:8px;padding:8px 12px;margin-bottom:12px;font-size:12px;color:var(--warn);text-align:center">⚠️ 预览测试环境(Staging) · 非正式站</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// System announcements — use real bulletin-board.json data
|
||||||
h+='<div class="ann-section"><div class="ann-section-title">📢 系统公告</div><div class="ann-card">';
|
h+='<div class="ann-section"><div class="ann-section-title">📢 系统公告</div><div class="ann-card">';
|
||||||
h+='<div class="ann-item">🔗 全链路自动化闭环上线 — CI/CD、广播分发、唤醒协议、PSP 巡检</div>';
|
if(bb&&bb.announcements&&bb.announcements.length>0){
|
||||||
h+='<div class="ann-item">🧠 AGE OS v0.1 人格语言操作系统构建中</div>';
|
bb.announcements.forEach(function(ann){
|
||||||
h+='<div class="ann-item">📊 HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+')</div>';
|
h+='<div class="ann-item">'+(ann.emoji||'📌')+' '+esc(ann.title||'')+'<span class="ann-date">'+esc(ann.date||'')+'</span></div>';
|
||||||
|
if(ann.detail) h+='<div style="font-size:11px;color:var(--dim);padding:2px 0 6px 24px">'+esc(ann.detail)+'</div>';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Fallback to hardcoded if bulletin-board not loaded
|
||||||
|
h+='<div class="ann-item">🔗 全链路自动化闭环上线 — CI/CD、广播分发、唤醒协议、PSP 巡检</div>';
|
||||||
|
h+='<div class="ann-item">🧠 AGE OS v0.1 人格语言操作系统构建中</div>';
|
||||||
|
h+='<div class="ann-item">📊 HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+')</div>';
|
||||||
|
}
|
||||||
if(evs.length){
|
if(evs.length){
|
||||||
evs.forEach(function(ev){
|
evs.forEach(function(ev){
|
||||||
h+='<div class="ann-item">📌 '+esc(ev.title||ev.type||'事件')+'<span class="ann-date">'+(ev.timestamp||'').slice(0,10)+'</span></div>';
|
h+='<div class="ann-item">📌 '+esc(ev.title||ev.type||'事件')+'<span class="ann-date">'+(ev.timestamp||'').slice(0,10)+'</span></div>';
|
||||||
|
|
@ -1081,6 +1118,35 @@ function renderAnnouncements(){
|
||||||
}
|
}
|
||||||
h+='</div></div>';
|
h+='</div></div>';
|
||||||
|
|
||||||
|
// System health panel — real data from system-health.json
|
||||||
|
if(sh){
|
||||||
|
h+='<div class="ann-section"><div class="ann-section-title">🦅 天眼 · 系统健康</div><div class="ann-card">';
|
||||||
|
const m=sh.metrics||{};
|
||||||
|
const sc=sh.last_skyeye_scan||{};
|
||||||
|
h+='<div class="ann-item">🟢 系统状态:'+(sh.system_status==='healthy'?'✅ 健康':sh.system_status==='warning'?'⚠️ 警告':'❌ 异常')+'</div>';
|
||||||
|
h+='<div class="ann-item">⚙️ 工作流:'+(m.workflows?.total||0)+' 个 · 活跃 '+(m.workflows?.active||0)+'</div>';
|
||||||
|
h+='<div class="ann-item">🤖 Agent:'+(m.agents?.total||0)+' 个</div>';
|
||||||
|
h+='<div class="ann-item">🛡️ 守卫:'+(m.guards?.active||0)+'/'+(m.guards?.total||0)+' 活跃</div>';
|
||||||
|
h+='<div class="ann-item">🧬 本体论:'+(m.ontology_version||'v1.0')+' · 神经系统:'+(m.neural_system_version||'v3.0')+'</div>';
|
||||||
|
if(sc.id) h+='<div class="ann-item">🔍 最近扫描:'+esc(sc.id)+' · 问题 '+(sc.issues||0)+' · 警告 '+(sc.warnings||0)+'</div>';
|
||||||
|
if(sh.hibernation) h+='<div class="ann-item">🌙 休眠:'+esc(sh.hibernation.next_daily||'')+' · '+esc(sh.hibernation.next_weekly||'')+'</div>';
|
||||||
|
h+='</div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persona telemetry panel
|
||||||
|
if(tl){
|
||||||
|
h+='<div class="ann-section"><div class="ann-section-title">📡 铸渊遥测</div><div class="ann-card">';
|
||||||
|
const ps=tl.persona_state||{};
|
||||||
|
h+='<div class="ann-item">🧠 活跃人格:'+esc(ps.active_persona||'铸渊')+' · '+esc(ps.style_profile||'')+'</div>';
|
||||||
|
h+='<div class="ann-item">📊 24h 会话:'+(tl.sessions?.total_24h||0)+' 次 · '+(tl.sessions?.total_messages||0)+' 条消息</div>';
|
||||||
|
const rh=tl.repo_health||{};
|
||||||
|
h+='<div class="ann-item">📈 HLI 覆盖:'+(rh.hli_coverage||c.implemented+'/'+c.total)+' · 团队 '+(rh.total_team_members||0)+' 人</div>';
|
||||||
|
if(tl.alerts&&tl.alerts.length>0){
|
||||||
|
tl.alerts.forEach(function(a){ h+='<div class="ann-item" style="color:var(--warn)">⚠️ '+esc(a)+'</div>'; });
|
||||||
|
}
|
||||||
|
h+='</div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
// My tasks
|
// My tasks
|
||||||
if(meta){
|
if(meta){
|
||||||
h+='<div class="ann-section"><div class="ann-section-title">📋 我的待办</div><div class="ann-card">';
|
h+='<div class="ann-section"><div class="ann-section-title">📋 我的待办</div><div class="ann-card">';
|
||||||
|
|
@ -1106,30 +1172,26 @@ function renderAnnouncements(){
|
||||||
h+='<button class="ann-action-btn" onclick="navigateAndSend(\'帮我写一个 HLI 接口\')">📦 上传模块</button>';
|
h+='<button class="ann-action-btn" onclick="navigateAndSend(\'帮我写一个 HLI 接口\')">📦 上传模块</button>';
|
||||||
h+='</div></div>';
|
h+='</div></div>';
|
||||||
|
|
||||||
// Module navigation — 模块入口导航
|
// Module navigation — real modules with correct paths
|
||||||
h+='<div class="ann-section"><div class="ann-section-title">🗂️ 模块导航</div><div class="ann-actions" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px">';
|
h+='<div class="ann-section"><div class="ann-section-title">🗂️ 模块导航</div><div class="ann-actions" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px">';
|
||||||
var modules=[
|
var modules=[
|
||||||
{icon:'📊',name:'系统状态看板',path:'/status-board/'},
|
{icon:'📊',name:'状态看板',path:'../status-board/',dev:'DEV-005',ready:true},
|
||||||
{icon:'💰',name:'成本控制',path:'/cost-control/'},
|
{icon:'🎫',name:'工单系统',path:'../ticket-system/',dev:'DEV-010',ready:true},
|
||||||
{icon:'🖥️',name:'开发者看板',path:'/devboard/'},
|
{icon:'📈',name:'数据统计',path:'../data-stats/',dev:'DEV-010',ready:false},
|
||||||
{icon:'🌊',name:'光湖集成壳',path:'/app/'},
|
{icon:'🔔',name:'通知中心',path:'../notification/',dev:'DEV-012',ready:true},
|
||||||
{icon:'🧠',name:'Persona Studio',path:'/persona-studio/'},
|
{icon:'👤',name:'用户中心',path:'../user-center/',dev:'DEV-009',ready:false},
|
||||||
{icon:'👤',name:'用户中心',path:'/m05-user-center/'},
|
{icon:'⚙️',name:'设置',path:'../settings/',dev:'DEV-003',ready:false},
|
||||||
{icon:'💬',name:'对话界面',path:'/m07-dialogue-ui/'},
|
{icon:'☁️',name:'云盘',path:'../cloud-drive/',dev:'DEV-003',ready:false},
|
||||||
{icon:'☁️',name:'云服务',path:'/m10-cloud/'},
|
{icon:'✍️',name:'码字台',path:'../writing-workspace/',dev:'DEV-011',ready:false},
|
||||||
{icon:'📦',name:'模块管理',path:'/m11-module/'},
|
{icon:'🎨',name:'动态漫画',path:'../dynamic-comic-studio/',dev:'DEV-010',ready:true},
|
||||||
{icon:'💾',name:'云盘',path:'/m15-cloud-drive/'},
|
{icon:'🧠',name:'Persona Studio',path:'../persona-studio/frontend/index.html',dev:'',ready:true},
|
||||||
{icon:'🔐',name:'登录',path:'/m01-login/'},
|
{icon:'📈',name:'仪表盘',path:'dashboard/',dev:'',ready:true},
|
||||||
{icon:'❤️',name:'健康检查',path:'/m18-health-check/'},
|
{icon:'🖥️',name:'前端',path:'../frontend/',dev:'DEV-002',ready:true},
|
||||||
{icon:'🚀',name:'冷启动',path:'/coldstart/'},
|
|
||||||
{icon:'📈',name:'仪表盘',path:'/dashboard/'},
|
|
||||||
{icon:'🏠',name:'门户',path:'/portal/'},
|
|
||||||
{icon:'🔔',name:'通知',path:'/notification/'},
|
|
||||||
{icon:'❓',name:'帮助中心',path:'/help-center/'},
|
|
||||||
{icon:'🎨',name:'前端',path:'/frontend/'}
|
|
||||||
];
|
];
|
||||||
modules.forEach(function(m){
|
modules.forEach(function(m){
|
||||||
h+='<a href="'+m.path+'" class="ann-action-btn" style="text-decoration:none;text-align:center;display:block">'+m.icon+' '+m.name+'</a>';
|
var style=m.ready?'':'opacity:0.5;';
|
||||||
|
var badge=m.ready?'':'<span style="font-size:9px;color:var(--warn)"> 开发中</span>';
|
||||||
|
h+='<a href="'+m.path+'" class="ann-action-btn" style="text-decoration:none;text-align:center;display:block;'+style+'">'+m.icon+' '+m.name+badge+'</a>';
|
||||||
});
|
});
|
||||||
h+='</div></div>';
|
h+='</div></div>';
|
||||||
|
|
||||||
|
|
@ -1283,6 +1345,14 @@ function showApp(){
|
||||||
document.getElementById('app').classList.add('on');
|
document.getElementById('app').classList.add('on');
|
||||||
document.getElementById('hmdl').textContent = A.mdl||'—';
|
document.getElementById('hmdl').textContent = A.mdl||'—';
|
||||||
document.getElementById('bbdemo').style.display = A.demo?'inline':'none';
|
document.getElementById('bbdemo').style.display = A.demo?'inline':'none';
|
||||||
|
// Staging environment watermark
|
||||||
|
if(HOLOLAKE_ENV==='staging'&&!document.getElementById('staging-wm')){
|
||||||
|
var wm=document.createElement('div');
|
||||||
|
wm.id='staging-wm';
|
||||||
|
wm.className='staging-watermark';
|
||||||
|
wm.textContent='⚠️ 预览测试环境(Staging)· GitHub Pages · 非正式站';
|
||||||
|
document.body.prepend(wm);
|
||||||
|
}
|
||||||
applyIdentityUI();
|
applyIdentityUI();
|
||||||
updateLeftSidebar();
|
updateLeftSidebar();
|
||||||
// Show right sidebar for controllers on desktop
|
// Show right sidebar for controllers on desktop
|
||||||
|
|
@ -1647,14 +1717,22 @@ function resetAllSettings(){
|
||||||
// ═══════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════
|
||||||
async function loadBrain(){
|
async function loadBrain(){
|
||||||
try{
|
try{
|
||||||
const [mr,rr,dr]=await Promise.all([
|
const [mr,rr,dr,shr,bbr,fsr,tlr]=await Promise.all([
|
||||||
fetch(RAW+'/.github/brain/memory.json'),
|
fetch(RAW+'/.github/brain/memory.json').catch(()=>null),
|
||||||
fetch(RAW+'/.github/brain/routing-map.json'),
|
fetch(RAW+'/.github/brain/routing-map.json').catch(()=>null),
|
||||||
fetch(RAW+'/.github/persona-brain/dev-status.json'),
|
fetch(RAW+'/.github/persona-brain/dev-status.json').catch(()=>null),
|
||||||
|
fetch(RAW+'/data/system-health.json').catch(()=>null),
|
||||||
|
fetch(RAW+'/data/bulletin-board.json').catch(()=>null),
|
||||||
|
fetch(RAW+'/federation-status.json').catch(()=>null),
|
||||||
|
fetch(RAW+'/persona-telemetry/latest-summary.json').catch(()=>null),
|
||||||
]);
|
]);
|
||||||
if(mr.ok) A.brain=await mr.json();
|
if(mr&&mr.ok) A.brain=await mr.json();
|
||||||
if(rr.ok) A.routing=await rr.json();
|
if(rr&&rr.ok) A.routing=await rr.json();
|
||||||
if(dr.ok) A.devStatus=await dr.json();
|
if(dr&&dr.ok) A.devStatus=await dr.json();
|
||||||
|
if(shr&&shr.ok) A.systemHealth=await shr.json();
|
||||||
|
if(bbr&&bbr.ok) A.bulletinBoard=await bbr.json();
|
||||||
|
if(fsr&&fsr.ok) A.federationStatus=await fsr.json();
|
||||||
|
if(tlr&&tlr.ok) A.telemetrySummary=await tlr.json();
|
||||||
}catch(_){}
|
}catch(_){}
|
||||||
if(!A.brain) A.brain={...FB_BRAIN};
|
if(!A.brain) A.brain={...FB_BRAIN};
|
||||||
updBbar();
|
updBbar();
|
||||||
|
|
@ -1662,9 +1740,18 @@ async function loadBrain(){
|
||||||
|
|
||||||
function updBbar(){
|
function updBbar(){
|
||||||
const b=A.brain||FB_BRAIN;
|
const b=A.brain||FB_BRAIN;
|
||||||
|
const sh=A.systemHealth;
|
||||||
const c=b.stats?.coverage||FB_COV;
|
const c=b.stats?.coverage||FB_COV;
|
||||||
const ev=b.events?.slice(-1)[0];
|
const ev=b.events?.slice(-1)[0];
|
||||||
document.getElementById('bbc').textContent='📊 HLI '+c.implemented+'/'+c.total+' ('+c.percent+')';
|
// Use system-health data if available for richer status bar
|
||||||
|
if(sh){
|
||||||
|
const m=sh.metrics||{};
|
||||||
|
const wf=m.workflows||{};
|
||||||
|
const sc=sh.last_skyeye_scan||{};
|
||||||
|
document.getElementById('bbc').textContent='🟢 系统健康 · '+wf.total+' 工作流 · '+m.agents?.total+' Agent · HLI '+c.implemented+'/'+c.total;
|
||||||
|
} else {
|
||||||
|
document.getElementById('bbc').textContent='📊 HLI '+c.implemented+'/'+c.total+' ('+c.percent+')';
|
||||||
|
}
|
||||||
document.getElementById('bbe').textContent=ev?('📌 '+(ev.title||ev.type||'').slice(0,28)):'';
|
document.getElementById('bbe').textContent=ev?('📌 '+(ev.title||ev.type||'').slice(0,28)):'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1686,6 +1773,21 @@ async function fetchNotionProfile(devId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchSkyeyeReport() {
|
async function fetchSkyeyeReport() {
|
||||||
|
// Primary: use system-health.json already loaded
|
||||||
|
if (A.systemHealth) {
|
||||||
|
const sh = A.systemHealth;
|
||||||
|
return {
|
||||||
|
overall_status: sh.system_status || 'unknown',
|
||||||
|
timestamp: sh.last_updated,
|
||||||
|
scan_id: sh.last_skyeye_scan?.id,
|
||||||
|
workflows: sh.metrics?.workflows?.total,
|
||||||
|
agents: sh.metrics?.agents?.total,
|
||||||
|
guards: sh.last_skyeye_scan?.guards,
|
||||||
|
issues: sh.last_skyeye_scan?.issues,
|
||||||
|
warnings: sh.last_skyeye_scan?.warnings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Fallback: try GitHub API cache
|
||||||
try {
|
try {
|
||||||
const url = GH_API_BASE + '.github/notion-cache/skyeye/latest-report.json';
|
const url = GH_API_BASE + '.github/notion-cache/skyeye/latest-report.json';
|
||||||
const res = await fetch(url, { headers: GH_RAW_HEADERS });
|
const res = await fetch(url, { headers: GH_RAW_HEADERS });
|
||||||
|
|
@ -1712,14 +1814,25 @@ function updateSkyeyeCard() {
|
||||||
const report = A.skyeyeReport;
|
const report = A.skyeyeReport;
|
||||||
const profile = A.notionProfile;
|
const profile = A.notionProfile;
|
||||||
const meta = A.userMeta;
|
const meta = A.userMeta;
|
||||||
|
const sh = A.systemHealth;
|
||||||
|
const bb = A.bulletinBoard;
|
||||||
|
|
||||||
if (!report && !profile) { card.classList.remove('on'); return; }
|
// Always show the card now since we have system-health data
|
||||||
|
if (!report && !profile && !sh) { card.classList.remove('on'); return; }
|
||||||
card.classList.add('on');
|
card.classList.add('on');
|
||||||
|
|
||||||
// SkyEye overall status
|
// SkyEye overall status - use system-health as primary
|
||||||
const statusEl = document.getElementById('skyeye-status');
|
const statusEl = document.getElementById('skyeye-status');
|
||||||
const timeEl = document.getElementById('skyeye-time');
|
const timeEl = document.getElementById('skyeye-time');
|
||||||
if (report) {
|
if (sh) {
|
||||||
|
const s = sh.system_status || 'unknown';
|
||||||
|
statusEl.textContent = s === 'healthy' ? '✅ 健康' : s === 'warning' ? '⚠️ 警告' : s === 'error' ? '❌ 异常' : s;
|
||||||
|
statusEl.className = 'skyeye-tag ' + (s === 'healthy' ? 'ok' : s === 'warning' ? 'warn' : 'err');
|
||||||
|
if (sh.last_updated) {
|
||||||
|
const d = new Date(sh.last_updated);
|
||||||
|
timeEl.textContent = '· 上次更新 ' + d.toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
|
||||||
|
}
|
||||||
|
} else if (report) {
|
||||||
const s = report.overall_status || 'unknown';
|
const s = report.overall_status || 'unknown';
|
||||||
statusEl.textContent = s === 'healthy' ? '✅ 健康' : s === 'warning' ? '⚠️ 警告' : s === 'error' ? '❌ 异常' : s;
|
statusEl.textContent = s === 'healthy' ? '✅ 健康' : s === 'warning' ? '⚠️ 警告' : s === 'error' ? '❌ 异常' : s;
|
||||||
statusEl.className = 'skyeye-tag ' + (s === 'healthy' ? 'ok' : s === 'warning' ? 'warn' : 'err');
|
statusEl.className = 'skyeye-tag ' + (s === 'healthy' ? 'ok' : s === 'warning' ? 'warn' : 'err');
|
||||||
|
|
@ -1736,7 +1849,11 @@ function updateSkyeyeCard() {
|
||||||
// Developer repo info
|
// Developer repo info
|
||||||
const repoRow = document.getElementById('skyeye-repo-row');
|
const repoRow = document.getElementById('skyeye-repo-row');
|
||||||
const repoInfo = document.getElementById('skyeye-repo-info');
|
const repoInfo = document.getElementById('skyeye-repo-info');
|
||||||
if (profile && profile.github) {
|
if (sh) {
|
||||||
|
repoRow.style.display = 'flex';
|
||||||
|
const m = sh.metrics || {};
|
||||||
|
repoInfo.textContent = m.workflows?.total + ' 工作流 · ' + (m.agents?.total||0) + ' Agent · ' + (m.guards?.active||0) + '/' + (m.guards?.total||0) + ' 守卫';
|
||||||
|
} else if (profile && profile.github) {
|
||||||
repoRow.style.display = 'flex';
|
repoRow.style.display = 'flex';
|
||||||
const mods = profile.modules_owned || [];
|
const mods = profile.modules_owned || [];
|
||||||
const warns = profile.skyeye_health?.warnings || [];
|
const warns = profile.skyeye_health?.warnings || [];
|
||||||
|
|
@ -1745,10 +1862,14 @@ function updateSkyeyeCard() {
|
||||||
repoRow.style.display = 'none';
|
repoRow.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast info
|
// Broadcast info - use bulletin-board as primary
|
||||||
const bcRow = document.getElementById('skyeye-broadcast-row');
|
const bcRow = document.getElementById('skyeye-broadcast-row');
|
||||||
const bcInfo = document.getElementById('skyeye-broadcast-info');
|
const bcInfo = document.getElementById('skyeye-broadcast-info');
|
||||||
if (profile && profile.current_work && profile.current_work.broadcast_id) {
|
if (bb && bb.announcements && bb.announcements.length > 0) {
|
||||||
|
bcRow.style.display = 'flex';
|
||||||
|
const latest = bb.announcements[0];
|
||||||
|
bcInfo.textContent = (latest.emoji||'') + ' ' + (latest.title||'') + ' · ' + (latest.date||'');
|
||||||
|
} else if (profile && profile.current_work && profile.current_work.broadcast_id) {
|
||||||
bcRow.style.display = 'flex';
|
bcRow.style.display = 'flex';
|
||||||
const cw = profile.current_work;
|
const cw = profile.current_work;
|
||||||
bcInfo.textContent = cw.broadcast_id + (cw.current_ring ? ' · 环节' + cw.current_ring + '进行中' : '') + (cw.status ? ' · ' + cw.status : '');
|
bcInfo.textContent = cw.broadcast_id + (cw.current_ring ? ' · 环节' + cw.current_ring + '进行中' : '') + (cw.status ? ' · ' + cw.status : '');
|
||||||
|
|
@ -1898,12 +2019,38 @@ function renderBrainPanel(){
|
||||||
const r=A.routing;
|
const r=A.routing;
|
||||||
const c=b.stats?.coverage||FB_COV;
|
const c=b.stats?.coverage||FB_COV;
|
||||||
const evs=(b.events||[]).slice(-5).reverse();
|
const evs=(b.events||[]).slice(-5).reverse();
|
||||||
|
const sh=A.systemHealth;
|
||||||
|
const tl=A.telemetrySummary;
|
||||||
let h='';
|
let h='';
|
||||||
|
|
||||||
|
// Real system health data
|
||||||
|
if(sh){
|
||||||
|
const m=sh.metrics||{};
|
||||||
|
h+='<div class="sec-ttl">系统概览(实时数据)</div>';
|
||||||
|
h+=ir2('系统状态','<span class="'+(sh.system_status==='healthy'?'iv':'ivw')+'">'+esc(sh.system_status==='healthy'?'✅ 健康':sh.system_status==='warning'?'⚠️ 警告':'❌ 异常')+'</span>');
|
||||||
|
h+=ir2('工作流','<span class="iv">'+(m.workflows?.total||0)+' 总 / '+(m.workflows?.active||0)+' 活跃</span>');
|
||||||
|
h+=ir2('Agent 数量','<span class="iv">'+(m.agents?.total||0)+'</span>');
|
||||||
|
h+=ir2('守卫','<span class="iv">'+(m.guards?.active||0)+'/'+(m.guards?.total||0)+' 活跃</span>');
|
||||||
|
h+=ir2('人格体','<span class="iv">'+(m.ai_personas?.total||0)+' 总 / '+(m.ai_personas?.active||0)+' 活跃</span>');
|
||||||
|
h+=ir2('神经系统','<span class="iv">'+(m.neural_system_version||'v3.0')+'</span>');
|
||||||
|
h+=ir2('本体论版本','<span class="iv">'+(m.ontology_version||'v1.0')+'</span>');
|
||||||
|
}
|
||||||
|
|
||||||
h+=ir2('HLI 覆盖率','<span class="'+(c.implemented<c.total?'ivw':'iv')+'">'+c.implemented+'/'+c.total+' ('+c.percent+')</span>');
|
h+=ir2('HLI 覆盖率','<span class="'+(c.implemented<c.total?'ivw':'iv')+'">'+c.implemented+'/'+c.total+' ('+c.percent+')</span>');
|
||||||
h+=ir2('规则版本','<span class="iv">'+(b.rules_version||'v1.0')+'</span>');
|
h+=ir2('规则版本','<span class="iv">'+(b.rules_version||'v1.0')+'</span>');
|
||||||
h+=ir2('唤醒协议','<span class="iv">'+(b.wake_protocol_version||'v1.0')+'</span>');
|
h+=ir2('唤醒协议','<span class="iv">'+(b.wake_protocol_version||'v1.0')+'</span>');
|
||||||
h+=ir2('CI 运行','<span class="iv">'+(b.stats?.ci_runs??0)+'</span>');
|
h+=ir2('CI 运行','<span class="iv">'+(b.stats?.ci_runs??0)+'</span>');
|
||||||
h+=ir2('广播处理','<span class="iv">'+(b.stats?.broadcasts_processed??0)+'</span>');
|
h+=ir2('广播处理','<span class="iv">'+(b.stats?.broadcasts_processed??0)+'</span>');
|
||||||
|
|
||||||
|
// Telemetry data
|
||||||
|
if(tl){
|
||||||
|
h+='<div class="sec-ttl">铸渊遥测</div>';
|
||||||
|
h+=ir2('活跃人格','<span class="iv">'+esc(tl.persona_state?.active_persona||'铸渊')+'</span>');
|
||||||
|
h+=ir2('风格轮廓','<span class="iv">'+esc(tl.persona_state?.style_profile||'')+'</span>');
|
||||||
|
h+=ir2('24h 会话','<span class="iv">'+(tl.sessions?.total_24h||0)+' 次</span>');
|
||||||
|
h+=ir2('消息总数','<span class="iv">'+(tl.sessions?.total_messages||0)+' 条</span>');
|
||||||
|
}
|
||||||
|
|
||||||
h+='<div class="sec-ttl">近期事件</div>';
|
h+='<div class="sec-ttl">近期事件</div>';
|
||||||
for(const ev of evs){
|
for(const ev of evs){
|
||||||
h+='<div class="drow"><div class="dn">'+esc(ev.title||ev.type||'事件')+'</div><div class="dm">'+(ev.timestamp||'').slice(0,10)+(ev.actor?' · '+esc(ev.actor):'')+'</div></div>';
|
h+='<div class="drow"><div class="dn">'+esc(ev.title||ev.type||'事件')+'</div><div class="dm">'+(ev.timestamp||'').slice(0,10)+(ev.actor?' · '+esc(ev.actor):'')+'</div></div>';
|
||||||
|
|
@ -1925,6 +2072,12 @@ function renderBrainPanel(){
|
||||||
h+='<li>.github/brain/memory.json</li><li>.github/brain/routing-map.json</li>';
|
h+='<li>.github/brain/memory.json</li><li>.github/brain/routing-map.json</li>';
|
||||||
h+='<li>.github/brain/wake-protocol.md</li><li>.github/brain/growth-log.md</li>';
|
h+='<li>.github/brain/wake-protocol.md</li><li>.github/brain/growth-log.md</li>';
|
||||||
h+='<li>src/routes/hli/</li></ol>';
|
h+='<li>src/routes/hli/</li></ol>';
|
||||||
|
|
||||||
|
h+='<div class="sec-ttl">环境信息</div>';
|
||||||
|
h+=ir2('当前环境','<span class="iv">'+HOLOLAKE_ENV+'</span>');
|
||||||
|
h+=ir2('前端版本','<span class="iv">v6.0</span>');
|
||||||
|
h+=ir2('大脑版本','<span class="iv">'+BRAIN_VERSION+'</span>');
|
||||||
|
|
||||||
document.getElementById('bpb').innerHTML=h;
|
document.getElementById('bpb').innerHTML=h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue