docs: initial design documents

- 9 pages: index, architecture, capabilities, roadmap, security,
  maintenance, pm-review, backlog, flow
- shared style.css (dark theme)
- .gitignore for OS / editor / build artifacts
This commit is contained in:
Childish-Ghost
2026-07-18 22:17:37 +08:00
commit 7f84ea56fc
11 changed files with 2386 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
# OS
.DS_Store
Thumbs.db
desktop.ini
# Editor
.vscode/
.idea/
*.swp
*.swo
*~
# Logs
*.log
npm-debug.log*
# Env
.env
.env.local
.env.*.local
# Build artifacts
node_modules/
dist/
build/
target/
*.exe
*.deb
*.apk
*.dmg
# Tauri
src-tauri/target/
# Expo / React Native
.expo/
.expo-shared/
*.tsbuildinfo

View File

@@ -0,0 +1,651 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统架构 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<span class="current">系统架构</span>
</div>
<div class="container">
<h1>系统架构设计</h1>
<p class="subtitle">任意设备控制任意设备 · 全部通过客户端 MCP Server · 多通道统一记忆</p>
<!-- ===== 核心模型 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--accent)"></span> 核心模型:任意设备 → 任意设备</h2>
<div class="highlight">
<h4>自建客户端:两个功能模块</h4>
<p>
<b>功能 1 — 与 Gateway 沟通(发送命令):</b>客户端通过 WebSocket 连接 OpenClaw Gateway提供聊天界面、设备管理、远程桌面。用户在客户端里的操作聊天、点按钮走的是 Gateway 的 API。<br><br>
<b>功能 2 — 暴露本机能力MCP Server</b>客户端启动后自动注册到 Gateway 作为 MCP Server。<b>AI 或其他设备要操作这台机器时Gateway 调用它暴露的 MCP Tools</b>file_list、exec、screenshot 等)。<br><br>
<b>所有被控设备都装客户端。</b>不装客户端的设备不纳入控制范围。
</p>
</div>
<div class="diagram">┌─────────────────────────────────────────────────────────────────────────────┐
<span class="hi">发起方 — 任意设备 / 任意通道</span>
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ <span class="hi">手机客户端</span>│ │ <span class="hi">电脑客户端</span>│ │ 飞书 │ │ 微信 │ │ Telegram │ │
│ │(MCP+UI) │ │(MCP+UI) │ │ │ │ │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└────────┼─────────────┼─────────────┼─────────────┼─────────────┼────────────┘
▼ ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
<span class="gr">OpenClaw GatewayMCP Host</span>
│ │
│ AI Agent · 通道路由 · 记忆系统 · MCP Host │
│ │
<span class="dim">── 设备注册表(全部通过客户端 MCP Server──</span>
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ "home-pc" → MCP SSE <span class="gr">在线</span> <span class="dim">[file,exec,screen,input]</span> │ │
│ │ "cloud-svr" → MCP SSE <span class="gr">在线</span> <span class="dim">[file,exec,sysinfo]</span> │ │
│ │ "my-phone" → MCP SSE <span class="gr">在线</span> <span class="dim">[file,exec,screenshot]</span> │ │
│ │ "work-pc" → MCP SSE <span class="dim">离线</span> <span class="dim">[—]</span> │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└───────────┬───────────────────────────────────────────────────────────────┘
┌────────┴────────┐ ┌──────────────────┐
▼ ▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ home-pc │ │ cloud-svr│ │ my-phone │ │ work-pc │
<span class="gr">客户端</span> │ │<span class="gr">客户端</span> │ │<span class="gr">客户端</span> │ │<span class="dim">离线</span>
└──────────┘ └──────────┘ └──────────┘ └──────────┘</div>
</div>
<!-- ===== 使用场景 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--pink)"></span> 典型场景</h2>
<div class="grid grid-2">
<div class="card">
<h4>📱 手机找电脑文件</h4>
<p>手机 App → Gateway → home-pc<br>"找桌面上的 PDF" → <code>file_list("home-pc", "C:\\Desktop", "*.pdf")</code></p>
</div>
<div class="card">
<h4>💻 电脑查服务器日志</h4>
<p>电脑 App → Gateway → cloud-svr<br>"看 nginx 最近 50 行日志" → <code>exec("cloud-svr", "tail -50 /var/log/nginx.log")</code></p>
</div>
<div class="card">
<h4>💬 微信开关游戏服务器</h4>
<p>微信 → Gateway AI → game-svr客户端<br>"把游戏服务器关了" → <code>exec("game-svr", "systemctl stop minecraft")</code></p>
</div>
<div class="card">
<h4>📱 电脑看手机屏幕</h4>
<p>电脑客户端 → Gateway → my-phone客户端<br><code>screenshot("my-phone")</code> → 返回手机当前屏幕截图</p>
</div>
<div class="card">
<h4>🔄 跨设备文件传输</h4>
<p>手机 App → Gateway → 从 NAS 传到电脑<br><code>file_transfer("nas", "/backup/data.zip", "home-pc", "D:\\backup\\")</code></p>
</div>
<div class="card">
<h4>🤖 AI 自动巡检</h4>
<p>定时任务 → Gateway AI → 遍历所有设备<br>"检查所有服务器磁盘使用率" → AI 逐个调用 <code>sysinfo</code></p>
</div>
</div>
</div>
<!-- ===== 接入方式 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--accent2)"></span> 目标设备接入方式</h2>
<div class="table-wrap">
<table>
<tr><th>设备</th><th>客户端类型</th><th>说明</th></tr>
<tr>
<td><b>Windows / macOS / Linux 桌面</b></td>
<td><span class="tag t-green">桌面客户端</span></td>
<td>Tauri 桌面客户端MCP Server + 完整 UI聊天/文件/远程桌面)</td>
</tr>
<tr>
<td><b>Android 手机</b></td>
<td><span class="tag t-green">移动端客户端</span></td>
<td>React Native 客户端MCP Server + 完整 UI</td>
</tr>
<tr>
<td><b>NAS群晖/威联通等)</b></td>
<td><span class="tag t-blue">CLI 客户端</span></td>
<td>Node.js CLIMCP Server 无 UIDocker/systemd 后台运行</td>
</tr>
<tr>
<td><b>Linux 服务器</b></td>
<td><span class="tag t-blue">CLI 客户端</span></td>
<td>同 NAS CLI 版npx 或 Docker 部署</td>
</tr>
<tr>
<td><b>树莓派 / 开发板</b></td>
<td><span class="tag t-blue">CLI 客户端</span></td>
<td>同 CLI 版,支持 GPIO/传感器扩展</td>
</tr>
</table>
</div>
<h3>能力说明</h3>
<p style="color:var(--dim);font-size:.85rem">所有被控设备必须安装客户端。客户端作为 MCP Server 注册到 Gateway能力完整文件/命令/屏幕/输入/系统信息)。不装客户端的设备不纳入控制范围。</p>
</div>
<!-- ===== 自建客户端 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--accent3)"></span> 自建客户端:两个功能</h2>
<p style="color:var(--dim);margin-bottom:16px;font-size:.9rem">自建客户端部署在用户的手机和电脑上,连接到主机的 Gateway。</p>
<div class="grid grid-2">
<div class="card">
<h4>功能 1与 Gateway 沟通</h4>
<p>通过 WebSocket 连接 Gateway提供聊天界面、设备管理、远程桌面。用户操作走 Gateway API。</p>
</div>
<div class="card">
<h4>功能 2暴露本机能力MCP Server</h4>
<p>启动后自动注册到 Gateway 作为 MCP Server。AI 或其他设备要操作这台机器时Gateway 调用它的 MCP Tools。</p>
</div>
<div class="card">
<h4>远程桌面</h4>
<p>获取目标设备屏幕推流,直接操控鼠标键盘。通过 WS 数据端口传输。</p>
</div>
<div class="card">
<h4>跨设备操作</h4>
<p>手机上找电脑文件、电脑上查服务器日志。客户端不需要知道目标设备用什么协议Gateway 统一路由。</p>
</div>
<div class="card">
<h4>独立代理</h4>
<p>客户端内置独立代理配置SOCKS5/HTTP<b>不影响系统代理</b>。只代理客户端自身的 WebSocket 连接。适合需要代理才能访问 Tailscale/外网的场景。</p>
</div>
<div class="card">
<h4>启动自动连接</h4>
<p>保存 Gateway 地址 + 认证 token。打开客户端自动连接 Gateway、注册 MCP Server、拉取设备列表。<b>断线自动重连</b>(指数退避 1s→2s→4s→...→60s</p>
</div>
</div>
<h3>客户端配置</h3>
<div class="code-block">
<span class="lang">客户端设置</span>
<pre><span class="comment">// 本地存储,首次启动时配置,之后自动连接</span>
{
<span class="key">"gateway"</span>: {
<span class="key">"url"</span>: <span class="str">"ws://100.x.x.x:18789"</span>, <span class="comment">// Gateway 地址Tailscale IP / DDNS 域名 / 内网 IP</span>
<span class="key">"token"</span>: <span class="str">"your-auth-token"</span>, <span class="comment">// 认证 token</span>
<span class="key">"autoConnect"</span>: <span class="bool">true</span>, <span class="comment">// 启动自动连接</span>
<span class="key">"reconnect"</span>: <span class="bool">true</span> <span class="comment">// 断线自动重连</span>
},
<span class="key">"proxy"</span>: {
<span class="key">"enabled"</span>: <span class="bool">false</span>, <span class="comment">// 是否启用独立代理</span>
<span class="key">"type"</span>: <span class="str">"socks5"</span>, <span class="comment">// socks5 / http</span>
<span class="key">"host"</span>: <span class="str">"127.0.0.1"</span>,
<span class="key">"port"</span>: <span class="num">7890</span>
},
<span class="key">"device"</span>: {
<span class="key">"name"</span>: <span class="str">"我的手机"</span>, <span class="comment">// 本设备名称</span>
<span class="key">"exposeAsMcp"</span>: <span class="bool">true</span> <span class="comment">// 是否暴露本机能力给 Gateway</span>
},
<span class="comment">// OTA 更新由 expo-updates 自动处理,无需手动配置</span>
<span class="comment">// 更新 URL 在 app.json 的 updates.url 中配置</span>
}</pre>
</div>
</div>
<!-- ===== 完整连接流程 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--pink)"></span> 客户端完整连接流程</h2>
<h3>启动流程</h3>
<div class="diagram">┌──────────────────┐
│ 客户端启动 │
└────────┬─────────┘
┌──────────────────┐ 通了 ┌──────────────┐
│ ① 测试 Gateway │───────────▶│ 连接 Gateway │
│ 是否通联 │ │ 注册 MCP Server│
│ (config 中的 URL │ │ 拉取设备列表 │
│ timeout: 3s) │ │ 启动心跳 │
└────────┬─────────┘ └──────────────┘
│ 不通
┌──────────────────┐
│ ② 检查 Tailscale │
│ 状态 │
└────────┬─────────┘
┌────┼──────────────┐
▼ ▼ ▼
没运行 运行未连接 运行已连接
│ │ │
▼ ▼ ▼
启动TS ③重连TS ┌─────────────┐
started │ │ Gateway 不通 │
_by_us=T │ │ 提示用户检查 │
│ ┌─┴──┐ └─────────────┘
│ ▼ ▼
│ up 成功 up失败(需认证)
│ │ │
│ │ ▼
│ │ tailscale login
│ │ │
│ │ ┌─┴──┐
│ │ ▼ ▼
│ │ 成功 失败→提示用户
│ │ │
▼ ▼ ▼
┌──────────────┐
│ 回到 ① 重试 │
└──────────────┘</div>
<h3>运行中心跳保活</h3>
<div class="diagram">┌──────────────────┐
│ 正常运行中 │
└────────┬─────────┘
┌──────────────────┐
│ 每 30s 发 WS ping│◀─────────────────────┐
└────────┬─────────┘ │
│ │
┌────┴────┐ │
▼ ▼ │
收到pong 连续3次无响应 │
│ │ │
继续运行 ▼ │
┌──────────┐ │
│ 判定断开 │ │
└────┬─────┘ │
▼ │
┌──────────┐ 成功 │
│ 重连流程 │──────────────────────┘
│ ①②③ │
└────┬─────┘
│ 全部失败
┌──────────┐
│ 通知用户 │
│ 连接丢失 │
└──────────┘</div>
<h3>退出流程</h3>
<div class="diagram">┌──────────────────┐
│ 客户端退出 │
└────────┬─────────┘
┌──────────────────┐
│ 断开 Gateway WS │
└────────┬─────────┘
┌──────────────────┐ 是 ┌──────────────┐
│ started_by_us? │───────────▶│ tailscale down│
└────────┬─────────┘ │ 恢复进入前状态 │
│ 否 └──────────────┘
┌──────────────────┐
│ 不动 Tailscale │
└──────────────────┘</div>
<h3>完整状态机</h3>
<div class="diagram"><span class="dim">客户端状态:</span>
<span class="hl">IDLE</span> ──启动──▶ <span class="hl">TESTING</span> ──通──▶ <span class="gr">CONNECTED</span> ──断开──▶ <span class="hi">RECONNECTING</span> ──成功──▶ <span class="gr">CONNECTED</span>
│ │ │
│ 不通 │ 退出 │ 全部失败
▼ ▼ ▼
<span class="hl">CHECK_TS</span> <span class="dim">SHUTDOWN</span> <span class="hi">DISCONNECTED</span>
┌─────┼─────┐
▼ ▼ ▼
没运行 未连接 已连接
│ │ │
▼ ▼ ▼
启动TS 重连TS 报错
│ │
▼ ▼
<span class="hl">TESTING</span>(重试)</div>
</div>
<!-- ===== 远程访问 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--red)"></span> 设备在外面怎么连?</h2>
<p style="color:var(--dim);margin-bottom:16px;font-size:.9rem">当设备不在同一局域网时(手机在外面、出差用笔记本、云服务器),需要穿透 NAT 连到主机 Gateway。</p>
<div class="table-wrap">
<table>
<tr><th>方案</th><th>原理</th><th>优点</th><th>缺点</th><th>国内可用</th></tr>
<tr>
<td><b>FRP</b></td>
<td>主机跑 frpc连到有公网 IP 的 frps 服务器。客户端通过 frps 的公网地址连 Gateway。</td>
<td>国内最流行、开源免费、配置灵活、延迟低</td>
<td>需要一台有公网 IP 的服务器(轻量云 30 元/年)</td>
<td><span class="tag t-green">最佳</span></td>
</tr>
<tr>
<td><b>ZeroTier</b></td>
<td>类似 Tailscale设备装 ZeroTier 自动组网。有官方中继服务器。</td>
<td>开源、国内可用、零配置</td>
<td>官方服务器偶尔抽风,可自建 Planet</td>
<td><span class="tag t-green">推荐</span></td>
</tr>
<tr>
<td><b>Cloudflare Tunnel</b></td>
<td>主机跑 cloudflaredGateway 通过 Cloudflare 网络暴露。</td>
<td>免费、不需要公网 IP、自带 DDoS 防护</td>
<td>国内访问可能慢/被墙</td>
<td><span class="tag t-orange">看网络</span></td>
</tr>
<tr>
<td><b>Tailscale</b></td>
<td>设备装 Tailscale 自动组网。OpenClaw 官方推荐。</td>
<td>零配置、加密</td>
<td>国内可能需要 DERP 中继、延迟高</td>
<td><span class="tag t-orange">看网络</span></td>
</tr>
<tr>
<td><b>WireGuard</b></td>
<td>自建 VPN所有设备连入。</td>
<td>高性能、自控</td>
<td>需要公网 IP 服务器、手机配置麻烦</td>
<td><span class="tag t-blue">可选</span></td>
</tr>
<tr>
<td><b>公网直连</b></td>
<td>主机有公网 IPGateway 直接暴露。</td>
<td>最简单、延迟最低</td>
<td>安全风险高</td>
<td><span class="tag t-orange">谨慎</span></td>
</tr>
</table>
</div>
<h3>当前方案</h3>
<div class="grid grid-2">
<div class="card">
<h4>Tailscale</h4>
<p>所有设备装 Tailscale自动组网。客户端通过 Tailscale IP 连 Gateway。OpenClaw 官方推荐。</p>
</div>
<div class="card">
<h4>DDNS-GO</h4>
<p>主机跑 DDNS-GO自动更新动态公网 IP 到域名。客户端通过域名连 Gateway。</p>
</div>
</div>
<p style="color:var(--dim);font-size:.85rem;margin-top:12px">初期通过聊天通道(微信/飞书/Telegram控制设备不需要穿透 NAT。客户端直连远程桌面等用 Tailscale 或 DDNS-GO。</p>
</div>
<!-- ===== 多通道记忆 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 多通道记忆统一</h2>
<div class="table-wrap">
<table>
<tr><th>机制</th><th>配置</th><th>作用</th></tr>
<tr><td>身份统一</td><td><code>session.identityLinks</code></td><td>手机 App / 飞书 / 微信 / Telegram 映射为同一用户</td></tr>
<tr><td>会话共享</td><td><code>dmScope: "per-peer"</code></td><td>跨通道共享对话上下文</td></tr>
<tr><td>长期记忆</td><td><code>MEMORY.md</code></td><td>设备信息、用户偏好、操作历史</td></tr>
<tr><td>每日笔记</td><td><code>memory/YYYY-MM-DD.md</code></td><td>按天记录操作日志,支持语义检索</td></tr>
</table>
</div>
</div>
<!-- ===== OpenClaw 配置 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--orange)"></span> OpenClaw Gateway 配置</h2>
<p style="color:var(--dim);margin-bottom:16px;font-size:.9rem">以下是主机上 OpenClaw 需要的完整配置。</p>
<div class="code-block">
<span class="lang">~/.openclaw/openclaw.json</span>
<pre>{
<span class="comment">// ① MCP Server 注册 — 客户端设备</span>
<span class="key">"mcpServers"</span>: {
<span class="key">"home-pc"</span>: {
<span class="key">"url"</span>: <span class="str">"http://192.168.1.100:3001/sse"</span>
},
<span class="key">"cloud-svr"</span>: {
<span class="key">"url"</span>: <span class="str">"http://100.64.0.3:3001/sse"</span>
}
},
<span class="comment">// ② 全部设备通过客户端 MCP Server 接入</span>
<span class="comment">// ③ 跨通道记忆统一</span>
<span class="key">"session"</span>: {
<span class="key">"dmScope"</span>: <span class="str">"per-peer"</span>,
<span class="key">"identityLinks"</span>: {
<span class="key">"user:me"</span>: {
<span class="key">"channels"</span>: {
<span class="key">"feishu"</span>: <span class="str">"ou_xxx"</span>,
<span class="key">"wechat"</span>: <span class="str">"wxid_xxx"</span>,
<span class="key">"telegram"</span>: <span class="str">"12345678"</span>
}
}
}
},
<span class="comment">// ④ Gateway 绑定(根据网络环境选一种)</span>
<span class="key">"gateway"</span>: {
<span class="key">"bind"</span>: <span class="str">"tailnet"</span>, <span class="comment">// Tailscale 虚拟网络</span>
<span class="key">"auth"</span>: {
<span class="key">"mode"</span>: <span class="str">"token"</span>,
<span class="key">"token"</span>: <span class="str">"your-secret-token"</span>
}
},
<span class="comment">// ⑤ 模型配置</span>
<span class="key">"agent"</span>: {
<span class="key">"model"</span>: <span class="str">"openai/gpt-4o"</span>
},
<span class="comment">// ⑥ 通道配置(按需启用)</span>
<span class="key">"channels"</span>: {
<span class="key">"telegram"</span>: {
<span class="key">"token"</span>: <span class="str">"your-telegram-bot-token"</span>,
<span class="key">"dmPolicy"</span>: <span class="str">"pairing"</span>
},
<span class="key">"feishu"</span>: {
<span class="key">"appId"</span>: <span class="str">"your-feishu-app-id"</span>,
<span class="key">"appSecret"</span>: <span class="str">"your-feishu-app-secret"</span>
}
}
}</pre>
</div>
<h3>配置说明</h3>
<div class="table-wrap">
<table>
<tr><th>配置项</th><th>作用</th><th>必填</th></tr>
<tr><td><code>mcpServers</code></td><td>注册客户端设备Gateway 自动发现其 MCP Tools</td><td></td></tr>
<tr><td><code>session.dmScope</code></td><td>跨通道会话共享per-peer = 同一用户共享)</td><td>推荐</td></tr>
<tr><td><code>session.identityLinks</code></td><td>飞书/微信/Telegram 用户映射为同一人</td><td>推荐</td></tr>
<tr><td><code>gateway.bind</code></td><td>Gateway 绑定地址tailnet/0.0.0.0/127.0.0.1</td><td></td></tr>
<tr><td><code>gateway.auth</code></td><td>认证方式token/password</td><td></td></tr>
<tr><td><code>agent.model</code></td><td>AI 模型(建议用旗舰模型)</td><td></td></tr>
<tr><td><code>channels</code></td><td>聊天通道配置Telegram/飞书/微信等)</td><td>按需</td></tr>
</table>
</div>
</div>
<!-- ===== 技术栈 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 最终技术方案</h2>
<div class="table-wrap">
<table>
<tr><th>组件</th><th>技术</th><th>说明</th></tr>
<tr><td>Gateway主机</td><td>OpenClaw</td><td>MCP HostAI 大脑,通道路由</td></tr>
<tr><td>MCP Server 核心</td><td>TypeScript + <code>@modelcontextprotocol/sdk</code></td><td>全平台通用36 个 MCP Tools</td></tr>
<tr><td>Desktop 客户端</td><td>Tauri v2 (Rust + React)</td><td>Windows/Linux/macOS~5MB内置 OTA updater</td></tr>
<tr><td>Android 客户端</td><td>React Native + Expo</td><td>移动端Expo Updates OTA 热更新</td></tr>
<tr><td>CLI 客户端</td><td>TypeScript (Node.js)</td><td>NAS/服务器/树莓派Docker/systemd 部署</td></tr>
<tr><td>共享类型</td><td>TypeScript</td><td>协议定义、MCP Tool 类型、配置类型</td></tr>
<tr><td>屏幕推流</td><td>WS 数据端口直连</td><td>screenshot-desktop + Sharp + MJPEG</td></tr>
<tr><td>鼠标键盘</td><td>nut.js</td><td>跨平台输入模拟</td></tr>
<tr><td>OTA 更新</td><td>Expo Updates (JS bundle) + Tauri updater (APK)</td><td>小更新 JS bundle OTA 静默推送(新增页面/改 UI/修 Bug大更新 APK 重装(原生模块变更)</td></tr>
<tr><td>CI/CD</td><td>GitHub Actions / Gitee</td><td>push tag → 自动构建所有平台</td></tr>
<tr><td>编辑器</td><td>IntelliJ IDEA</td><td>TypeScript + Rust 开发</td></tr>
</table>
</div>
</div>
<!-- ===== OTA 更新策略 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> OTA 更新策略</h2>
<div class="highlight">
<h4>双轨更新:小更新 OTA 静默推送,大更新 APK 重装</h4>
<p>
<b>小更新JS bundle</b>新增页面、改 UI、修 Bug、改业务逻辑 → expo-updates 静默推送 JS bundle~1-2MB用户无感下次打开自动生效。<br>
<b>大更新APK</b>新增原生模块、改图标、升级 React Native 版本 → 需要重新打包 APK用户手动安装。
</p>
</div>
<div class="table-wrap">
<table>
<tr><th>更新类型</th><th>方式</th><th>用户感知</th><th>场景</th></tr>
<tr><td><b>小更新</b></td><td>JS bundle OTA (expo-updates)</td><td>无感,自动生效</td><td>新增页面、改 UI、修 Bug、改逻辑、新增 JS 依赖</td></tr>
<tr><td><b>大更新</b></td><td>APK 重装</td><td>需手动安装</td><td>新增原生模块、改图标/启动图、改包名、升级 RN</td></tr>
</table>
</div>
<h3>OTA 发布流程</h3>
<div class="code-block">
<span class="lang">发布 JS bundle 更新</span>
<pre><span class="comment"># 1. 修改代码JS/TS</span>
<span class="comment"># 2. 增加版本号app.json version + versionCode</span>
<span class="comment"># 3. 导出 JS bundle</span>
npx expo export --platform android
<span class="comment"># 4. 上传 dist/ 到 Gitee 静态仓库</span>
git add dist/ && git commit -m "ota: v0.1.1" && git push
<span class="comment"># 5. App 自动检测更新(启动时 + 每 24 小时)</span>
<span class="comment"># 用户下次打开 App 自动生效</span></pre>
</div>
<h3>OTA 配置app.json</h3>
<div class="code-block">
<span class="lang">app.json</span>
<pre>{
<span class="key">"expo"</span>: {
<span class="key">"updates"</span>: {
<span class="key">"url"</span>: <span class="str">"https://gitee.com/your-org/gca-ota/manifest.json"</span>
},
<span class="key">"plugins"</span>: [
[<span class="str">"expo-updates"</span>, { <span class="key">"username"</span>: <span class="str">"gca"</span> }]
]
}
}</pre>
</div>
</div>
<!-- ===== 项目结构 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--accent2)"></span> 项目结构</h2>
<div class="code-block">
<pre>gca/
├── packages/
│ ├── client/ <span class="comment"># 桌面/移动端客户端MCP Server + UI</span>
│ │ ├── src/
│ │ │ ├── server/ <span class="comment"># MCP Server暴露本机能力给 Gateway</span>
│ │ │ │ ├── tools/ <span class="comment"># MCP Toolsfile/exec/screen/input/sysinfo</span>
│ │ │ │ └── data-channel/<span class="comment"># WS 数据端口(推流/文件/键鼠)</span>
│ │ │ ├── ui/ <span class="comment"># UI聊天/文件浏览/远程桌面,连 Gateway WS API</span>
│ │ │ └── platform/ <span class="comment"># 平台适配win/linux/mac/android</span>
│ │ └── package.json
│ ├── client-cli/ <span class="comment"># CLI 版客户端NAS/树莓派/无显示器设备)</span>
│ │ ├── src/
│ │ │ ├── index.ts <span class="comment"># CLI 入口gca-cli start/stop/status</span>
│ │ │ ├── daemon.ts <span class="comment"># 后台守护进程</span>
│ │ │ └── server/ <span class="comment"># 复用 client/server 的 MCP Tools</span>
│ │ └── package.json
│ └── shared/ <span class="comment"># 共享类型</span>
├── pnpm-workspace.yaml
└── README.md</pre>
</div>
</div>
<!-- ===== 实现细节 ===== -->
<div class="section">
<h2><span class="dot" style="background:var(--accent)"></span> 实现细节</h2>
<h3>客户端实现</h3>
<div class="table-wrap">
<table>
<tr><th>模块</th><th>实现</th><th>说明</th></tr>
<tr>
<td>MCP Server</td>
<td><code>@modelcontextprotocol/sdk</code></td>
<td>启动时创建 MCP Server 实例,注册 Tools通过 SSE/WS 暴露给 Gateway</td>
</tr>
<tr>
<td>Gateway 连接</td>
<td>WebSocket Client</td>
<td>连接 Gateway 的 WS API支持独立代理SOCKS5/HTTP、自动重连</td>
</tr>
<tr>
<td>文件服务</td>
<td>Node.js <code>fs</code> / Rust <code>std::fs</code></td>
<td>实现 file_list/read/write/move/delete支持 glob 过滤</td>
</tr>
<tr>
<td>命令执行</td>
<td><code>child_process</code> / Rust <code>std::process::Command</code></td>
<td>实现 exec支持超时、工作目录、环境变量</td>
</tr>
<tr>
<td>屏幕捕获</td>
<td><code>screenshot-desktop</code> (Node) / <code>screenshots</code> crate (Rust)</td>
<td>截取屏幕JPEG 压缩后返回 base64</td>
</tr>
<tr>
<td>系统信息</td>
<td><code>systeminformation</code> (Node) / <code>sysinfo</code> crate (Rust)</td>
<td>CPU/内存/磁盘/网络/运行时间</td>
</tr>
<tr>
<td>独立代理</td>
<td>Tauri: <code>tokio-tungstenite</code> + HTTP CONNECT / RN: OkHttp proxy</td>
<td>只代理客户端自身的 WS 连接,不影响系统代理</td>
</tr>
<tr>
<td>UI</td>
<td>Tauri: React / RN: React Native</td>
<td>聊天界面、设备列表、文件浏览器、远程桌面、设置页面</td>
</tr>
</table>
</div>
<h3>通信流程</h3>
<div class="diagram"><span class="dim">场景:用户在手机上找电脑文件</span>
手机客户端 Gateway 电脑客户端
│ │ │
│ ① 用户操作/发消息 │ │
│ ──WS──▶ │ │
│ ② AI 调用 MCP Tool │ │
│ file_list("pc-1") │ │
│ │ ③ 转发到电脑客户端 │
│ │ ──MCP──▶ │
│ │ ④ 电脑执行 file_list│
│ │ 本地文件系统操作 │
│ │ ◀──结果── │
│ ◀──结果── │ │
│ ⑤ 返回给手机 │ │
│ ◀──结果── │ │
│ │ │
<span class="dim">场景:用户在电脑上看手机屏幕</span>
电脑客户端 Gateway 手机客户端
│ │ │
│ ① 调用 screenshot("phone") │ │
│ ──WS──▶ │ │
│ ② 转发到手机客户端 │ │
│ │ ──MCP──▶ │
│ │ ③ 手机截屏 │
│ │ ◀──base64─ │
│ ◀──图片── │ │
│ ④ 显示手机屏幕 │ │
│ ◀──图片── │ │</div>
</div>
</div>
<footer>
<a href="../index.html">← 返回首页</a> &nbsp;|&nbsp;
<a href="../capabilities/index.html">能力全景 →</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

