Web 管理界面(ui)
chainlesschain ui会启动本地 Web 管理面板,并自动连接内置 WebSocket 服务。当前文档已对齐统一 runtime event、session record、后台任务增强、Worktree 合并助手和压缩观测的最新实现。
概述
ui 命令启动本地浏览器管理界面(HTTP 端口 18810 + WebSocket 端口 18800),将 CLI 已有能力以可视化方式呈现,覆盖 23 个页面(Dashboard、AI 对话、服务管理、技能配置、安全中心、P2P 网络等)。支持项目模式和全局模式,前端通过统一事件模型与 Runtime/WS Gateway 实时通信。
核心特性
- 🖥️ Vue3 管理面板: 23 个功能页面,4 种颜色主题,支持项目级与全局两种工作模式
- 🔗 自动对接 WebSocket: 启动 HTTP (18810) + 自动带起 WS (18800) 服务,无需单独配置
- 🎨 主题与国际化: CSS 变量驱动 4 套主题,localStorage 持久化,一键切换
- 🔐 Token 认证: 支持
--token认证模式,Panel 加载后自动携带 token 与 WS 通信 - 📊 统一事件模型: 所有会话、任务、压缩观测通过
runtime event实时推送到面板 - 🧩 三路面板检测: 优先使用
--web-panel-dir,其次源码产物,最后包内置产物,兜底经典 HTML - 🚀 零构建发布: npm 全局安装已内置 Panel dist,开箱即用
- 🧪 可组合: 可单独作为前端接入外部
serve,也可一键复合启动
系统架构
Browser (http://127.0.0.1:18810)
│ 加载 Vue3 SPA + 注入 window.__CC_CONFIG__
│
▼ WebSocket (ws://127.0.0.1:18800)
┌───────────────────────────────────────┐
│ web-ui-server.js (Node HTTP) │
│ ├── 三路 panel 检测 (dist / 内置 / 经典) │
│ └── 静态资源服务 + 配置注入 │
├───────────────────────────────────────┤
│ ws-server.js (与 serve 共享实现) │
│ ├── 认证 / 心跳 / 消息分发 │
│ └── runtime event 广播 │
├───────────────────────────────────────┤
│ CLI Runtime (60+ 命令) │
│ └── spawn 子进程 / Agent 会话 │
└───────────────────────────────────────┘这是什么
chainlesschain ui 是 ChainlessChain 的本地浏览器管理界面。它的目标不是替代 CLI,而是把 CLI 已有能力以更适合观察、切换和联调的方式呈现出来。
它适合以下场景:
- 用浏览器管理 Agent / Chat 会话
- 查看后台任务、任务历史和完成通知
- 查看压缩策略观测与会话运行状态
- 在项目模式下,把对话绑定到某个项目根目录
- 作为
chainlesschain serve的内置前端使用
启动后会发生什么
执行:
chainlesschain ui会同时启动两类服务:
- HTTP 服务,默认端口
18810 - WebSocket 服务,默认端口
18800
浏览器页面负责展示界面,真正的会话、任务和运行状态仍然由本地 CLI 侧的 Runtime / WS Gateway 负责。
常用命令
chainlesschain ui
chainlesschain ui --port 9000 --ws-port 9001
chainlesschain ui --token my-secret-token
chainlesschain ui --no-open
chainlesschain ui --web-panel-dir /custom/dist常见用法:
- 本机直接使用:
chainlesschain ui - 联调其它前端或保留浏览器手动打开:
chainlesschain ui --no-open - 需要认证:
chainlesschain ui --token my-secret-token - 使用自定义构建产物:
chainlesschain ui --web-panel-dir /custom/dist
配置参考
# CLI 启动参数
chainlesschain ui [options]
-p, --port <port> # HTTP 端口 (默认 18810)
--ws-port <port> # WebSocket 端口 (默认 18800)
-H, --host <host> # 绑定地址 (默认 127.0.0.1)
--no-open # 不自动打开浏览器
--token <token> # WebSocket 认证 token
--web-panel-dir <dir> # 自定义 dist/ 目录
# 环境变量
CC_UI_PORT=18810
CC_UI_WS_PORT=18800
CC_UI_HOST=127.0.0.1
CC_UI_TOKEN=<token>
CC_UI_WEB_PANEL_DIR=<dir>
# 运行时配置(注入到页面 window.__CC_CONFIG__)
{
"wsUrl": "ws://127.0.0.1:18800",
"token": "<token>",
"projectRoot": "<cwd>", // 项目模式时为项目根目录
"mode": "project" | "global"
}
# 三路 panel 检测顺序
1. --web-panel-dir <dir>
2. packages/web-panel/dist/ (源码模式)
3. src/assets/web-panel/ (npm 内置)
4. 经典单页 HTML 兜底性能指标
| 操作 | 目标 | 实际 | 状态 |
|---|---|---|---|
| 面板首屏加载 (本地) | < 1.5s | ~0.8s | ✅ |
| WebSocket 连接建立 | < 100ms | ~40ms | ✅ |
| 页面切换 (Vue Router) | < 100ms | ~35ms | ✅ |
| runtime event 推送延迟 | < 50ms | ~20ms | ✅ |
| 主题切换过渡 | < 500ms | ~400ms | ✅ |
| ui 启动 + WS ready | < 2s | ~1.2s | ✅ |
运行模式
项目模式
从包含 .chainlesschain/ 的目录启动时,UI 会自动进入项目模式,并把 projectRoot 注入会话上下文。
适合:
- 面向单个项目持续对话
- 让 Agent 工具调用更明确地绑定项目目录
- 区分项目级会话和全局会话
全局模式
从普通目录启动时,UI 作为全局管理面板运行。
适合:
- 通用 AI 对话
- 查看全局会话
- 调试 Provider、技能和系统能力
页面能力概览
当前 Web Panel 覆盖 23 个页面,分为七大类:
概览:Dashboard、AI 对话、服务管理、日志查看
配置:技能管理、LLM 配置、MCP 工具
数据:笔记管理、记忆文件、定时任务、后台任务
高级:安全中心、权限管理、P2P 网络、备份同步、Git 与数据、项目管理
企业:钱包管理、组织管理、使用分析、模板中心
扩展:RSS 订阅、身份认证
Dashboard
Dashboard 负责展示全局摘要,而不是完整业务细节。当前已经能看到:
- 会话数量
- 压缩观测摘要
- 时间窗口筛选后的统计
- 按
provider/model切片的观测结果
Chat / Agent 会话
会话区域支持:
- 新建 Agent / Chat 会话
- 切换历史会话
- 恢复会话 history
- 流式 token 输出
- 工具执行过程可视化
- 交互式问题回答
后台任务
任务区域已对齐当前任务协议能力,支持:
- 查询任务列表
- 查询任务详情
- 查询任务历史分页
- 接收
task:notification - 查看任务输出摘要
压缩观测
压缩观测现在不是只显示一个总数字,而是支持:
windowMs时间窗口筛选provider/model维度切片- 命中率
- 节省 token
- 净节省率
- 策略分布
- 变体分布
当前前端事件模型
Web Panel 已开始统一通过 onRuntimeEvent() 消费后端事件,而不是每个页面都直接监听原始 WS 消息。
已归一化的消息包括:
| 协议消息 | 统一事件 |
|---|---|
task:notification | task:notification |
session-created | session:start |
session-resumed | session:resume |
worktree-diff | worktree:diff:ready |
worktree-merged | worktree:merge:completed |
compression-stats | compression:summary |
当前已接入统一事件入口的前端模块:
ws.jstasks.jschat.jsdashboard.js
这一步的意义是:
- 前端主干页面开始共享一套标准事件流
- 协议字段扩展时,不需要每个页面都重写一遍适配逻辑
- Runtime / WS / Panel 三层开始真正共享同一模型
三类消息在前端的分工
当前前端实际同时接触三类消息:
1. 协议响应
用于回答某次主动请求的返回值。
典型包括:
session-list-resulttasks-listtasks-detailtasks-historyworktree-diffworktree-mergedcompression-stats
2. Runtime Event
用于描述“系统状态发生了什么”,由 ws.js 归一化后通过 onRuntimeEvent() 广播。
典型包括:
session:startsession:resumesession:endtask:notificationworktree:diff:readyworktree:merge:completedcompression:summary
3. Session Stream
用于描述当前会话的流式输出过程,主要由 chat.js 直接消费。
典型包括:
response-tokenresponse-completetool-executingtool-resultquestion
当前口径是:
ws.js负责协议响应 → runtime event 的归一化chat.js继续直接消费 session stream- 不要求把所有流式 token 消息都迁进
onRuntimeEvent()
Session Record
会话相关数据现在统一附带 record,用于让前后端对齐会话摘要结构。
标准字段包括:
idtypeprovidermodelprojectRootmessageCounthistorystatus
当前会返回 record 的消息:
session-createdsession-resumedsession-list-result
这意味着无论是:
- 被动收到会话创建/恢复响应
- 主动拉取会话列表
前端拿到的都是同一套 session summary 结构。
会话流转
一个典型会话流程如下:
- UI 建立 WebSocket 连接
- 如果配置了 token,先发送
auth - 拉取
session-list - 创建新会话,或恢复已有会话
- 发送
session-message - 接收:
response-tokentool-executingtool-resultquestionresponse-complete
当前还有两个重要细节:
- 会话关闭后,前端会本地补发 synthetic
session:end,保持统一事件流连续。 - 当本地没有缓存消息时,切换会话会自动调用
session-resume拉回 history。
WebSocket 协议要点
| 事件 | 方向 | 说明 |
|---|---|---|
auth | →服务端 | 发送 token 认证 |
auth-result | ←服务端 | 返回认证结果 |
session-list | →服务端 | 请求会话列表 |
session-list-result | ←服务端 | 返回会话列表,sessions[] 每项带 record |
session-create | →服务端 | 创建新会话 |
session-created | ←服务端 | 返回 sessionId、sessionType、record |
session-resume | →服务端 | 恢复历史会话 |
session-resumed | ←服务端 | 返回 history[] 与 record |
session-close | →服务端 | 关闭会话 |
tasks-list | →服务端 | 查询后台任务 |
tasks-history | →服务端 | 查询任务历史分页 |
tasks-detail | →服务端 | 查询任务详情 |
compression-stats | →服务端 | 查询压缩观测摘要 |
worktree-diff | →服务端 | 查询 diff 预览 |
worktree-merge | →服务端 | 执行一键合并 |
与 serve 的关系
ui面向浏览器用户,是完整管理界面入口。serve面向外部接入,是 WS Gateway 入口。- 二者不是两套完全独立系统,而是前后配合:
ui负责页面serve/ 内置 WS 服务负责协议与 Runtime 暴露
如果你只是想打开浏览器管理界面,优先使用 chainlesschain ui。如果你要把 CLI 接到 IDE、插件或自定义前端,优先使用 chainlesschain serve。
常见联调点
1. 页面有了,但状态不更新
优先检查:
- 是否已经通过
onRuntimeEvent()订阅 - 当前消息是协议响应还是统一事件
sendRaw()的 pending resolve 之后,事件是否仍然继续广播
2. 会话列表和会话详情字段不一致
优先检查:
session-list-result.sessions[]是否带recordsession-created/session-resumed是否带record- 前端
listSessions()是否做了统一归一化
3. 任务页没有收到完成通知
优先检查:
- 是否有
task:notification - 任务页是否在消费
onRuntimeEvent() - 后台任务是否已经完成持久化与恢复初始化
4. Dashboard 统计不对
优先检查:
compression-stats是否带了windowMsprovider/model筛选参数是否透传- 统计是否来自统一 runtime event,而不是旧的局部手动赋值
安全中心
安全中心覆盖三大模块:
- DID 身份管理:列表、创建、签名验证
- 文件加解密:AES-256-GCM 加密/解密
- 审计日志:事件列表、统计卡片
P2P 网络
P2P 页面支持:
- 设备列表与在线状态
- 配对新设备
- 发送加密消息
- 同步状态查看与推送/拉取操作
Git 与数据
Git 页面包含两个 Tab:
- Git 仓库:分支显示、变更计数、自动提交(带确认弹窗)
- 导入导出:Markdown/PDF/Evernote 导入、静态站点导出
项目管理
项目页面支持:
- 项目状态卡片(系统状态、LLM、初始化、配置)
- 6 个项目模板初始化
- 环境诊断(
doctor命令)
当前验证
- Web Panel 单元测试:
523/523(9 个文件,含批次 1+2 页面解析测试) - Web Panel 集成测试:
40/40(web-ui-server + CLI 命令集成) - Web Panel E2E:
12/12(WS 协议兼容) +46SPA 路由 + 资源文件测试 - Web Panel 构建:通过
测试覆盖率
packages/web-panel/src/**/__tests__/
├── ✅ parsers.test.js # 纯函数解析层 (技能/状态/MCP/记忆/Cron)
├── ✅ theme.test.js # 4 主题切换 + localStorage 持久化
├── ✅ ws-store.test.js # WS 连接状态管理
├── ✅ chat-store.test.js # 会话与流式消息
├── ✅ tasks-store.test.js # 后台任务状态
├── ✅ dashboard-store.test.js # Dashboard 统计聚合
├── ✅ new-pages.test.js # 批次 1 新页面解析
└── ✅ batch-pages.test.js # 批次 2 新页面解析
packages/cli/__tests__/
├── integration/
│ ├── ✅ web-ui-server.test.js # HTTP 静态 + 配置注入
│ └── ✅ cli-commands.test.js # ui 命令选项解析
└── e2e/
├── ✅ ws-protocol-compat.test.js # WS 协议兼容性
└── ✅ panel.test.js # SPA 路由 + 资源加载- 前端 Store: WS / Theme / Chat / Skills / Providers / Tasks / Dashboard
- 页面解析: 23 个页面的纯函数解析层
- 集成: ui 启动链路 + WS gateway 对接
- E2E: WebSocket 协议、SPA 路由与静态资源
安全考虑
1. 输入验证
- WebSocket 消息校验: 所有入站消息经过
message-dispatcher.js的 type + schema 校验 - XSS 防护: 面板渲染用户内容(会话、技能描述)通过 Vue 的自动转义 + marked.js 的 sanitize
- 命令黑名单: WS 层禁止
serve/chat/agent/setup等交互式命令(继承自serve)
2. 权限控制
- 默认 localhost: 默认只监听
127.0.0.1,浏览器仅本机可访问 - Token 必需模式:
--token设置后,Panel 加载时通过 URL 参数或 localStorage 读取,不符合立即踢出 - 同源策略: Panel 与 WS 同源(loopback),浏览器 CORS 天然隔离
- 会话隔离: 多浏览器窗口连接时,每个 WS 连接独立管理自己的 session ID
3. 审计
- 访问日志: HTTP 请求记录到
~/.chainlesschain/logs/web-ui.log - WS 连接日志: 每次 connect / auth 成功/失败 / disconnect 均记录 IP + 时间戳
- 敏感操作溯源: 会话创建、任务触发、worktree merge 等操作在日志中可定位到具体 WS connId
4. 进程隔离
- UI 服务与 WS 服务共享同一 Node 进程;命令执行仍通过 spawn 子进程隔离
- Panel 前端通过 WS 协议调用 CLI,无本地文件写入权限
故障排查
Q: 启动后浏览器自动打开但页面空白 / 仅显示骨架?
- 打开浏览器 DevTools Console,查看是否有 WS 连接错误
- 确认
--ws-port与实际 WS 端口一致(面板通过window.__CC_CONFIG__.wsUrl连接) - 检查是否被浏览器扩展拦截(某些代理插件会阻断
ws://127.0.0.1)
Q: 提示 "WebSocket 未连接" 且仪表板全空?
- 面板内置指数退避重连,等 3-5 秒看是否自动恢复
- 确认
--token值服务端与浏览器完全一致(区分大小写) - 运行
netstat -ano | findstr :18800(Windows)/lsof -i :18800确认 WS 端口存活 - 若使用
--web-panel-dir,确认该目录包含index.html和__CC_CONFIG__注入脚本
Q: Error: listen EADDRINUSE :::18810?
端口被占用。使用 --port 9000 --ws-port 9001 或杀掉占用进程后重试。
Q: 修改代码后 Panel 没更新?
npm 全局安装的用户,面板 dist 内置在包中,需要 npm update -g chainlesschain。源码用户运行 npm run build:web-panel 重建。
Q: 主题切换后刷新又变回默认?
主题存储在 localStorage;如使用无痕模式或浏览器清理了 localStorage,会回到默认。已登录的浏览器应该持久化。
Q: 项目模式没生效,Agent 工具不识别 projectRoot?
确认启动时 cwd 是包含 .chainlesschain/ 目录的项目根目录。运行 chainlesschain ui --verbose 可在控制台看到 mode: project 或 mode: global。
关键文件
| 文件 | 职责 |
|---|---|
packages/cli/src/commands/ui.js | ui 命令入口,参数解析 + 启动编排 |
packages/cli/src/lib/web-ui-server.js | HTTP 服务器 + 静态资源 + __CC_CONFIG__ 注入 |
packages/cli/src/lib/ws-server.js | WebSocket 服务(与 serve 共享) |
packages/web-panel/src/main.js | Vue3 SPA 入口 |
packages/web-panel/src/stores/ws.js | WS 连接状态管理(指数退避重连) |
packages/web-panel/src/stores/theme.js | 4 主题状态与 localStorage 持久化 |
packages/web-panel/src/utils/parsers.js | 纯函数解析层 |
packages/web-panel/src/views/ | 23 个页面视图 |
packages/cli/src/assets/web-panel/ | npm 发布时内置的 dist 产物 |
使用示例
# 默认启动
chainlesschain ui
# 指定端口 + token(面板与 WS 同步)
chainlesschain ui --port 9000 --ws-port 9001 --token mysecret
# 不自动打开浏览器(CI / 联调)
chainlesschain ui --no-open
# 局域网分享(绑定 0.0.0.0)
chainlesschain ui --host 0.0.0.0 --token strong-token
# 开发模式:使用本地构建产物
chainlesschain ui --web-panel-dir packages/web-panel/dist
# 复用已存在的 serve 服务(前后分离)
chainlesschain serve --port 18800 --token t1 &
chainlesschain ui --ws-port 18800 --token t1 --no-open
# 项目模式(cwd 自动识别)
cd /path/to/project && chainlesschain ui
# 通过环境变量配置
CC_UI_PORT=9000 CC_UI_TOKEN=secret chainlesschain ui相关文档
- WebSocket 服务(serve) — UI 后端协议与 Gateway
- Web 管理面板(web-panel) — 23 页面的详细能力清单
- Agent 架构优化 — Agent Runtime 与 UI 的事件模型
- 设计文档索引 — 系统设计总入口
- 设计模块:Web 管理界面
- 设计模块:Web 管理面板
