浏览器聊天界面。支持用户注册/登录、邀请制和 Persona 隔离。
需要 Server 模式。
{
"web": {
"enable": true,
"port": 8082
},
"admin": {
"token": "your-secret-token"
}
}
| 字段 | 必填 | 默认值 | 说明 |
|---|---|---|---|
enable | ✅ | false | 启用 Web 渠道 |
host | ❌ | "" | 监听地址(空 = 所有接口) |
port | ❌ | 0 | 监听端口 |
static_dir | ❌ | 自动检测 | 前端静态文件目录 |
upload_dir | ❌ | "" | 上传文件自定义目录 |
persona_isolation | ❌ | false | 启用后每个 Web 用户的 persona 互相隔离 |
invite_only | ❌ | true | 禁止自主注册。默认 true(安全默认)——第一个账号仍可注册(首用户引导),之后只能由管理员创建账号。显式设为 false 才会重新开放公开注册。 |
preview_origins | ❌ | [] | 允许申请短期后端授权的外部预览前端(如 Vercel PR 预览)。为空即关闭预览授权。可写精确 origin,或一条单标签 HTTPS 通配,如 https://xbot-preview-*-<team>.vercel.app。设置了 XBOT_PREVIEW_ORIGINS(逗号分隔)时以环境变量为准。启动时读取。 |
Server 模式安装时,安装器会自动下载 Web UI 到 ~/.xbot/web/dist/。
如果需要手动安装:
# 下载对应版本的 web 压缩包并解压到 ~/.xbot/web/dist/
改了 web/ 的源码后,部署必须整体替换:
bash scripts/deploy-web.sh # npm run build + 整体部署 + 一致性自证
bash scripts/deploy-web.sh --no-build # 跳过构建,只部署当前 web/dist
Warning混合态产物是这条路上最容易踩的坑:把新构建的assets/增量拷进旧目录、而index.html保留旧版 ⇒ 服务端吐出的页面引用旧 bundle,新代码一行都不跑(症状:新功能"看着打开了" 但完全不生效)。deploy-web.sh用「整体 mv + 校验index.html引用的 bundle 存在且含探针 符号」把这条路封死;校验不过直接exit 1。
启动 Server 后,在浏览器中打开 http://your-server:8082。
新建会话:可选择工作目录;目录不存在时会自动创建(含多级父目录)。若路径被文件占住或没有权限,会明确报「工作目录设置失败」,不会静默用错目录。
富文本(WYSIWYG)编辑器,支持 Markdown 快捷语法(**粗体**、- 列表等)与链接:
| 功能 | 说明 |
|---|---|
| 链接 | 输入 https://… 后跟空格自动成链;粘贴链接/Markdown 链接语法([文字](URL))实时渲染;链接以主题色高亮显示 |
| 链接编辑 | 选中文本浮现工具栏(加粗/斜体/删除线/行内代码/链接);Ctrl/Cmd+K 快速添加或修改链接,支持一键解除 |
| 文件上传 | 支持任意类型文件(无类型白名单)。点击 📎 选择文件、直接粘贴(截图自动上传)或拖拽到输入框,文件作为附件随消息发送 |
| 上传限制 | 单文件 10MB(仅限大小,不限类型) |
| 终端命令 | 以 ! 开头的消息会作为 shell 命令在沙箱中直接执行,输出以对话消息返回(跳过 AI),例如 !ls -la、!git status、!docker ps。输入框在 ! 命令草稿时会给出提示;不会被当作命令 |
输入框里的图片按比例缩略显示,最大 240 × 120 px,窄窗口下自动适配。单击图片可放大查看,按 Esc、点击遮罩或关闭按钮退出。缩略图只改变显示尺寸,不修改上传文件或发送给模型的原图引用。
删除输入框正文中的已上传图片,会同步移除对应附件标签,发送时不再携带该图片;点击图片标签的 × 也会同步删除对应预览。同名图片按上传标识独立管理,不会一起误删。
为避免长回复选区恢复拖慢输出,原生高亮恢复仅适用于 Markdown 原文和渲染文本均不超过 16384 个 UTF-16 单位、且不超过 256 个文本节点的正文。超过上限后不强制恢复高亮,已捕获的批注引用仍可使用,输出不会暂停。上传过程中仍可发送普通文字或使用 /cancel、/tasks、/rewind;带批注的发送需等待上传完成。会话列表摘要暂时可能显示批注协议前缀,消息气泡会正常解码。
在上述限额内,流式追加内容时,只要所选文本及其前文未改变,Markdown 更新后会保留选区高亮和拖选方向。若 Markdown 格式变化改变了这部分文本,评论入口仍保留已经捕获的引用快照。
鼠标拖选助手正文后,评论图标会出现在松开鼠标的位置附近,并保持在可视区域内;键盘和手机原生选文时,图标出现在选区附近。点击即可添加批注,不需要右键,也不必等待输出结束。整段选中最后一段正文(含段末换行)也可批注;实际选到工具文字或另一条回复则不支持。文字仍在逐步显示时,也可以拖选已出现的片段;选中后回复继续输出,所选引用保留为快照,不会因为后续文本更新而撤掉评论按钮。手机长按选中文字后,可用原生选区手柄调整范围。编辑器只显示所选片段的只读快照,编辑框和预览均不显示轮次、迭代和字符计数。评论框按 Enter 确认、Shift+Enter 换行,输入法选词不会误确认;确认仅添加草稿,不会发送消息。点击别处、通过键盘取消选区、滚动、调整视口或切换会话后,图标消失;右键菜单仍用于复制和链接操作。思考、工具输出和用户消息不开放批注。
勾选确认后,批注进入现有输入框内部的计数 chip,与附件同层;点击计数可预览、编辑和删除。添加或编辑不会覆盖正文、链接、图片和附件,也不会触发 Agent。可仅发送批注,或与正文、附件一起发送;Agent 忙碌时按普通反馈排队。批注不能与 slash/shell 命令、目标模式或插话模式混用。
已确认批注按登录用户名和渠道/会话保存在当前浏览器,刷新可恢复,退出登录清理。发送被拒绝时保留草稿,迟到的成功响应不会清空后来新写的正文。限制:每次 10 条,引用 6000 个 Unicode code points,评论 2000 个,总计 20000 个;超限明确拒绝,不截断。
发送内容采用 <response-annotations> 包裹的 JSON 数组 {text, annotation, source},再通过 # My request: 携带输入框原有正文。Agent 会收到引用原文、用户评论以及已知的来源位置(轮次、迭代、消息 ID 和选区偏移)。偏移是渲染正文拼接 DOM 文本中从 0 开始、左闭右开的 UTF-16 位置,不是原始 Markdown 的偏移。旧草稿缺失位置仍可使用,不会编造。提示明确区分历史引用与本次用户指令。
聊天气泡仍只显示正文、引用和评论,不显示 XML 或来源标签;复制或编辑消息时保留实际发送的 XML prompt。反馈沿用现有历史和队列。来源位置只是选中时的快照,不是撤回后的永久链接或锚点。首版不包含私有备注、服务器/跨设备草稿、原文高亮或重启后持久化发送去重。输入框仍挂载时,内容未变的重试复用请求 ID,受服务器既有去重窗口约束;刷新或重启后的恢复不保证 exactly-once。
会话列表默认按项目组织 —— 项目 = 该会话的工作目录(后端 tenants.cwd)。同一目录下的会话归为一组,组头显示项目名 + 会话数(悬停可看完整路径;没有工作目录的会话归入「未设置工作路径」)。
列表上方的视图栏可切换组织方式(桌面左栏与手机抽屉完全一致):
| 分类 | 分组键 |
|---|---|
| 项目(默认) | 工作目录 |
| 状态 | 运行中 / 等待输入 / 排队 / 未读 / 空闲 / 错误 |
| 时间 | 今天 / 昨天 / 更早 |
折叠 / 展开:点组头折叠或展开该组;点视图栏右侧的「全部折叠 / 全部展开」一次改所有组。折叠状态按项目记住(存 localStorage,纯前端、不跨设备同步),刷新或重开面板后保持。
从旧版本升级:旧默认是「按时间」,首次打开会自动切到「按项目」一次;此后你手动选择的分类不会再被改动。
删除确认:在会话菜单中选择「删除」后,按 Enter 确认、Esc 取消;即使焦点在「取消」按钮上,Enter 也会确认删除。输入法确认和长按重复按键不会触发删除,请求进行中不会重复提交。
会话快捷键仅桌面端提供。移动模式不显示快捷键设置分类和菜单键位提示,也不监听这七项绑定;原有触屏/菜单操作和弹窗确认不受影响。是否启用跟随「设置 → 外观」中的实际 UI 模式,手动强制移动模式同样不启用。切换模式不会清空键位,回到桌面端后仍可使用原有配置。
在独立的 设置 → 快捷键 分类中编辑全部七项会话键位;「交互」保留代码换行和发送键模式。直接输入组合键后按 Enter 或移出输入框保存,也可点击键盘图标录制;操作菜单可清空解绑或恢复单项默认,标题栏右侧的「全部恢复默认」重置整组。重复键位和已注册命令的冲突会被拒绝。修改即时作用于操作和菜单提示,刷新保留并随账号同步。
自定义 Control 与 Command 分别匹配,Mod 在 Mac/Linux 上表示 Ctrl/Cmd,在 Windows 上只匹配 Ctrl;不允许绑定无修饰的文字/导航键,F1-F24 可单独使用。Esc 取消录制,输入法和长按事件不会保存键位。系统/浏览器保留的组合键可能无法送达网页,录制收不到时可手动输入其他键位。下表为默认值。
| 操作 | Mac | Linux | Windows |
|---|---|---|---|
| 创建新会话 | Ctrl/Cmd+Alt+N | Ctrl/Cmd+Alt+N | Ctrl+Alt+N |
| 在新标签页中打开已有会话 | Ctrl+N | Ctrl+Shift+2 | Ctrl+Shift+2 |
| 标星 / 取消标星 | Ctrl/Cmd+Alt+S | Ctrl/Cmd+Alt+S | Ctrl+Alt+S |
| 重命名 | F2 | F2 | F2 |
| 分叉会话 | Ctrl/Cmd+Alt+F | Ctrl/Cmd+Alt+F | Ctrl+Alt+F |
| 导出(选择原生 / OpenAI / Codex 格式) | Ctrl/Cmd+Alt+E | Ctrl/Cmd+Alt+E | Ctrl+Alt+E |
| 打开删除确认 | Ctrl/Cmd+Alt+Backspace | Ctrl/Cmd+Alt+Backspace | Ctrl+Alt+Backspace |
Windows 使用独立的快捷键配置,首次使用从自己的默认值开始,不复制已有 Mac/Linux 键位。Windows 上的编辑、解绑和恢复默认不会覆盖 Mac/Linux 偏好,两份配置随账号独立同步。产品默认键按 Command → Control、Option → Alt 映射,Shift 保持不变;不会翻译已保存的自定义修饰键或合并 Control+Command。已有 Windows 自定义键(包括旧数字组合和解绑状态)保持原样。修饰键产生符号时仍按物理键位匹配,AltGr 输入被排除。系统、浏览器和自定义输入法切换键仍可能冲突,全部键位均可编辑。
「创建新会话」全局生效,无当前会话或会话面板隐藏时也可使用,创建后直接切到新会话。旧 openInTab 自定义键位(包括已解绑状态)仍保留给创建新会话;独立的 openInBrowserTab 用于在浏览器新标签页打开已有会话,不创建或切换原页面的会话。Mac 默认 Ctrl+N 只匹配 Control,不匹配 Cmd+N;Linux 和 Windows 默认使用 Ctrl+Shift+2,避开浏览器新建窗口键 Ctrl+N。已保存的自定义键位保持原样,恢复默认时采用当前平台的默认值。如果浏览器占用,可在设置中修改。
其余六项在菜单中显示对应键位;Mac 的 Alt 即 Option。这六项优先作用于已打开的会话菜单或聚焦的会话行,否则作用于当前会话(会话面板需可见),多选模式不触发。全部七项都不会抢占输入框、编辑器、AskUser 选项/按钮、输入法和长按重复事件;创建操作在任何弹窗/菜单打开时暂停,其余六项忽略无关弹窗/菜单。子代理和合成会话行/菜单只支持非破坏性的新标签页打开,不支持修改类快捷键。重命名和分叉需按 Enter 或按钮确认,Esc 取消;导出在右键菜单中打开格式子菜单,在会话行或当前会话上打开格式选择弹窗。删除快捷键不会跳过确认。
| 方式 | 说明 |
|---|---|
| 用户名/密码 | 注册后登录,Session Cookie 有效期 30 天 |
| CLI Token | WebSocket 连接时使用 admin token |
| 飞书登录 | 通过飞书账号一键登录/关联 |
当 invite_only: true 时:
- 新用户无法自主注册(返回 403)
- 管理员可通过飞书渠道的管理命令或直接操作数据库创建账号
- 适合内部团队使用
全新部署还没有任何账号,因此第一次注册会被放行——该账号即成为管理员。注册页会明确提示「首次设置 · 仅此一次」,并说明注册随后自动关闭,访客不必猜测注册接口是否对所有人开放。账号创建后,/register 显示 invite-only 通知,登录页也不再显示注册入口。
Web UI 有桌面与移动两套外壳,默认按视口宽度自动选择(≤767px 用手机外壳)。窄屏平板、横屏手机或桌面窄窗口边缘场景下,自动判断未必符合预期,因此可以在设置 → 外观 → UI 模式手动固定:
| 模式 | 行为 |
|---|---|
| 自动(默认) | 跟随视口断点(≤767px = 手机外壳) |
| 桌面 | 始终使用桌面外壳(多面板 / Dockview 布局) |
| 移动端 | 始终使用手机外壳(抽屉会话 + 底部导航) |
偏好存本地(localStorage)即时生效,并同步到服务端(web:ui:ui-mode),换设备/浏览器后保持一致。该设置只切换外壳,不改变 CSS 断点——在窄屏上强制桌面外壳会得到被压缩的桌面布局。
当 persona_isolation: true 时:
- 每个 Web 用户的系统人格(persona)互相隔离
- 用户 A 设置的 Agent 行为不影响用户 B
- 适合多租户场景
Web 设置 → 存储可切换后端,保存即生效,无需重启:
| 后端 | 说明 | 保留策略 |
|---|---|---|
| 本地(默认,免配置) | 上传写 <XBOT_HOME>/uploads/,由同源 /api/files/download 读盘返回 | 每次上传后只保留最新 500 个(按文件修改时间;没有时间上限,等于 500 ÷ 日均上传数 天) |
| 阿里云 OSS / 腾讯云 COS | S3 兼容:复用同一组凭据,endpoint 由 region 自动推导(cn-hangzhou → oss-cn-hangzhou.aliyuncs.com;ap-guangzhou → cos.ap-guangzhou.myqcloud.com),也可手填 endpoint 覆盖(MinIO/R2/自建网关) | 云端不会自动过期 |
| 七牛 Kodo / S3 兼容 | 对象存储为权威;本地仍留一份副本供模型拿到真实路径 | 云端不会自动过期(如需过期请在云控制台设 lifecycle) |
- 上传:编辑器里粘贴/拖拽 →
POST /api/files/upload(≤10MB,类型不限制)→ 返回upload_key,消息正文里只存相对引用(不存 base64;取不到时显示占位)。 - 取回:
GET /api/files/download?key=…(默认「下载」,加&inline=1才内联渲染)。 - 凭据在读取时打码(
AKID****),回写掩码值不会覆盖真实密钥;切到云后端前必须给齐 access/secret/bucket(阿里云 OSS / 腾讯云 COS 还需 region,除非手填 endpoint),否则会拒绝保存(避免半配置把上传打断)。 - 想让模型"看到"图片,还需在 设置 → LLM → 模型行 → 视觉输入(多模态) 打开对应模型的开关。
桌面会话面板和手机会话抽屉均提供「多选」。进入后,点击或按 Space/Enter 勾选主会话,不会切换当前会话。Shift 连选遵循显示顺序;全选只包括当前已加载、符合搜索条件且所在分组已展开的主会话,子代理和占位会话不参与。还有未加载会话时会显示范围提示。
可批量标星、取消标星、标为已读、导出和删除。导出统一选择 xbot / OpenAI / Codex 格式,每个会话一个文件,下载一个 ZIP。删除先显示数量和名称并要求确认;导出或删除部分失败时显示结果,失败项继续选中,便于重试。
「清空选择」保留多选模式;「退出多选」或 Escape 退出。列表聚焦时 Ctrl/Cmd+A 全选,输入区和弹窗不会被截获。改变搜索、渠道或分类会清空选择;新加载的会话不会自动勾选。
Vercel 仅托管静态前端。预览模式先显示连接门禁,后端地址默认为 http://localhost:8082;测试连通性不代表授权。后端需由用户在 web.preview_origins 中配置允许的预览 origin(或用 XBOT_PREVIEW_ORIGINS 覆盖),可写精确 origin,也可写一条单标签通配,如 https://xbot-preview-*-<team>.vercel.app,配好后重启一次,之后的新部署无需再重启;授权仍绑定具体 origin,在本地登录并确认授权后,粘贴短期令牌才能进入工作区。令牌仅在内存中保存,具有完整工作区能力,并非只读沙箱。详见 docs/vercel-preview.md;不要把凭据配置到 Vercel,也不要为前端部署自动重启后端。