164
docs/backlog/index.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>开发代办清单 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">开发代办</span>
</div>
<div class="container">
<h1>开发代办清单</h1>
<p class="subtitle">按模块拆分,每个功能独立任务</p>
<div class="summary-bar">
<div class="s-item"><div class="num" style="color:var(--accent)">6</div><div class="label">模块</div></div>
<div class="s-item"><div class="num" style="color:var(--green)">55</div><div class="label">任务总数</div></div>
<div class="s-item"><div class="num" style="color:var(--red)">15</div><div class="label">P0</div></div>
<div class="s-item"><div class="num" style="color:var(--orange)">20</div><div class="label">P1</div></div>
<div class="s-item"><div class="num" style="color:var(--accent2)">20</div><div class="label">P2</div></div>
</div>
<!-- 模块 1 -->
<div class="module">
<h2><span class="dot" style="background:var(--accent)"></span> 模块 1shared — 共享类型与协议</h2>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>S-001</td><td>定义 MCP Tool 类型</td><td>36 个 Tool 的 TypeScript 类型name、inputSchema、outputSchema</td><td><span class="tag t-red">P0</span></td><td></td></tr>
<tr><td>S-002</td><td>定义设备配置类型</td><td>设备信息、连接配置、代理配置接口</td><td><span class="tag t-red">P0</span></td><td></td></tr>
<tr><td>S-003</td><td>定义数据通道协议</td><td>屏幕推流、文件传输、键鼠事件的 WS 消息格式</td><td><span class="tag t-orange">P1</span></td><td></td></tr>
<tr><td>S-004</td><td>定义客户端状态类型</td><td>连接状态、Tailscale 状态、设备在线状态枚举</td><td><span class="tag t-orange">P1</span></td><td></td></tr>
<tr><td>S-005</td><td>JSON Schema 生成</td><td>从 TypeScript 类型自动生成 JSON Schema</td><td><span class="tag t-purple">P2</span></td><td>S-001</td></tr>
</table>
</div>
<!-- 模块 2 -->
<div class="module">
<h2><span class="dot" style="background:var(--green)"></span> 模块 2client/server — MCP Server 核心</h2>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>C-001</td><td>MCP Server 框架</td><td>用 @modelcontextprotocol/sdk 搭建基础框架SSE 传输</td><td><span class="tag t-red">P0</span></td><td>S-001</td></tr>
<tr><td>C-002</td><td>file_list Tool</td><td>列出目录内容,支持 glob 过滤和递归</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-003</td><td>file_read Tool</td><td>读取文件内容,支持行范围</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-004</td><td>file_write Tool</td><td>写入/创建文件</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-005</td><td>file_move Tool</td><td>移动/重命名文件</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-006</td><td>file_delete Tool</td><td>删除文件</td><td><span class="tag t-orange">P1</span></td><td>C-001</td></tr>
<tr><td>C-007</td><td>file_transfer Tool</td><td>跨设备文件传输(通过 WS 数据端口)</td><td><span class="tag t-purple">P2</span></td><td>C-001, S-003</td></tr>
<tr><td>C-008</td><td>exec Tool</td><td>执行命令并返回结果,支持超时</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-009</td><td>exec_background Tool</td><td>后台执行长时间命令,返回任务 ID</td><td><span class="tag t-orange">P1</span></td><td>C-008</td></tr>
<tr><td>C-010</td><td>process_list Tool</td><td>列出进程,支持 CPU/内存排序</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-011</td><td>sysinfo Tool</td><td>返回 CPU/内存/磁盘/网络/运行时间</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-012</td><td>power Tool</td><td>关机/重启/休眠/WoL</td><td><span class="tag t-orange">P1</span></td><td>C-001</td></tr>
<tr><td>C-013</td><td>service Tool</td><td>系统服务管理(启动/停止/重启/状态)</td><td><span class="tag t-orange">P1</span></td><td>C-001</td></tr>
<tr><td>C-014</td><td>notify_send Tool</td><td>发送桌面通知</td><td><span class="tag t-orange">P1</span></td><td>C-001</td></tr>
<tr><td>C-015</td><td>Gateway 注册与自动连接</td><td>客户端启动时 SSE 注册到 Gateway支持自动重连</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>C-016</td><td>独立代理支持</td><td>SOCKS5/HTTP 代理,只代理自身连接</td><td><span class="tag t-orange">P1</span></td><td>C-015</td></tr>
<tr><td>C-017</td><td>MCP Resources</td><td>device://list、device://{id}/status 资源暴露</td><td><span class="tag t-purple">P2</span></td><td>C-001</td></tr>
<tr><td>C-018</td><td>MCP Prompts</td><td>troubleshoot、optimize 预置提示词</td><td><span class="tag t-purple">P2</span></td><td>C-001</td></tr>
</table>
</div>
<!-- 模块 3 -->
<div class="module">
<h2><span class="dot" style="background:var(--accent2)"></span> 模块 3client/platform — 平台适配</h2>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>P-001</td><td>Windows 平台适配</td><td>屏幕捕获、系统信息、命令执行的 Windows 实现</td><td><span class="tag t-red">P0</span></td><td>C-001</td></tr>
<tr><td>P-002</td><td>Linux 平台适配</td><td>复用 Windows 代码,适配 Linux 路径和命令</td><td><span class="tag t-orange">P1</span></td><td>P-001</td></tr>
<tr><td>P-003</td><td>macOS 平台适配</td><td>复用代码,适配 macOS 特定 API</td><td><span class="tag t-purple">P2</span></td><td>P-001</td></tr>
<tr><td>P-004</td><td>Android 平台适配</td><td>React Native 环境下的文件/进程/系统信息</td><td><span class="tag t-orange">P1</span></td><td>P-001</td></tr>
<tr><td>P-005</td><td>CLI 平台适配</td><td>无 UI 版Node.js CLI 入口systemd/Docker 部署</td><td><span class="tag t-orange">P1</span></td><td>C-001</td></tr>
<tr><td>P-006</td><td>连接生命周期 — 通联检测</td><td>启动时测试 Gateway 是否可达</td><td><span class="tag t-red">P0</span></td><td>C-015</td></tr>
<tr><td>P-007</td><td>连接生命周期 — Tailscale 管理</td><td>按需启停 Tailscale记录 started_by_us 状态</td><td><span class="tag t-orange">P1</span></td><td>P-006</td></tr>
<tr><td>P-008</td><td>连接生命周期 — 心跳保活</td><td>每 30s ping连续 3 次无响应判定断开</td><td><span class="tag t-red">P0</span></td><td>C-015</td></tr>
<tr><td>P-009</td><td>连接生命周期 — 断线重连</td><td>指数退避重连1s→2s→4s→...→60s</td><td><span class="tag t-red">P0</span></td><td>P-008</td></tr>
<tr><td>P-010</td><td>连接生命周期 — 退出恢复</td><td>退出时恢复 Tailscale 到进入前状态</td><td><span class="tag t-orange">P1</span></td><td>P-007</td></tr>
<tr><td>P-011</td><td>配置管理</td><td>本地 JSON 配置读写、系统 keychain 凭据存储</td><td><span class="tag t-orange">P1</span></td><td>S-002</td></tr>
</table>
</div>
<!-- 模块 4 -->
<div class="module">
<h2><span class="dot" style="background:var(--pink)"></span> 模块 4client/ui — 客户端界面</h2>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>U-001</td><td>设置页面</td><td>Gateway 地址、token、代理、设备名称配置</td><td><span class="tag t-red">P0</span></td><td>P-011</td></tr>
<tr><td>U-002</td><td>连接状态指示器</td><td>顶部状态栏显示 Gateway 连接状态、Tailscale 状态</td><td><span class="tag t-orange">P1</span></td><td>P-008</td></tr>
<tr><td>U-003</td><td>设备列表页面</td><td>所有设备卡片名称、在线状态、CPU/内存/磁盘概览)</td><td><span class="tag t-orange">P1</span></td><td>C-015</td></tr>
<tr><td>U-004</td><td>设备详情页面</td><td>单设备完整信息(进程列表、系统信息、网络状态)</td><td><span class="tag t-purple">P2</span></td><td>U-003</td></tr>
<tr><td>U-005</td><td>文件浏览器</td><td>远程目录树、文件列表、面包屑导航</td><td><span class="tag t-orange">P1</span></td><td>C-002</td></tr>
<tr><td>U-006</td><td>文件查看器</td><td>文本文件查看、图片预览</td><td><span class="tag t-purple">P2</span></td><td>U-005</td></tr>
<tr><td>U-007</td><td>文件上传/下载</td><td>拖拽上传、下载进度条</td><td><span class="tag t-purple">P2</span></td><td>U-005, C-007</td></tr>
<tr><td>U-008</td><td>远程终端</td><td>命令输入框、输出显示、历史记录</td><td><span class="tag t-orange">P1</span></td><td>C-008</td></tr>
<tr><td>U-009</td><td>远程桌面视图</td><td>屏幕推流显示区域</td><td><span class="tag t-purple">P2</span></td><td>S-003</td></tr>
<tr><td>U-010</td><td>远程桌面输入</td><td>鼠标点击/移动/滚动、键盘输入转发</td><td><span class="tag t-purple">P2</span></td><td>U-009</td></tr>
<tr><td>U-011</td><td>远程桌面工具栏</td><td>全屏、缩放、剪贴板同步、快捷键</td><td><span class="tag t-purple">P2</span></td><td>U-009</td></tr>
<tr><td>U-012</td><td>AI 聊天界面</td><td>消息列表、输入框、Markdown 渲染</td><td><span class="tag t-orange">P1</span></td><td>C-015</td></tr>
</table>
</div>
<!-- 模块 5 -->
<div class="module">
<h2><span class="dot" style="background:var(--orange)"></span> 模块 5远程控制与 AI 操控</h2>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>R-001</td><td>screenshot Tool</td><td>截取屏幕,返回 base64 JPEG</td><td><span class="tag t-orange">P1</span></td><td>P-001</td></tr>
<tr><td>R-002</td><td>remote_input Tool</td><td>鼠标移动/点击/滚动/拖拽、键盘输入/按键/快捷键</td><td><span class="tag t-orange">P1</span></td><td>P-001</td></tr>
<tr><td>R-003</td><td>clipboard_sync Tool</td><td>剪贴板读写/同步</td><td><span class="tag t-orange">P1</span></td><td>P-001</td></tr>
<tr><td>R-004</td><td>remote_stream Tool</td><td>开始/停止屏幕推流WS 数据端口</td><td><span class="tag t-purple">P2</span></td><td>R-001, S-003</td></tr>
<tr><td>R-005</td><td>ui_find Tool</td><td>通过 Accessibility API 查找 UI 元素</td><td><span class="tag t-purple">P2</span></td><td>P-001</td></tr>
<tr><td>R-006</td><td>ui_act Tool</td><td>操作 UI 元素(点击/输入/选择/读取)</td><td><span class="tag t-purple">P2</span></td><td>R-005</td></tr>
<tr><td>R-007</td><td>browser_open Tool</td><td>打开 URL / 操控远端浏览器</td><td><span class="tag t-purple">P2</span></td><td>C-001</td></tr>
<tr><td>R-008</td><td>browser_act Tool</td><td>浏览器内操作(填写/点击/截图/获取文本)</td><td><span class="tag t-purple">P2</span></td><td>R-007</td></tr>
<tr><td>R-009</td><td>ocr_screen Tool</td><td>屏幕 OCR 文字识别</td><td><span class="tag t-purple">P2</span></td><td>R-001</td></tr>
</table>
</div>
<!-- 模块 6 -->
<div class="module">
<h2><span class="dot" style="background:var(--accent3)"></span> 模块 6OTA 更新与 CI/CD</h2>
<p style="color:var(--dim);font-size:.85rem;margin-bottom:12px">策略:小更新 JS bundle OTA 静默推送,大更新 APK 重装。</p>
<table class="task-table">
<tr><th>编号</th><th>任务</th><th>说明</th><th>优先级</th><th>依赖</th></tr>
<tr><td>O-001</td><td>CI/CD 流水线</td><td>push tag → 自动构建 Desktop + Android + CLI</td><td><span class="tag t-orange">P1</span></td><td></td></tr>
<tr><td>O-002</td><td>Android JS bundle OTA</td><td>expo-updates启动检查 + 每 24h 检查 → 静默下载 JS bundle → 下次打开生效</td><td><span class="tag t-orange">P1</span></td><td>O-001</td></tr>
<tr><td>O-003</td><td>Desktop 自动更新</td><td>Tauri updater检查 latest.json → 后台下载 APK → 静默安装</td><td><span class="tag t-orange">P1</span></td><td>O-001</td></tr>
<tr><td>O-004</td><td>CLI 自动更新</td><td>gca-cli update 命令,下载最新版本并替换</td><td><span class="tag t-purple">P2</span></td><td>O-001</td></tr>
<tr><td>O-005</td><td>OTA 发布脚本</td><td>一键导出 JS bundle 并上传到 Gitee 静态仓库</td><td><span class="tag t-orange">P1</span></td><td>O-002</td></tr>
</table>
</div>
<!-- 开发顺序 -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 建议开发顺序</h2>
<div class="table-wrap">
<table>
<tr><th>批次</th><th>任务</th><th>产出</th></tr>
<tr><td><b>第 1 批</b></td><td>S-001, S-002, U-001</td><td>类型定义 + 设置页面</td></tr>
<tr><td><b>第 2 批</b></td><td>C-001~C-005, C-008, C-010, C-011</td><td>MCP Server 核心 8 个 Tool</td></tr>
<tr><td><b>第 3 批</b></td><td>P-001, P-006, P-008, P-009, C-015</td><td>Windows 适配 + 连接生命周期</td></tr>
<tr><td><b>第 4 批</b></td><td>U-002, U-003, U-005, U-008, U-012</td><td>核心 UI设备列表/文件/终端/聊天)</td></tr>
<tr><td><b>第 5 批</b></td><td>C-006, C-009, C-012~C-016, P-011</td><td>扩展 Tool + 代理 + 配置</td></tr>
<tr><td><b>第 6 批</b></td><td>R-001~R-003, P-002, P-005</td><td>远程控制基础 + Linux/CLI 适配</td></tr>
<tr><td><b>第 7 批</b></td><td>R-004, S-003, U-009~U-011</td><td>屏幕推流 + 远程桌面 UI</td></tr>
<tr><td><b>第 8 批</b></td><td>U-004, U-006, U-007, C-007, C-017, C-018</td><td>设备详情/文件查看/Resources</td></tr>
<tr><td><b>第 9 批</b></td><td>R-005~R-009, P-004</td><td>AI 操控 + Android 适配</td></tr>
<tr><td><b>第 10 批</b></td><td>O-001~O-005, S-005, P-003</td><td>CI/CD + OTA + macOS</td></tr>
</table>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a> &nbsp;|&nbsp; <a href="../roadmap/index.html">路线图</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

View File

@@ -0,0 +1,343 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>能力全景 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
<style>
.cat{margin-bottom:40px}
.cat-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid var(--border)}
.cat-icon{width:36px;height:36px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1.3rem;flex-shrink:0}
.cat-header h2{font-size:1.2rem;flex:1;margin:0}
.cat-header .count{font-size:.72rem;padding:3px 10px;border-radius:12px;background:rgba(255,255,255,.05);color:var(--dim);flex-shrink:0}
.tool-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
.tool{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px;transition:all .3s}
.tool:hover{border-color:var(--accent)}
.tool h4{font-size:.9rem;margin-bottom:4px;font-family:'Cascadia Code','Fira Code','Consolas',monospace;color:var(--green)}
.tool p{color:var(--dim);font-size:.8rem;line-height:1.4;margin-bottom:6px}
.tool .params{font-size:.75rem;color:var(--dim);font-family:'Cascadia Code','Fira Code','Consolas',monospace;background:rgba(0,0,0,.2);padding:6px 10px;border-radius:6px;line-height:1.6}
</style>
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">能力全景</span>
</div>
<div class="container">
<h1>MCP Tools 能力全景</h1>
<p class="subtitle">客户端MCP Server暴露给 Gateway 的全部工具AI 自动调用</p>
<div class="summary-bar">
<div class="s-item"><div class="num" style="color:var(--accent)">4</div><div class="label">设备管理</div></div>
<div class="s-item"><div class="num" style="color:var(--green)">3</div><div class="label">命令执行</div></div>
<div class="s-item"><div class="num" style="color:var(--accent3)">6</div><div class="label">文件操作</div></div>
<div class="s-item"><div class="num" style="color:var(--orange)">3</div><div class="label">系统控制</div></div>
<div class="s-item"><div class="num" style="color:var(--pink)">4</div><div class="label">远程桌面</div></div>
<div class="s-item"><div class="num" style="color:var(--accent2)">5</div><div class="label">AI 操控</div></div>
<div class="s-item"><div class="num" style="color:var(--teal)">3</div><div class="label">网络</div></div>
<div class="s-item"><div class="num" style="color:var(--lime)">3</div><div class="label">硬件</div></div>
<div class="s-item"><div class="num" style="color:var(--sky)">3</div><div class="label">开发工具</div></div>
<div class="s-item"><div class="num" style="color:var(--red)">2</div><div class="label">媒体</div></div>
</div>
<!-- 1. 设备管理 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(59,130,246,.15)">📱</div>
<h2>设备管理</h2>
<span class="count">4 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>device_list</h4>
<p>列出所有已注册设备及在线状态</p>
<div class="params">无参数</div>
</div>
<div class="tool">
<h4>device_info</h4>
<p>获取指定设备的详细信息OS、IP、资源使用</p>
<div class="params">device: string</div>
</div>
<div class="tool">
<h4>device_add</h4>
<p>添加新设备配置(客户端自动注册,此 Tool 用于手动注册 CLI 设备)</p>
<div class="params">id, name, url: string</div>
</div>
<div class="tool">
<h4>device_remove</h4>
<p>移除设备配置</p>
<div class="params">device: string</div>
</div>
</div>
</div>
<!-- 2. 命令执行 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(34,197,94,.15)">💻</div>
<h2>命令执行</h2>
<span class="count">3 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>exec</h4>
<p>在指定设备上执行命令并等待结果</p>
<div class="params">device: string, command: string, timeout?: number</div>
</div>
<div class="tool">
<h4>exec_background</h4>
<p>后台执行长时间命令,返回任务 ID</p>
<div class="params">device: string, command: string</div>
</div>
<div class="tool">
<h4>process_list</h4>
<p>列出指定设备上的进程(支持按 CPU/内存排序)</p>
<div class="params">device: string, sort?: "cpu" | "memory", limit?: number</div>
</div>
</div>
</div>
<!-- 3. 文件操作 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(6,182,212,.15)">📁</div>
<h2>文件操作</h2>
<span class="count">6 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>file_list</h4>
<p>列出目录内容(支持 glob 过滤和递归)</p>
<div class="params">device: string, path: string, pattern?: string, recursive?: boolean</div>
</div>
<div class="tool">
<h4>file_read</h4>
<p>读取文件内容(支持行范围读取)</p>
<div class="params">device: string, path: string, offset?: number, limit?: number</div>
</div>
<div class="tool">
<h4>file_write</h4>
<p>写入/创建文件</p>
<div class="params">device: string, path: string, content: string</div>
</div>
<div class="tool">
<h4>file_move</h4>
<p>移动/重命名文件</p>
<div class="params">device: string, from: string, to: string</div>
</div>
<div class="tool">
<h4>file_delete</h4>
<p>删除文件</p>
<div class="params">device: string, path: string</div>
</div>
<div class="tool">
<h4>file_transfer</h4>
<p>跨设备文件传输(从源设备传到目标设备)</p>
<div class="params">from_device: string, from_path: string, to_device: string, to_path: string</div>
</div>
</div>
</div>
<!-- 4. 系统控制 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(245,158,11,.15)">⚙️</div>
<h2>系统控制</h2>
<span class="count">3 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>sysinfo</h4>
<p>获取系统信息CPU/内存/磁盘/网络/运行时间)</p>
<div class="params">device: string</div>
</div>
<div class="tool">
<h4>power</h4>
<p>电源操作(关机/重启/休眠/Wake-on-LAN</p>
<div class="params">device: string, action: "shutdown" | "restart" | "hibernate" | "wol"</div>
</div>
<div class="tool">
<h4>service</h4>
<p>系统服务管理(启动/停止/重启/查看状态)</p>
<div class="params">device: string, name: string, action: "start" | "stop" | "restart" | "status"</div>
</div>
</div>
</div>
<!-- 5. 远程桌面 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(236,72,153,.15)">🖱️</div>
<h2>远程桌面(人工操控)</h2>
<span class="count">4 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>screenshot</h4>
<p>截取远程设备屏幕画面(返回 base64 图片)</p>
<div class="params">device: string, display?: number, quality?: number</div>
</div>
<div class="tool">
<h4>remote_input</h4>
<p>发送鼠标/键盘事件到远程设备</p>
<div class="params">device: string, type: "mouse_move" | "mouse_click" | "mouse_scroll" | "key_type" | "key_press" | "hotkey", ...</div>
</div>
<div class="tool">
<h4>remote_stream</h4>
<p>开始/停止屏幕推流(返回 WS 数据端口地址)</p>
<div class="params">device: string, action: "start" | "stop", fps?: number, quality?: number</div>
</div>
<div class="tool">
<h4>clipboard_sync</h4>
<p>读取/设置远程设备剪贴板,跨设备同步</p>
<div class="params">device: string, action: "get" | "set" | "sync", content?: string</div>
</div>
</div>
</div>
<!-- 6. AI 应用操控 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(139,92,246,.15)">🤖</div>
<h2>AI 应用操控</h2>
<span class="count">5 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>ui_find</h4>
<p>通过 Accessibility API 查找应用内的 UI 元素</p>
<div class="params">device: string, app: string, element: string, role?: string</div>
</div>
<div class="tool">
<h4>ui_act</h4>
<p>操作 UI 元素(点击/输入/选择/读取)</p>
<div class="params">device: string, element_id: string, action: "click" | "set_value" | "get_value"</div>
</div>
<div class="tool">
<h4>browser_open</h4>
<p>在远程设备上打开 URL 或操控已打开的浏览器</p>
<div class="params">device: string, url?: string, attach?: boolean</div>
</div>
<div class="tool">
<h4>browser_act</h4>
<p>浏览器内操作(填写表单/点击元素/截图/获取文本)</p>
<div class="params">device: string, action: "fill" | "click" | "screenshot" | "get_text", selector?: string, value?: string</div>
</div>
<div class="tool">
<h4>ocr_screen</h4>
<p>对远程设备屏幕进行 OCR 文字识别</p>
<div class="params">device: string, region?: { x, y, width, height }</div>
</div>
</div>
</div>
<!-- 7. 网络管理 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(20,184,166,.15)">🌍</div>
<h2>网络管理</h2>
<span class="count">3 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>net_status</h4>
<p>网络状态(接口/IP/连通性/流量)</p>
<div class="params">device: string</div>
</div>
<div class="tool">
<h4>net_wifi</h4>
<p>WiFi 管理(扫描/连接/列出已保存网络)</p>
<div class="params">device: string, action: "scan" | "connect" | "list", ssid?: string, password?: string</div>
</div>
<div class="tool">
<h4>net_ping</h4>
<p>网络诊断ping/traceroute/DNS 查询)</p>
<div class="params">device: string, target: string, action?: "ping" | "traceroute" | "dns"</div>
</div>
</div>
</div>
<!-- 8. 硬件监控 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(132,204,22,.15)">🔧</div>
<h2>硬件监控</h2>
<span class="count">3 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>hw_temps</h4>
<p>温度监控CPU/GPU/磁盘温度)</p>
<div class="params">device: string</div>
</div>
<div class="tool">
<h4>hw_battery</h4>
<p>电池状态(电量/充电状态/健康度)</p>
<div class="params">device: string</div>
</div>
<div class="tool">
<h4>hw_disk</h4>
<p>磁盘信息(分区/使用量/SMART 数据)</p>
<div class="params">device: string</div>
</div>
</div>
</div>
<!-- 9. 开发者工具 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(14,165,233,.15)">🛠️</div>
<h2>开发者工具</h2>
<span class="count">3 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>docker_ps</h4>
<p>Docker 容器管理(列表/启动/停止/重启/日志)</p>
<div class="params">device: string, action: "list" | "start" | "stop" | "restart" | "logs", container?: string</div>
</div>
<div class="tool">
<h4>git_op</h4>
<p>Git 操作status/pull/push/log</p>
<div class="params">device: string, repo: string, action: "status" | "pull" | "push" | "log"</div>
</div>
<div class="tool">
<h4>log_read</h4>
<p>读取系统/应用日志</p>
<div class="params">device: string, source: string, lines?: number, filter?: string</div>
</div>
</div>
</div>
<!-- 10. 媒体通信 -->
<div class="cat">
<div class="cat-header">
<div class="cat-icon" style="background:rgba(239,68,68,.15)">🎬</div>
<h2>媒体通信</h2>
<span class="count">2 tools</span>
</div>
<div class="tool-grid">
<div class="tool">
<h4>media_control</h4>
<p>媒体播放控制(播放/暂停/下一曲/音量)</p>
<div class="params">device: string, action: "play" | "pause" | "next" | "prev" | "volume", value?: number</div>
</div>
<div class="tool">
<h4>notify_send</h4>
<p>发送桌面通知到指定设备</p>
<div class="params">device: string, title: string, body?: string</div>
</div>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a> &nbsp;|&nbsp; <a href="../roadmap/index.html">路线图</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

374
docs/flow/index.html Normal file
View File

@@ -0,0 +1,374 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统流程 — Global Control Assistant</title>
<link rel="stylesheet" href="style.css">
<style>
.flow-section{margin-bottom:40px}
.flow-section h2{font-size:1.2rem;margin-bottom:16px;display:flex;align-items:center;gap:8px}
.flow-box{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:20px;margin-bottom:16px}
.flow-box h4{font-size:.95rem;margin-bottom:8px;color:var(--accent)}
.flow-box p{color:var(--dim);font-size:.85rem;line-height:1.6}
.step-list{list-style:none;counter-reset:step}
.step-list li{counter-increment:step;padding:10px 14px;margin-bottom:8px;background:rgba(255,255,255,.02);border-radius:8px;font-size:.85rem;color:var(--dim);line-height:1.5;display:flex;align-items:flex-start;gap:10px}
.step-list li::before{content:counter(step);min-width:24px;height:24px;border-radius:50%;background:var(--accent);color:white;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:700;flex-shrink:0}
.step-list li b{color:var(--text)}
.diagram-box{background:#0d1117;border:1px solid var(--border);border-radius:12px;padding:20px;font-family:'Cascadia Code','Fira Code',monospace;font-size:.78rem;line-height:1.6;overflow-x:auto;white-space:pre;color:#c9d1d9;margin-bottom:16px}
.tag{display:inline-block;padding:2px 8px;border-radius:6px;font-size:.7rem;font-weight:600}
.t-green{background:rgba(34,197,94,.15);color:var(--green)}
.t-blue{background:rgba(59,130,246,.15);color:var(--accent)}
.t-orange{background:rgba(245,158,11,.15);color:var(--orange)}
.t-pink{background:rgba(236,72,153,.15);color:var(--pink)}
</style>
</head>
<body>
<div class="topbar">
<a href="index.html">首页</a><span class="sep">/</span>
<a href="architecture/index.html">架构</a><span class="sep">/</span>
<a href="capabilities/index.html">能力</a><span class="sep">/</span>
<a href="roadmap/index.html">路线图</a><span class="sep">/</span>
<a href="backlog/index.html">代办</a><span class="sep">/</span>
<a href="security/index.html">安全</a><span class="sep">/</span>
<span class="current">流程</span>
</div>
<div class="container">
<h1>系统流程</h1>
<p class="subtitle">GCA 系统中各个核心流程的完整走查</p>
<!-- ===== 1. 客户端启动流程 ===== -->
<div class="flow-section">
<h2>1. 客户端启动流程</h2>
<div class="flow-box">
<h4>客户端打开后的完整启动链路</h4>
<ol class="step-list">
<li><b>App 启动</b> → 加载本地配置Gateway 地址、Token、代理设置</li>
<li><b>启动 MCP Server</b> → 客户端内置 MCP Server 开始监听暴露本机能力file/exec/screen/sysinfo 等)</li>
<li><b>连接 Gateway</b> → WebSocket 连接 OpenClaw Gateway发送认证 Token</li>
<li><b>注册设备</b> → 向 Gateway 报告设备信息名称、IP、OS、能力列表</li>
<li><b>开始心跳</b> → 每 30 秒发送心跳Gateway 更新设备在线状态</li>
<li><b>OTA 检查</b> → 启动 3 秒后检查一次更新,之后每 24 小时检查一次</li>
<li><b>就绪</b> → 设备出现在 Gateway 设备列表中,可被 AI 或其他设备调用</li>
</ol>
</div>
<div class="diagram-box">客户端启动
├── 1. 读取本地配置
│ └── Gateway URL / Token / 代理 / 设备名
├── 2. 启动 MCP Server
│ └── 注册 36 个 MCP Tools (file/exec/screen/sysinfo/...)
├── 3. 连接 OpenClaw Gateway
│ ├── WebSocket → ws://gateway:port
│ └── 发送认证 Token
├── 4. 注册设备
│ └── { name, ip, os, capabilities }
├── 5. 心跳循环 (30s)
│ └── 持续上报设备状态
└── 6. OTA 检查 (启动后 3s + 每 24h)
└── expo-updates 检查 → 静默下载 JS bundle</div>
</div>
<!-- ===== 2. AI 控制设备流程 ===== -->
<div class="flow-section">
<h2>2. AI 控制设备流程</h2>
<div class="flow-box">
<h4>用户通过任意通道发送自然语言指令</h4>
<ol class="step-list">
<li><b>用户发消息</b> → 通过微信/飞书/Telegram/自建客户端发送:"看看服务器磁盘满了没"</li>
<li><b>Gateway 接收</b> → OpenClaw Gateway 的 AI Agent 接收消息,理解意图</li>
<li><b>AI 选择工具</b> → AI 决定调用 <code>exec</code> 工具,参数 <code>device="cloud-svr", command="df -h"</code></li>
<li><b>Gateway 路由</b> → Gateway 将 MCP Tool 调用转发到 cloud-svr 客户端</li>
<li><b>客户端执行</b> → cloud-svr 的 MCP Server 执行 <code>df -h</code>,返回磁盘信息</li>
<li><b>AI 格式化</b> → AI 将原始数据格式化为易读的回复</li>
<li><b>回复用户</b> → 通过原通道返回结果给用户</li>
</ol>
</div>
<div class="diagram-box">用户: "看看服务器磁盘满了没"
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 任意通道 │───▶│ Gateway │───▶│ cloud-svr │
│ 微信/飞书/ │ │ AI Agent │ │ 客户端 │
│ Telegram │ │ │ │ MCP Server │
└─────────────┘ └──────┬──────┘ └──────┬──────┘
│ │
│ MCP Tool 调用 │
│ exec("df -h") │
│──────────────────▶│
│ │
│ 执行结果 │
│◀──────────────────│
│ │
│ AI 格式化回复 │
▼ │
"磁盘使用率 78%
剩余 120GB" │
│ │
▼ │
回复给用户 │</div>
</div>
<!-- ===== 3. 人工远程控制流程 ===== -->
<div class="flow-section">
<h2>3. 人工远程控制流程</h2>
<div class="flow-box">
<h4>用户通过客户端直接操控远端设备(类 TeamViewer</h4>
<ol class="step-list">
<li><b>选择设备</b> → 在客户端设备列表中点击目标设备</li>
<li><b>发起远程桌面</b> → 客户端发送 <code>screen_stream_start</code> 请求</li>
<li><b>建立数据通道</b> → 客户端与目标设备建立 WebSocket 直连(不经过 Gateway低延迟</li>
<li><b>屏幕推流</b> → 目标设备以 MJPEG 格式推流15-30fps</li>
<li><b>输入转发</b> → 用户的鼠标/键盘操作通过数据通道实时转发到目标设备</li>
<li><b>剪贴板同步</b> → 双向剪贴板同步(可选)</li>
<li><b>结束</b> → 用户断开,数据通道关闭</li>
</ol>
</div>
<div class="diagram-box">用户客户端 Gateway 目标设备
│ │ │
│ ① 请求远程桌面 │ │
│ MCP: screen_stream_start │ │
│───────────────────────────▶│ │
│ │ ② 转发请求 │
│ │─────────────────────────▶│
│ │ │
│ │ ③ 返回数据通道地址 │
│ │◀─────────────────────────│
│ ④ 数据通道地址 │ │
│◀───────────────────────────│ │
│ │
│ ⑤ 直连数据通道 (WebSocket) │
│◀══════════════════════════════════════════════════════▶│
│ │
│ ⑥ 屏幕推流 (MJPEG 15-30fps) │
│◀──────────────────────────────────────────────────────│
│ │
│ ⑦ 鼠标/键盘事件 │
│───────────────────────────────────────────────────────▶│
│ │
│ ⑧ 剪贴板同步 (可选) │
│◀══════════════════════════════════════════════════════▶│</div>
</div>
<!-- ===== 4. AI 自动操控应用流程 ===== -->
<div class="flow-section">
<h2>4. AI 自动操控应用流程</h2>
<div class="flow-box">
<h4>AI 代理自动操作设备上的应用(无需人工干预)</h4>
<ol class="step-list">
<li><b>用户指令</b> → "帮我打开 Chrome搜索今天的天气"</li>
<li><b>AI 分解任务</b> → ① 启动 Chrome ② 打开 Google ③ 输入搜索词 ④ 点击搜索</li>
<li><b>执行 Step 1</b> → MCP Tool: <code>exec("home-pc", "start chrome")</code></li>
<li><b>执行 Step 2</b> → MCP Tool: <code>browser_open("home-pc", "https://google.com")</code></li>
<li><b>执行 Step 3</b> → MCP Tool: <code>browser_fill("home-pc", "input[name=q]", "今天天气")</code></li>
<li><b>执行 Step 4</b> → MCP Tool: <code>browser_click("home-pc", "input[name=btnK]")</code></li>
<li><b>返回结果</b> → 截图返回给用户</li>
</ol>
</div>
<div class="diagram-box">用户: "帮我打开 Chrome搜索今天的天气"
AI Agent 分解任务:
├── Step 1: exec("home-pc", "start chrome")
├── Step 2: browser_open("home-pc", "https://google.com")
├── Step 3: browser_fill("home-pc", "input[name=q]", "今天天气")
├── Step 4: browser_click("home-pc", "input[name=btnK]")
└── Step 5: screenshot("home-pc") → 返回截图给用户
每个 Step 都是 MCP Tool 调用,通过 Gateway 路由到 home-pc 客户端执行</div>
</div>
<!-- ===== 5. 跨设备文件传输流程 ===== -->
<div class="flow-section">
<h2>5. 跨设备文件传输流程</h2>
<div class="flow-box">
<h4>从一台设备传输文件到另一台设备</h4>
<ol class="step-list">
<li><b>用户指令</b> → "把 NAS 上的 backup.zip 传到电脑桌面"</li>
<li><b>AI 调用</b> → MCP Tool: <code>file_transfer("nas", "/backup/backup.zip", "home-pc", "C:\\Desktop\\")</code></li>
<li><b>Gateway 协调</b> → Gateway 分别连接 NAS 和 home-pc 的 MCP Server</li>
<li><b>NAS 读取</b> → NAS 客户端读取文件,通过数据通道流式传输</li>
<li><b>PC 写入</b> → home-pc 客户端接收并写入目标路径</li>
<li><b>完成</b> → 返回传输结果(文件大小、耗时)</li>
</ol>
</div>
<div class="diagram-box">用户: "把 NAS 上的 backup.zip 传到电脑桌面"
Gateway AI → file_transfer("nas", "/backup.zip", "home-pc", "C:\Desktop\")
├── NAS 客户端 Gateway home-pc 客户端
│ │ │ │
│ │ ① 读取文件 │ │
│ │◀──────────────────│ │
│ │ │ │
│ │ ② 流式传输 │ │
│ │──────────────────▶│ │
│ │ │ ③ 写入文件 │
│ │ │─────────────────────▶│
│ │ │ │
│ │ │ ④ 完成确认 │
│ │ │◀─────────────────────│
│ │ │ │
└─────┴───────────────────┴──────────────────────┘
"传输完成128MB耗时 3.2s"</div>
</div>
<!-- ===== 6. OTA 更新流程 ===== -->
<div class="flow-section">
<h2>6. OTA 更新流程</h2>
<div class="flow-box">
<h4>JS bundle 静默更新(小更新)</h4>
<ol class="step-list">
<li><b>开发者修改代码</b> → 修改 JS/TS 代码(新增页面、修 Bug、改 UI</li>
<li><b>导出 bundle</b><code>npx expo export --platform android</code> 生成 JS bundle</li>
<li><b>上传到 Gitee</b> → 将 bundle 上传到 Gitee 静态仓库</li>
<li><b>App 检查更新</b> → 启动时 + 每 24 小时自动检查</li>
<li><b>静默下载</b> → 发现新版,后台下载 JS bundle~1-2MB</li>
<li><b>下次启动生效</b> → 用户下次打开 App 自动使用新版本</li>
</ol>
</div>
<div class="flow-box">
<h4>APK 重装(大更新)</h4>
<ol class="step-list">
<li><b>开发者修改原生代码</b> → 新增原生模块、改图标、升级 RN</li>
<li><b>构建 APK</b><code>eas build -p android --profile preview</code></li>
<li><b>发布到 Gitee</b> → 上传 APK 到 Releases</li>
<li><b>通知用户</b> → App 内提示有新版本</li>
<li><b>用户手动安装</b> → 下载 APK 并安装</li>
</ol>
</div>
<div class="diagram-box">小更新 (JS bundle OTA):
开发者 → expo export → 上传 Gitee → App 自动检查 → 静默下载 → 下次启动生效
用户无感1-2MB几秒钟完成
大更新 (APK 重装):
开发者 → eas build → 上传 Gitee Releases → App 提示 → 用户手动下载安装
需要用户操作15-30MB</div>
</div>
<!-- ===== 7. 多通道记忆流程 ===== -->
<div class="flow-section">
<h2>7. 多通道记忆流程</h2>
<div class="flow-box">
<h4>用户在不同通道的对话如何统一记忆</h4>
<ol class="step-list">
<li><b>身份映射</b> → OpenClaw 的 <code>identityLinks</code> 将微信/飞书/Telegram 账号映射为同一用户</li>
<li><b>会话共享</b><code>dmScope: "per-peer"</code> 确保同一用户跨通道共享会话上下文</li>
<li><b>记忆存储</b><code>MEMORY.md</code> 存储持久记忆(设备信息、用户偏好、操作历史)</li>
<li><b>每日笔记</b><code>memory/YYYY-MM-DD.md</code> 记录当天操作日志</li>
<li><b>记忆蒸馏</b> → Dreaming 系统自动从每日笔记中提取有价值信息晋升到长期记忆</li>
<li><b>跨通道回忆</b> → 在飞书中问"刚才微信说的那个文件在哪"AI 能从记忆中找到</li>
</ol>
</div>
<div class="diagram-box">微信: "帮我备份桌面 PDF"
AI 执行 file_list + file_move → 完成
├── 写入 memory/2026-07-16.md:
│ "用户要求备份桌面 PDF已移动 12 个文件到 D:\备份\"
飞书 (3小时后): "刚才那个备份做了吗?"
AI → memory_search("备份 PDF") → 找到今日笔记
"已备份,共 12 个 PDF 文件到 D:\备份\"</div>
</div>
<!-- ===== 8. 设备连接生命周期 ===== -->
<div class="flow-section">
<h2>8. 设备连接生命周期</h2>
<div class="flow-box">
<h4>设备从离线到在线的完整流程</h4>
<div class="diagram-box">设备状态流转:
offline ──客户端启动──▶ online ──开始操控──▶ busy ──操控结束──▶ online
│ │
│ ├── 设备休眠 ──▶ sleeping ──唤醒──▶ online
│ │
│ └── 维护模式 ──▶ maintenance ──完成──▶ online
└── 连接失败 ──▶ unreachable ──重连成功──▶ online
└── 重连失败 ──▶ offline
Gateway 设备注册表:
┌──────────────────────────────────────────────┐
│ 设备ID │ 协议 │ 状态 │ 最后心跳 │
│─────────────┼─────────┼─────────┼─────────────│
│ home-pc │ MCP SSE │ online │ 2s ago │
│ cloud-svr │ MCP SSE │ online │ 5s ago │
│ my-phone │ MCP SSE │ busy │ 1s ago │
│ game-svr │ MCP SSE │ offline │ 2h ago │
└──────────────────────────────────────────────┘</div>
</div>
</div>
<!-- ===== 9. 安全控制流程 ===== -->
<div class="flow-section">
<h2>9. 安全控制流程</h2>
<div class="flow-box">
<h4>多层安全防护</h4>
<div class="diagram-box">请求进入
┌─────────────────────────────────────┐
│ ① 身份验证 │
│ - Gateway Token 认证 │
│ - 设备配对 Token │
│ - 通道身份验证 (微信/飞书) │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ ② 权限控制 │
│ - Tool 白名单/黑名单 │
│ - 设备级权限 │
│ - 通道级权限 │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ ③ 执行沙箱 │
│ - 命令白名单 │
│ - 路径限制 │
│ - 超时控制 │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ ④ 审计日志 │
│ - 所有操作记录 │
│ - 异常行为告警 │
└──────────────┬──────────────────────┘
执行完成</div>
</div>
</div>
</div>
<footer>
<a href="index.html">首页</a> &nbsp;|&nbsp; <a href="architecture/index.html">架构</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

116
docs/index.html Normal file
View File

@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Global Control Assistant — 全局控制助手</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="topbar">
<span class="current">首页</span>
</div>
<div class="hero">
<h1>Global Control Assistant</h1>
<p>任意设备控制任意设备 · AI 对话操作所有设备</p>
<div class="badge">自建客户端 = MCP Server · Gateway = MCP Host · 所有被控设备装客户端</div>
</div>
<div class="container">
<h2>这个项目是什么?</h2>
<div class="card" style="border-color:rgba(59,130,246,.3);margin-bottom:32px">
<p style="font-size:.95rem;line-height:1.8;color:var(--text)">
<b>Global Control Assistant (GCA)</b> 是一个<b>跨设备远程控制与 AI 自动化系统</b><br><br>
<b>核心思路:</b>1 台主机运行 OpenClaw GatewayMCP HostAI 大脑)。每台被控设备装一个<b>自建客户端</b>,客户端作为 MCP Server 暴露本机能力给 Gateway。不装客户端的设备不纳入控制范围。<br><br>
<b>使用方式:</b>通过任意通道微信、飞书、Telegram、自建客户端用自然语言告诉 AI 你要做什么——"看看服务器磁盘满了没"、"把手机照片传到电脑"、"重启游戏服务器"。AI 自动选择正确的设备和 MCP Tool 执行。<br><br>
<b>自建客户端</b>有两个功能:① 与 Gateway 沟通(聊天/远程桌面 UI② 暴露本机能力MCP Server让 AI 能操作这台设备)。
</p>
</div>
<h2>项目文档</h2>
<div class="nav-cards">
<a class="nav-card" href="architecture/index.html">
<div class="emoji">🏗️</div>
<h3>系统架构</h3>
<p>连接流程、实现细节、配置</p>
</a>
<a class="nav-card" href="capabilities/index.html">
<div class="emoji">🧩</div>
<h3>能力全景</h3>
<p>36 MCP Tools 定义</p>
</a>
<a class="nav-card" href="roadmap/index.html">
<div class="emoji">🗺️</div>
<h3>实施路线图</h3>
<p>5 阶段开发计划</p>
</a>
<a class="nav-card" href="security/index.html">
<div class="emoji">🔒</div>
<h3>安全分析</h3>
<p>风险矩阵与安全机制</p>
</a>
<a class="nav-card" href="maintenance/index.html">
<div class="emoji">🔧</div>
<h3>维护优化</h3>
<p>技术债务与可维护性</p>
</a>
<a class="nav-card" href="pm-review/index.html">
<div class="emoji">📋</div>
<h3>PM 审查</h3>
<p>范围、风险、验收标准</p>
</a>
<a class="nav-card" href="backlog/index.html">
<div class="emoji"></div>
<h3>开发代办</h3>
<p>55 个任务 · 6 个模块</p>
</a>
<a class="nav-card" href="flow/index.html">
<div class="emoji">🔄</div>
<h3>系统流程</h3>
<p>9 大核心流程完整走查</p>
</a>
</div>
<h2 style="margin-top:40px">核心设计</h2>
<div class="grid grid-3">
<div class="card">
<h4>🔀 任意 → 任意</h4>
<p>手机找电脑文件、电脑查服务器日志、微信开关游戏服务器。发起方可以是任意设备或任意聊天通道。</p>
</div>
<div class="card">
<h4>🔌 客户端接入</h4>
<p>所有被控设备装自建客户端MCP Server + UI。Gateway 统一调度所有客户端。</p>
</div>
<div class="card">
<h4>💬 AI 对话控制</h4>
<p>通过微信/飞书/Telegram 用自然语言控制设备。AI 自动选择正确的设备和命令。</p>
</div>
<div class="card">
<h4>🖥️ 自建客户端</h4>
<p>Android APK + Desktop (Tauri) + CLI。AI 对话 + 设备管理 + 远程桌面 UI。</p>
</div>
<div class="card">
<h4>🖱️ 远程桌面</h4>
<p>客户端截取本机屏幕,通过 WS 数据端口推流到请求方。鼠标键盘事件实时转发。</p>
</div>
<div class="card">
<h4>🌍 外网访问</h4>
<p>聊天通道(微信/飞书)不需要穿透 NAT。客户端直连用 Tailscale 或 DDNS-GO。</p>
</div>
<div class="card">
<h4>🧠 跨通道记忆</h4>
<p>identityLinks 统一身份MEMORY.md 跨通道持久记忆。微信说的事飞书也知道。</p>
</div>
<div class="card">
<h4>🔄 双轨更新</h4>
<p>小更新 JS bundle OTA 静默推送(新增页面/修 Bug大更新 APK 重装(原生模块变更)。</p>
</div>
</div>
</div>
<footer>
Global Control Assistant &copy; 2026 &mdash; 基于 OpenClaw + MCP 构建
</footer>
</body>
</html>

100
docs/maintenance/index.html Normal file
View File

@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>维护优化 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">维护优化</span>
</div>
<div class="container">
<h1>项目维护优化清单</h1>
<p class="subtitle">从项目维护角度审视架构、流程和技术债务</p>
<div class="summary-bar">
<div class="s-item"><div class="num" style="color:var(--green)">1</div><div class="label">已解决</div></div>
<div class="s-item"><div class="num" style="color:var(--red)">3</div><div class="label">必须做</div></div>
<div class="s-item"><div class="num" style="color:var(--orange)">3</div><div class="label">强烈建议</div></div>
<div class="s-item"><div class="num" style="color:var(--accent)">2</div><div class="label">锦上添花</div></div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 已解决</h2>
<div class="issue-grid">
<div class="issue">
<h4><span class="tag t-green">已解决</span> API 数量精简</h4>
<p>从最初 180+ API 精简到 36 个 MCP Tool用 exec 兜底低频操作。JSON Schema 自动校验。</p>
</div>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--red)"></span> 必须做</h2>
<div class="issue-grid">
<div class="issue">
<h4><span class="tag t-red">P0</span> 跨平台 UI 自动化</h4>
<p>AI 应用操控需要 Accessibility APIWindows (UIAutomation)、Linux (AT-SPI2)、macOS (AX API)。三套 API每个平台独立实现。</p>
<div class="fix"><strong>方案:</strong>① 定义 UIAdapter 接口,每平台一个实现;② Phase 1 只做 Windows③ 优先用浏览器自动化Playwright 跨平台一致)。</div>
</div>
<div class="issue">
<h4><span class="tag t-red">P0</span> 缺少测试策略</h4>
<p>36 MCP Tool × 多平台 × 多设备接入方式 = 测试矩阵。</p>
<div class="fix"><strong>方案:</strong>① 单元测试:每个 tool handler 独立测试;② 集成测试:客户端 MCP Server ↔ Gateway③ E2E 测试Telegram → AI → MCP Tool → 执行;④ CIGitHub Actions。</div>
</div>
<div class="issue">
<h4><span class="tag t-red">P0</span> 无错误恢复策略</h4>
<p>网络断开、Gateway 重启、设备休眠。远程场景下错误是常态。</p>
<div class="fix"><strong>方案:</strong>① WS 自动重连(指数退避);② 请求超时 + 重试;③ 幂等性设计idempotency key</div>
</div>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--orange)"></span> 强烈建议</h2>
<div class="issue-grid">
<div class="issue">
<h4><span class="tag t-orange">P1</span> 无日志与可观测性</h4>
<p>远程设备出问题时没有日志无法排查。</p>
<div class="fix"><strong>方案:</strong>① 结构化日志pino/winston② 日志通过 WS 上报到 Gateway 集中查看;③ 健康心跳30s 上报 CPU/内存/磁盘)。</div>
</div>
<div class="issue">
<h4><span class="tag t-orange">P1</span> 无配置管理方案</h4>
<p>客户端需要配置Gateway 地址、token、代理、服务开关</p>
<div class="fix"><strong>方案:</strong>① 本地 JSON 配置 + 系统 keychain 存凭据;② Gateway 可远程推送配置;③ JSON Schema 校验。</div>
</div>
<div class="issue">
<h4><span class="tag t-orange">P1</span> 无自动化构建发布</h4>
<p>客户端要打包成 Windows .exe / Linux .deb / Android APK。手动打包耗时易错。</p>
<div class="fix"><strong>方案:</strong>① GitHub Actions CI② tag push 自动构建所有平台;③ 自动更新机制Tauri updater / Expo OTA</div>
</div>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--accent)"></span> 锦上添花</h2>
<div class="issue-grid">
<div class="issue">
<h4><span class="tag t-blue">P2</span> 文档迁移</h4>
<p>当前手写 HTML改一个样式要改多处。迁移到 VitePress 可用 Markdown 写内容。</p>
</div>
<div class="issue">
<h4><span class="tag t-blue">P2</span> 性能监控仪表盘</h4>
<p>多设备运行后需要统一视图查看所有设备健康状态。</p>
</div>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a> &nbsp;|&nbsp; <a href="../security/index.html">安全</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

94
docs/pm-review/index.html Normal file
View File

@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>项目经理审查 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">PM 审查</span>
</div>
<div class="container">
<h1>项目经理审查报告</h1>
<p class="subtitle">从项目管理角度审视风险、范围、进度和资源</p>
<div class="section">
<h2><span class="dot" style="background:var(--orange)"></span> 总体评估</h2>
<div class="card" style="border-color:rgba(245,158,11,.3)">
<p style="font-size:.95rem;line-height:1.8;color:var(--text)">
<b>结论:范围过大,需要砍阶段。</b><br><br>
当前设计覆盖了 10 大类能力、4 个客户端平台、外网穿透、远程桌面、AI 操控——对一个<b>个人开发者</b>来说是 2-3 年的工作量。<br><br>
<b>建议:</b>Phase 1 严格控制范围,只做"通过聊天通道控制一台设备"。其他全部推后。先跑通核心链路。
</p>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--red)"></span> 关键问题</h2>
<div class="issue-grid">
<div class="issue">
<h4><span class="tag t-red">P0</span> 范围过大</h4>
<p>36 MCP Tool × 4 平台 × 外网穿透 × 远程桌面 × AI 操控 = 不可能在 28 周内完成。</p>
<div class="fix"><strong>建议:</strong>Phase 1 只做 10 个 Tool + 聊天通道控制。远程桌面、AI 操控、Android 客户端全部推到 Phase 2+。</div>
</div>
<div class="issue">
<h4><span class="tag t-red">P0</span> 没有用户验证</h4>
<p>设计了大量功能但没有验证用户是否需要。</p>
<div class="fix"><strong>建议:</strong>Phase 1 交付后自己用 2 周,记录哪些功能真正用到。根据实际使用调整优先级。</div>
</div>
<div class="issue">
<h4><span class="tag t-red">P0</span> 外部依赖风险</h4>
<p>OpenClaw 是核心依赖MCP 支持可能变更、API 可能不稳定。</p>
<div class="fix"><strong>建议:</strong>① 锁定 OpenClaw 版本;② 所有交互封装在适配层;③ 关注 CHANGELOG。</div>
</div>
<div class="issue">
<h4><span class="tag t-orange">P1</span> 跨平台是最大技术风险</h4>
<p>四个平台的屏幕捕获、输入模拟、UI 自动化都不同。</p>
<div class="fix"><strong>建议:</strong>Phase 1 只做 Windows。验证核心链路通了再扩平台。</div>
</div>
<div class="issue">
<h4><span class="tag t-orange">P1</span> 没有里程碑和验收标准</h4>
<p>路线图有阶段划分,但没有明确的"完成"定义。</p>
<div class="fix"><strong>建议:</strong>每个 Phase 定义 3 个验收测试用例,全部通过才算完成。</div>
</div>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 各阶段验收标准</h2>
<div class="table-wrap">
<table>
<tr><th>阶段</th><th>验收用例</th><th>完成定义</th></tr>
<tr><td><b>Phase 1</b></td><td>① Telegram 发 "列出电脑文件" → 收到列表<br>② Telegram 发 "执行 dir" → 收到结果<br>③ 客户端重启后自动重连</td><td>3 个用例全部通过</td></tr>
<tr><td><b>Phase 2</b></td><td>① Android 客户端看到 2+ 设备在线<br>② 手机找电脑文件成功<br>③ 跨设备远程桌面连接成功</td><td>3 个用例全部通过</td></tr>
<tr><td><b>Phase 3</b></td><td>① 远程桌面操控流畅(&lt;300ms<br>② AI 自动打开记事本输入文字<br>③ 跨设备文件传输成功</td><td>3 个用例全部通过</td></tr>
</table>
</div>
</div>
<div class="section">
<h2><span class="dot" style="background:var(--accent)"></span> 建议的最小 MVP2 周)</h2>
<div class="highlight">
<h4>砍到不能再砍</h4>
<p>
<b>只做一件事:</b>通过 Telegram 用自然语言在一台 Windows 电脑上执行命令并返回结果。<br><br>
<b>技术栈:</b>OpenClaw Gateway + 客户端 MCP Server只实现 exec 和 file_list 两个 Tool<br>
<b>验证方式:</b>Telegram 发 "dir C:\Users" → 收到目录列表<br>
<b>不做的:</b>远程桌面、Android 客户端、AI 操控、外网访问、多设备
</p>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

208
docs/roadmap/index.html Normal file
View File

@@ -0,0 +1,208 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实施路线图 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
<style>
.timeline{position:relative;padding-left:40px}
.timeline::before{content:'';position:absolute;left:15px;top:0;bottom:0;width:3px;background:linear-gradient(to bottom,var(--accent),var(--accent2),var(--accent3),var(--green),var(--orange));border-radius:2px}
.phase{position:relative;margin-bottom:40px;animation:fadeIn .5s ease-out}
@keyframes fadeIn{from{opacity:0;transform:translateX(-20px)}to{opacity:1;transform:translateX(0)}}
.phase-dot{position:absolute;left:-33px;top:24px;width:20px;height:20px;border-radius:50%;border:3px solid var(--bg);z-index:1}
.phase-card{background:var(--card);border:1px solid var(--border);border-radius:16px;overflow:hidden;transition:all .3s}
.phase-card:hover{border-color:var(--accent);box-shadow:0 8px 32px rgba(59,130,246,.1)}
.phase-header{padding:20px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.phase-header .phase-label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:2px;padding:4px 12px;border-radius:8px}
.phase-header h2{font-size:1.25rem;flex:1}
.phase-header .duration{font-size:.85rem;color:var(--dim);display:flex;align-items:center;gap:6px}
.phase-body{padding:0 24px 24px}
.phase-goal{background:rgba(59,130,246,.06);border:1px solid rgba(59,130,246,.15);border-radius:10px;padding:14px 18px;margin-bottom:16px;font-size:.9rem}
.phase-goal strong{color:var(--accent)}
.task-list{list-style:none;display:grid;gap:8px}
.task-list li{display:flex;align-items:flex-start;gap:10px;padding:10px 14px;background:rgba(255,255,255,.02);border-radius:8px;font-size:.88rem;color:var(--dim);transition:background .2s}
.task-list li:hover{background:rgba(255,255,255,.05)}
.task-num{min-width:24px;height:24px;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:.72rem;font-weight:700;background:rgba(255,255,255,.05);color:var(--text)}
.deliverable{margin-top:16px;padding:14px 18px;border-radius:10px;display:flex;align-items:center;gap:10px;font-size:.88rem;font-weight:600}
.p1 .phase-dot,.p1 .phase-label{background:var(--accent);color:white}
.p1 .deliverable{background:rgba(59,130,246,.1);border:1px solid rgba(59,130,246,.2);color:var(--accent)}
.p2 .phase-dot,.p2 .phase-label{background:var(--accent2);color:white}
.p2 .deliverable{background:rgba(139,92,246,.1);border:1px solid rgba(139,92,246,.2);color:var(--accent2)}
.p3 .phase-dot,.p3 .phase-label{background:var(--accent3);color:white}
.p3 .deliverable{background:rgba(6,182,212,.1);border:1px solid rgba(6,182,212,.2);color:var(--accent3)}
.p4 .phase-dot,.p4 .phase-label{background:var(--green);color:white}
.p4 .deliverable{background:rgba(34,197,94,.1);border:1px solid rgba(34,197,94,.2);color:var(--green)}
.p5 .phase-dot,.p5 .phase-label{background:var(--orange);color:white}
.p5 .deliverable{background:rgba(245,158,11,.1);border:1px solid rgba(245,158,11,.2);color:var(--orange)}
</style>
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">实施路线图</span>
</div>
<div class="container">
<h1>实施路线图</h1>
<p class="subtitle">五阶段渐进式开发,每个阶段交付独立可用的产品</p>
<div class="summary-bar">
<div class="s-item"><div class="num" style="color:var(--accent)">5</div><div class="label">实施阶段</div></div>
<div class="s-item"><div class="num" style="color:var(--accent2)">28</div><div class="label">总周数</div></div>
<div class="s-item"><div class="num" style="color:var(--green)">36</div><div class="label">MCP Tools</div></div>
<div class="s-item"><div class="num" style="color:var(--orange)">4</div><div class="label">目标平台</div></div>
</div>
<div class="timeline">
<!-- Phase 1 -->
<div class="phase p1">
<div class="phase-dot"></div>
<div class="phase-card">
<div class="phase-header">
<span class="phase-label">Phase 1</span>
<h2>基础 MVP</h2>
<span class="duration">第 1-4 周</span>
</div>
<div class="phase-body">
<div class="phase-goal"><strong>目标:</strong>MCP Server 跑通,通过聊天通道控制一台设备</div>
<ul class="task-list">
<li><span class="task-num">1</span>安装配置 OpenClaw Gateway主机配置 mcpServers</li>
<li><span class="task-num">2</span>实现客户端的 MCP Server 功能10 个核心 MCP Toolfile_list/read/write、exec、process_list、sysinfo、power、notify_send</li>
<li><span class="task-num">3</span>客户端启动时自动通过 SSE 注册到 Gateway</li>
<li><span class="task-num">4</span>端到端测试Telegram/飞书发 "查看电脑上的文件" → AI 调用 MCP tool → 执行 → 返回</li>
<li><span class="task-num">5</span>配置 session.identityLinks 跨通道记忆统一</li>
</ul>
<div class="deliverable">交付物:客户端运行在主机,通过 Telegram/飞书/微信控制</div>
</div>
</div>
</div>
<!-- Phase 2 -->
<div class="phase p2">
<div class="phase-dot"></div>
<div class="phase-card">
<div class="phase-header">
<span class="phase-label">Phase 2</span>
<h2>多设备 + Android 客户端</h2>
<span class="duration">第 5-10 周</span>
</div>
<div class="phase-body">
<div class="phase-goal"><strong>目标:</strong>多设备 + Android 客户端 + 远程控制</div>
<ul class="task-list">
<li><span class="task-num">1</span>客户端跨平台Linux / macOS 版本(复用 Windows 代码)</li>
<li><span class="task-num">2</span>添加远程控制能力:屏幕截图/推流、鼠标键盘直通、剪贴板同步</li>
<li><span class="task-num">3</span>自建 Android 客户端设备列表、文件浏览器、远程终端、远程桌面、AI 聊天</li>
<li><span class="task-num">4</span>跨设备操作:手机找电脑文件、电脑看手机截图</li>
</ul>
<div class="deliverable">交付物:多设备互联,手机控制电脑</div>
</div>
</div>
</div>
<!-- Phase 3 -->
<div class="phase p3">
<div class="phase-dot"></div>
<div class="phase-card">
<div class="phase-header">
<span class="phase-label">Phase 3</span>
<h2>桌面客户端 + 完善</h2>
<span class="duration">第 11-16 周</span>
</div>
<div class="phase-body">
<div class="phase-goal"><strong>目标:</strong>桌面客户端 + AI 应用操控 + 完整体验</div>
<ul class="task-list">
<li><span class="task-num">1</span>自建 Tauri 桌面客户端:设备仪表盘、文件管理器、远程终端、远程桌面、系统监控</li>
<li><span class="task-num">2</span>远程控制增强MJPEG 推流15-30fps、鼠标键盘实时操控、多显示器、剪贴板同步</li>
<li><span class="task-num">3</span>AI 应用操控UI 元素操作Accessibility API、浏览器自动化、OCR 屏幕识别</li>
<li><span class="task-num">4</span>跨设备文件传输:设备间直接传输文件</li>
<li><span class="task-num">5</span>客户端连接生命周期自动通联检测、Tailscale 按需启停、心跳保活、断线重连</li>
<li><span class="task-num">6</span>打包为 Windows .exe + Linux .deb + Android APK</li>
</ul>
<div class="deliverable">交付物全平台客户端AI 操控应用,跨设备文件传输</div>
</div>
</div>
</div>
<!-- Phase 4 -->
<div class="phase p4">
<div class="phase-dot"></div>
<div class="phase-card">
<div class="phase-header">
<span class="phase-label">Phase 4</span>
<h2>智能家居与 IoT</h2>
<span class="duration">第 17-22 周</span>
</div>
<div class="phase-body">
<div class="phase-goal"><strong>目标:</strong>扩展到计算机之外的设备</div>
<ul class="task-list">
<li><span class="task-num">1</span>轻量 IoT 客户端(树莓派 CLI 版)</li>
<li><span class="task-num">2</span>智能家居集成Tuya / SmartThings / Home Assistant</li>
<li><span class="task-num">3</span>定时任务(通过 OpenClaw cron如每晚 2 点备份照片)</li>
<li><span class="task-num">4</span>通知转发(手机通知 → 聊天通道)</li>
</ul>
<div class="deliverable">交付物:统一控制 PC、手机和 IoT 设备</div>
</div>
</div>
</div>
<!-- Phase 5 -->
<div class="phase p5">
<div class="phase-dot"></div>
<div class="phase-card">
<div class="phase-header">
<span class="phase-label">Phase 5</span>
<h2>安全加固与发布</h2>
<span class="duration">第 23-28 周</span>
</div>
<div class="phase-body">
<div class="phase-goal"><strong>目标:</strong>生产级质量,可正式发布</div>
<ul class="task-list">
<li><span class="task-num">1</span>端到端加密libsodium / NaCl</li>
<li><span class="task-num">2</span>基于角色的权限控制(如 "此通道只能读文件,不能执行命令"</li>
<li><span class="task-num">3</span>所有远程操作审计日志</li>
<li><span class="task-num">4</span>客户端自动更新机制</li>
<li><span class="task-num">5</span>发布Play Store、GitHub Releases</li>
<li><span class="task-num">6</span>文档和安装指南</li>
</ul>
<div class="deliverable">交付物:可发布的正式产品</div>
</div>
</div>
</div>
</div>
<!-- 风险 -->
<div class="section">
<h2><span class="dot" style="background:var(--red)"></span> 风险与缓解</h2>
<div class="table-wrap">
<table>
<tr><th>风险</th><th>影响</th><th>缓解措施</th></tr>
<tr><td>OpenClaw MCP 协议变更</td><td>集成困难</td><td>适配层隔离;锁定 OpenClaw 版本</td></tr>
<tr><td>跨平台 UI 自动化</td><td>开发效率</td><td>Phase 1 只做 Windows优先浏览器自动化</td></tr>
<tr><td>个人开发者精力有限</td><td>进度延迟</td><td>每阶段独立交付Phase 1 仅需 4 周</td></tr>
<tr><td>外网访问不稳定</td><td>连接中断</td><td>Tailscale + DDNS-GO 双方案;心跳自动重连</td></tr>
</table>
</div>
</div>
<!-- 验证 -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 验证方式</h2>
<div class="grid grid-3">
<div class="card"><h4>Phase 1</h4><p>Telegram 发 "列出电脑上的文件" → 收到文件列表</p></div>
<div class="card"><h4>Phase 2</h4><p>Android 客户端看到多台设备在线,手机找电脑文件成功</p></div>
<div class="card"><h4>Phase 3</h4><p>桌面客户端远程桌面操控流畅AI 自动操作应用成功</p></div>
<div class="card"><h4>Phase 4</h4><p>"关闭客厅灯" → IoT 设备响应;定时备份执行</p></div>
<div class="card"><h4>Phase 5</h4><p>安全审计通过自动更新正常Play Store 上架</p></div>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a> &nbsp;|&nbsp; <a href="../capabilities/index.html">能力</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

134
docs/security/index.html Normal file
View File

@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>安全分析 — Global Control Assistant</title>
<link rel="stylesheet" href="../style.css">
<style>
.verdict{display:inline-block;padding:4px 14px;border-radius:20px;font-size:.8rem;font-weight:700;letter-spacing:.5px}
.v-feasible{background:rgba(34,197,94,.15);color:var(--green);border:1px solid rgba(34,197,94,.3)}
.v-partial{background:rgba(245,158,11,.15);color:var(--orange);border:1px solid rgba(245,158,11,.3)}
.v-risk{background:rgba(239,68,68,.15);color:var(--red);border:1px solid rgba(239,68,68,.3)}
</style>
</head>
<body>
<div class="topbar">
<a href="../index.html">首页</a><span class="sep">/</span>
<a href="../architecture/index.html">架构</a><span class="sep">/</span>
<span class="current">安全分析</span>
</div>
<div class="container">
<h1>可行性与安全性分析</h1>
<p class="subtitle">基于 OpenClaw + MCP 架构的技术验证与风险评估</p>
<div class="summary-bar">
<div class="s-item"><div class="num" style="color:var(--green)"></div><div class="label">整体可行</div></div>
<div class="s-item"><div class="num" style="color:var(--red)">3</div><div class="label">高风险</div></div>
<div class="s-item"><div class="num" style="color:var(--orange)">4</div><div class="label">中风险</div></div>
<div class="s-item"><div class="num" style="color:var(--green)">2</div><div class="label">低风险</div></div>
</div>
<!-- 可行性 -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 技术可行性</h2>
<div class="table-wrap">
<table>
<tr><th>评估项</th><th>结论</th><th>依据</th></tr>
<tr><td>Gateway MCP Host</td><td><span class="verdict v-feasible">可行</span></td><td>OpenClaw 原生支持 mcpServers 配置,自动发现 MCP Tools</td></tr>
<tr><td>客户端 MCP Server</td><td><span class="verdict v-feasible">可行</span></td><td>@modelcontextprotocol/sdk 成熟SSE/WS 传输</td></tr>
<tr><td>远程桌面推流</td><td><span class="verdict v-partial">需要适配</span></td><td>screenshot-desktop + Sharp + WS跨平台有差异</td></tr>
<tr><td>UI 自动化</td><td><span class="verdict v-partial">平台差异大</span></td><td>Windows UIAutomation / Linux AT-SPI2 / macOS AX API 三套</td></tr>
<tr><td>外网访问</td><td><span class="verdict v-feasible">可行</span></td><td>Tailscale + DDNS-GO 已验证可用</td></tr>
</table>
</div>
</div>
<!-- 高风险 -->
<div class="section">
<h2><span class="dot" style="background:var(--red)"></span> 高风险项</h2>
<div class="risk-matrix">
<div class="risk risk-critical">
<h4>远程命令执行 — 命令注入</h4>
<p>客户端暴露 exec MCP ToolAI 被 prompt injection 攻击可能执行恶意命令。</p>
<div class="fix"><strong>缓解:</strong>OpenClaw exec approval 机制allowlist + ask敏感命令黑名单沙箱模式。</div>
</div>
<div class="risk risk-critical">
<h4>远程桌面 — 未授权访问</h4>
<p>屏幕推流 + 鼠标键盘直通 = 完全控制。连接被劫持则设备沦陷。</p>
<div class="fix"><strong>缓解:</strong>Gateway auth token 强制认证Tailscale 加密隧道;远程控制需被控端确认。</div>
</div>
<div class="risk risk-critical">
<h4>Prompt Injection — AI 被劫持</h4>
<p>不受信内容(网页、邮件、文件)携带恶意指令,操纵 AI 执行危险操作。</p>
<div class="fix"><strong>缓解:</strong>使用旗舰模型;不受信内容用只读 reader agent 预处理;高风险工具走 approval。</div>
</div>
</div>
</div>
<!-- 中风险 -->
<div class="section">
<h2><span class="dot" style="background:var(--orange)"></span> 中风险项</h2>
<div class="risk-matrix">
<div class="risk risk-high">
<h4>Gateway Token 泄露</h4>
<p>客户端存储 Gateway 认证 token泄露则未授权设备可接入。</p>
<div class="fix"><strong>缓解:</strong>token 存储在系统 keychain定期轮换Gateway 侧可撤销已知设备。</div>
</div>
<div class="risk risk-high">
<h4>剪贴板数据泄露</h4>
<p>跨设备剪贴板同步可能无意中传输密码、token。</p>
<div class="fix"><strong>缓解:</strong>敏感模式检测;同步后自动清除远端剪贴板。</div>
</div>
<div class="risk risk-high">
<h4>Gateway 单点故障</h4>
<p>Gateway 挂掉导致所有设备失联、所有通道中断。</p>
<div class="fix"><strong>缓解:</strong>launchd/systemd 守护进程自动重启;健康检查告警。</div>
</div>
<div class="risk risk-high">
<h4>外网暴露攻击面</h4>
<p>Tailscale/DDNS-GO 暴露 Gateway 到外网,可能被扫描攻击。</p>
<div class="fix"><strong>缓解:</strong>Gateway auth token 必须设置Tailscale 本身有加密;定期安全审计。</div>
</div>
</div>
</div>
<!-- 低风险 -->
<div class="section">
<h2><span class="dot" style="background:var(--green)"></span> 低风险项</h2>
<div class="risk-matrix">
<div class="risk risk-low">
<h4>配置文件安全</h4>
<p>客户端本地存储 Gateway token、Headscale 密钥等凭据。</p>
<div class="fix"><strong>缓解:</strong>使用系统 keychain 存储凭据;不写入明文配置文件。</div>
</div>
<div class="risk risk-low">
<h4>第三方依赖漏洞</h4>
<p>systeminformation/screenshot-desktop/@modelcontextprotocol/sdk 等 npm 包可能存在安全漏洞。</p>
<div class="fix"><strong>缓解:</strong>npm audit 定期检查;锁定版本;关键依赖 fork。</div>
</div>
</div>
</div>
<!-- OpenClaw 安全机制 -->
<div class="section">
<h2><span class="dot" style="background:var(--accent)"></span> 可复用的 OpenClaw 安全机制</h2>
<div class="grid grid-3">
<div class="card"><h4>设备配对</h4><p>challenge 签名 + 人工审批,防止未授权设备接入</p></div>
<div class="card"><h4>工具策略</h4><p>per-agent allow/deny 列表AI 只能看到被允许的 Tools</p></div>
<div class="card"><h4>Exec Approval</h4><p>命令执行审批机制allowlist + 每次确认</p></div>
<div class="card"><h4>沙箱模式</h4><p>Docker 容器隔离工具执行,限制文件系统和网络访问</p></div>
<div class="card"><h4>安全审计</h4><p>openclaw security audit 自动检查配置风险</p></div>
<div class="card"><h4>会话隔离</h4><p>dmScope: per-peer不同用户上下文隔离</p></div>
</div>
</div>
</div>
<footer>
<a href="../index.html">首页</a> &nbsp;|&nbsp; <a href="../architecture/index.html">架构</a> &nbsp;|&nbsp; <a href="../maintenance/index.html">维护</a>
<br><br>
Global Control Assistant &copy; 2026
</footer>
</body>
</html>

164
docs/style.css Normal file
View File

@@ -0,0 +1,164 @@
:root{--bg:#0f172a;--card:#1e293b;--border:#334155;--accent:#3b82f6;--accent2:#8b5cf6;--accent3:#06b6d4;--text:#e2e8f0;--dim:#94a3b8;--green:#22c55e;--orange:#f59e0b;--red:#ef4444;--pink:#ec4899;--amber:#f59e0b;--lime:#84cc16;--teal:#14b8a6;--sky:#0ea5e9}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Segoe UI',system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);min-height:100vh;line-height:1.6}
/* Topbar */
.topbar{position:sticky;top:0;z-index:100;background:rgba(15,23,42,.92);backdrop-filter:blur(12px);border-bottom:1px solid var(--border);padding:12px 24px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.topbar a{color:var(--dim);text-decoration:none;font-size:.88rem;transition:color .2s}
.topbar a:hover{color:var(--accent)}
.topbar .sep{color:var(--border)}
.topbar .current{color:var(--text);font-weight:600}
/* Layout */
.container{max-width:1200px;margin:0 auto;padding:40px 20px}
h1{font-size:2rem;font-weight:800;margin-bottom:8px}
h2{font-size:1.3rem;font-weight:700;margin-bottom:16px;display:flex;align-items:center;gap:10px}
h2 .dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
h3{font-size:1rem;margin:20px 0 10px;color:var(--accent2)}
.subtitle{color:var(--dim);margin-bottom:40px;font-size:1rem}
/* Grid */
.grid{display:grid;gap:14px}
.grid-2{grid-template-columns:repeat(auto-fit,minmax(340px,1fr))}
.grid-3{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
/* Card */
.card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:20px;transition:all .3s}
.card:hover{border-color:var(--accent);box-shadow:0 4px 20px rgba(59,130,246,.08)}
.card h4{font-size:.95rem;margin-bottom:6px;display:flex;align-items:center;gap:8px}
.card p{color:var(--dim);font-size:.82rem;line-height:1.5}
/* Nav card */
.nav-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}
.nav-card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:24px 16px;text-align:center;text-decoration:none;color:var(--text);transition:all .3s}
.nav-card:hover{border-color:var(--accent);transform:translateY(-3px);box-shadow:0 8px 32px rgba(59,130,246,.12)}
.nav-card .emoji{font-size:2rem;margin-bottom:8px}
.nav-card h3{margin-bottom:4px;font-size:1rem}
.nav-card p{color:var(--dim);font-size:.78rem}
/* Summary bar */
.summary-bar{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:12px;margin-bottom:40px}
.s-item{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:14px;text-align:center}
.s-item .num{font-size:1.8rem;font-weight:800}
.s-item .label{color:var(--dim);font-size:.72rem;margin-top:2px}
/* Tags */
.tag{display:inline-block;padding:3px 10px;border-radius:10px;font-size:.72rem;font-weight:600}
.t-red{background:rgba(239,68,68,.15);color:var(--red)}
.t-orange{background:rgba(245,158,11,.15);color:var(--orange)}
.t-blue{background:rgba(59,130,246,.15);color:var(--accent)}
.t-green{background:rgba(34,197,94,.15);color:var(--green)}
.t-purple{background:rgba(139,92,246,.15);color:var(--accent2)}
.t-pink{background:rgba(236,72,153,.15);color:var(--pink)}
.t-cyan{background:rgba(6,182,212,.15);color:var(--accent3)}
/* Table */
.table-wrap{overflow-x:auto;margin-bottom:20px}
table{width:100%;border-collapse:collapse;font-size:.85rem}
th{text-align:left;padding:10px 14px;background:rgba(59,130,246,.08);border-bottom:2px solid var(--border);color:var(--accent);font-weight:600}
td{padding:10px 14px;border-bottom:1px solid var(--border);color:var(--dim)}
tr:hover td{background:rgba(59,130,246,.03)}
td:first-child{color:var(--text);font-weight:500}
/* Service grid */
.svc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px}
.svc{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:14px;text-align:center;transition:all .3s}
.svc:hover{border-color:var(--accent);transform:translateY(-1px)}
.svc .icon{font-size:1.5rem;margin-bottom:6px}
.svc h4{font-size:.85rem;margin-bottom:2px}
.svc p{color:var(--dim);font-size:.72rem}
/* Code block */
.code-block{background:#0d1117;border:1px solid var(--border);border-radius:12px;padding:18px;overflow-x:auto;font-family:'Cascadia Code','Fira Code','Consolas',monospace;font-size:.8rem;line-height:1.7;color:#c9d1d9;position:relative}
.code-block .lang{position:absolute;top:8px;right:12px;font-size:.68rem;color:var(--dim);text-transform:uppercase;letter-spacing:1px}
.code-block pre{margin:0}
.key{color:#7ee787}
.str{color:#a5d6ff}
.num{color:#79c0ff}
.bool{color:#ff7b72}
.comment{color:#8b949e}
/* Diagram */
.diagram{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:20px;font-family:'Cascadia Code','Fira Code','Consolas',monospace;font-size:.76rem;line-height:1.8;overflow-x:auto;white-space:pre}
.diagram .hl{color:var(--accent);font-weight:700}
.diagram .hi{color:var(--pink);font-weight:700}
.diagram .gr{color:var(--green);font-weight:700}
.diagram .dim{color:var(--dim)}
/* Before-after */
.before-after{display:grid;grid-template-columns:1fr 36px 1fr;gap:10px;align-items:start;margin:16px 0}
.ba-box{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px;font-family:'Cascadia Code','Fira Code','Consolas',monospace;font-size:.76rem;line-height:1.7;overflow-x:auto}
.ba-box.before{border-color:rgba(239,68,68,.3)}
.ba-box.after{border-color:rgba(34,197,94,.3)}
.ba-arrow{display:flex;align-items:center;justify-content:center;font-size:1.3rem;color:var(--dim)}
.ba-label{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:1px;margin-bottom:6px;display:block}
.ba-label.red{color:var(--red)}
.ba-label.green{color:var(--green)}
/* Highlight box */
.highlight{background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.2);border-radius:14px;padding:18px;margin-bottom:16px}
.highlight h4{color:var(--green);margin-bottom:6px;font-size:.95rem}
.highlight p{color:var(--dim);font-size:.85rem;line-height:1.5}
/* Issue card */
.issue-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
.issue{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px;transition:all .3s}
.issue:hover{border-color:var(--accent)}
.issue h4{font-size:.92rem;margin-bottom:6px;display:flex;align-items:center;gap:6px}
.issue>p{color:var(--dim);font-size:.82rem;line-height:1.5;margin-bottom:10px}
.issue .fix{font-size:.8rem;padding:10px 14px;background:rgba(34,197,94,.05);border:1px solid rgba(34,197,94,.12);border-radius:8px;line-height:1.6}
.issue .fix strong{color:var(--green)}
/* Risk card */
.risk-matrix{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px}
.risk{background:var(--card);border-left:4px solid;border-radius:0 12px 12px 0;padding:16px 18px}
.risk h4{font-size:.9rem;margin-bottom:6px}
.risk p{color:var(--dim);font-size:.82rem;line-height:1.5}
.risk .fix{margin-top:8px;font-size:.8rem;padding:8px 12px;background:rgba(255,255,255,.03);border-radius:8px}
.risk .fix strong{color:var(--green)}
.risk-critical{border-color:var(--red)}
.risk-high{border-color:var(--orange)}
.risk-medium{border-color:var(--accent)}
.risk-low{border-color:var(--green)}
/* Capability card */
.cap-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
.cap{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px;transition:all .3s}
.cap:hover{border-color:var(--accent)}
.cap h4{font-size:.92rem;margin-bottom:4px;display:flex;align-items:center;gap:6px}
.cap p{color:var(--dim);font-size:.8rem;line-height:1.4;margin-bottom:6px}
.cap-methods{display:flex;flex-wrap:wrap;gap:3px}
.mtag{padding:2px 7px;border-radius:5px;font-size:.68rem;font-weight:600;font-family:'Cascadia Code','Fira Code','Consolas',monospace;background:rgba(59,130,246,.1);color:var(--accent)}
.mtag.green{background:rgba(34,197,94,.1);color:var(--green)}
.mtag.purple{background:rgba(139,92,246,.1);color:var(--accent2)}
.mtag.pink{background:rgba(236,72,153,.1);color:var(--pink)}
.mtag.orange{background:rgba(245,158,11,.1);color:var(--orange)}
.mtag.cyan{background:rgba(6,182,212,.1);color:var(--accent3)}
.mtag.red{background:rgba(239,68,68,.1);color:var(--red)}
/* Hero */
.hero{text-align:center;padding:60px 20px 32px;background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 50%,#0f172a 100%);position:relative;overflow:hidden}
.hero::before{content:'';position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:radial-gradient(circle at 30% 50%,rgba(59,130,246,.06) 0%,transparent 50%),radial-gradient(circle at 70% 50%,rgba(139,92,246,.06) 0%,transparent 50%);animation:pulse 8s ease-in-out infinite}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
.hero h1{font-size:2.5rem;font-weight:800;background:linear-gradient(135deg,var(--accent),var(--accent2),var(--accent3));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;position:relative}
.hero p{color:var(--dim);font-size:1.1rem;margin-top:10px;position:relative}
.hero .badge{display:inline-block;margin-top:16px;padding:5px 14px;border-radius:18px;background:rgba(59,130,246,.12);border:1px solid rgba(59,130,246,.25);color:var(--accent);font-size:.82rem;position:relative}
/* Footer */
footer{text-align:center;padding:40px 20px;color:var(--dim);font-size:.78rem;border-top:1px solid var(--border);margin-top:40px}
footer a{color:var(--accent);text-decoration:none}
footer a:hover{text-decoration:underline}
/* Section */
.section{margin-bottom:40px}
/* Backlog / Task table */
.module{margin-bottom:40px}
.module h2{font-size:1.15rem;margin-bottom:14px;display:flex;align-items:center;gap:8px}
.module h2 .dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.task-table{width:100%;border-collapse:collapse;font-size:.82rem;margin-bottom:12px}
.task-table th{text-align:left;padding:8px 12px;background:rgba(59,130,246,.06);border-bottom:2px solid var(--border);color:var(--accent);font-weight:600;font-size:.75rem}
.task-table td{padding:7px 12px;border-bottom:1px solid var(--border);color:var(--dim);font-size:.82rem}
.task-table tr:hover td{background:rgba(59,130,246,.02)}
.task-table td:first-child{color:var(--text);font-weight:500;font-family:'Cascadia Code','Fira Code','Consolas',monospace;font-size:.78rem;white-space:nowrap}
.task-table td:nth-child(2){color:var(--text)}