跳转到内容

前端架构

RTC Agent 的前端是一个基于 Lit Web Components 构建的组件库。对外只暴露一个 <rtc-agent> 组件,内部包含 57 个子组件,使用 23 个 Controller 管理状态,通过 @lit/context 向子组件分发数据。

文件浏览器

文件浏览器:左侧为虚拟文件系统目录树(functions/、scenarios/、scripts/),右侧为编辑器 + 实时预览。所有文件数据存储在浏览器 IndexedDB 中。

设置界面

设置界面:支持主题切换、语言选择、字体大小调整等个性化配置。

组件用途替换关系
rtc-chat-layout两栏聊天布局(会话树 + 内容区)替代旧版 rtc-content-wrapper
rtc-session-treeVS Code 风格会话树侧栏新增
rtc-session-tree-item树节点(递归渲染)新增
rtc-session-tab-bar浏览器风格标签栏新增
rtc-session-tab单个标签页新增
rtc-settings-panel设置侧抽屉面板新增
rtc-settings-layout设置两栏布局新增
rtc-settings-nav设置分类导航新增
rtc-file-preview-area附件预览区(水平滚动缩略图列表)新增
rtc-file-thumbnail文件缩略图(上传进度、删除、预览)新增
rtc-file-preview-modal文件全屏预览弹窗(图片/文本)新增

宿主应用只需引入一个组件即可使用全部功能:

属性说明示例
theme主题切换light / dark / system
lang界面语言zh-CN / en-US
app-label标题栏文字 + 气泡 tooltip"RTC 助手"
database-nameIndexedDB 名称前缀"my-app-rtc"
server-url服务端地址"https://rtc.example.com"
redirect-uriOAuth 回调地址"/auth/callback.html"
bubble-icon最小化气泡内的 SVG/HTML自定义图标
logo自定义品牌 Logo(light/dark 两套){ light: '<svg>...', dark: '<svg>...' }
worker-urlSharedWorker 文件 URL"/rtc-agent/shared-worker.js"
scenarios-url场景文档 URL"https://..."
agentConfig声明式函数注册(推荐)JSON 配置对象

详细 API 说明见 Component API。

ControllerContext说明
SessionTreeControllerSessionTreeContext管理会话树结构、展开/折叠状态
NotificationControllerNotificationContext管理通知状态、音效、焦点检测
SettingsControllerSettingsContext管理全局设置、localStorage 持久化

此外,还有以下辅助模块:

模块说明
LocaleController / i18n国际化支持,运行时语言切换
SessionTabController管理标签页状态(SessionTabContext)
ToastController管理 Toast 通知展示
原则说明
Controller 不互相引用每个 Controller 独立管理自己的状态切片
根组件编排<rtc-agent> 作为中枢,协调跨 Controller 通信
Context 分发通过 @lit/context 向子组件分发状态,避免 prop drilling
数据层隔离Persistence Controller 统一管理 IndexedDB 读写

💡 为什么不用全局状态? Web Components 运行在宿主应用的页面中,可能有多个实例。例如一个页面同时嵌入”客服助手”和”数据分析助手”两个 <rtc-agent>,它们需要各自独立的会话、消息、认证状态。Controller + Context 保证每个实例的状态完全隔离,互不干扰。

RTC Agent 内置了离线优先的文件存储系统,通过 FileStorageContext 向子组件分发 FileStorage 实例。所有文件操作都先写入本地 IndexedDB 缓存,再后台同步到 S3,保证离线场景下的可用性。

FileStorage 核心 API:

方法说明
cacheFileForUpload(file)缓存文件到本地 IndexedDB,计算 MD5,返回 FileInfo(含 md5、ext、size)
upload(options)上传文件到 S3,支持 onProgress 回调,返回 FileInfo(含 syncStatus)
download(md5, ext, options?)下载文件,优先从本地缓存读取,缓存未命中时从 S3 下载
getThumbnailUrl(identifier)获取图片缩略图 URL(返回 blob URL,需调用 releaseThumbnailUrl() 释放)
getPresignedUrl(identifier, expires)获取 S3 预签名 URL(用于降级场景)
list(filter?)列出文件,支持分页和过滤
delete(identifier)删除文件(同时删除本地缓存和 S3)
getCacheStats()获取缓存统计信息(文件数、占用空间)

离线优先特性:

  • 文件上传先写入本地缓存(syncStatus: 'pending'),缩略图立即可显示
  • 网络恢复后,后台自动同步到 S3(syncStatus: 'synced')
  • 下载优先读取本地缓存,缓存未命中时才请求 S3
  • 支持中断恢复:resumeInterruptedUploads() 恢复未完成的上传任务
交互实现
拖拽title-bar 作为拖拽手柄
缩放四角 + 四边共 8 个缩放手柄
键盘方向键移动,Shift 加速
视口约束始终保持在可视区域内
层级内容自定义方式
Design Tokens间距、字体、圆角、阴影、过渡、z-index覆盖 CSS 变量
颜色主题light / dark 两套配色theme 属性切换
CSS 变量窗口尺寸、气泡大小--rtc-* 前缀变量

文件上传流程:

  1. 触发方式:点击附件按钮打开文件选择器,或使用 Ctrl+V / Cmd+V 粘贴剪贴板中的文件
  2. 本地缓存:文件先写入本地 IndexedDB 缓存(FileStorage.cacheFileForUpload()),生成真实的 fileid(md5.ext 格式)
  3. 即时预览:缩略图立即显示(rtc-file-thumbnail 从 FileStorage 缓存加载),无需等待 S3 上传
  4. 后台上传:后台调用 FileStorage.upload() 上传到 S3,实时显示上传进度(0-100%)
  5. 状态管理:每个文件有三种状态 —— loading(上传中)、loaded(成功)、error(失败)
  6. 重试机制:上传失败的文件显示重试按钮,点击后重新上传
  7. 发送条件:所有文件上传完成后,发送按钮才可用;发送时文件列表随消息一起提交
特性行为
自动滚动新消息到达时自动滚动到底部
智能暂停用户手动上滑时暂停自动滚动
新消息提示用户离开底部时显示”新消息”按钮
渲染Markdown 渲染 + 代码高亮

用户输入 / 开头的文本时,触发命令输入模式:

命令类型功能
/compactRPC手动触发上下文压缩
/loop本地 + RPC循环执行任务(定时 / 动态)
/goalPrompt目标驱动,AI 设置完成条件,Judge 模型检查

详见 命令系统。

前端工程采用多层测试策略,覆盖单元测试、集成测试与端到端测试,确保组件行为正确、跨模块协作稳定。

工具用途配置位置
Vitest单元测试 & 集成测试packages/*/vitest.config.ts
Playwright端到端测试 (E2E)packages/component/playwright.config.ts
jsdom浏览器 API 模拟(Vitest 环境)test-setup.ts 中 polyfill IndexedDB、matchMedia、ResizeObserver 等
fake-indexeddbIndexedDB 纯 JS 实现,供 Dexie 在测试中使用test-setup.ts 自动导入
包单元测试文件数说明
@rtc-agent/component62覆盖所有 Controller、组件、工厂函数、事件系统、认证流程
@rtc-agent/persistence12覆盖 IndexedDB 操作、实体仓库、事务、偏移管理器、脚本引擎
@rtc-agent/client1覆盖 WebSocket 客户端、偏移同步、gap-fill 逻辑
@rtc-agent/worker1覆盖 SharedWorker 核心消息路由
E2E (Playwright)6覆盖调试 API、业务流程、高级交互、文档协调、脚本执行

当前共计 835+ 单元测试用例,全部通过。

终端窗口
# 运行所有单元测试(在 web-components 根目录)
pnpm test
# 仅运行 component 包的单元测试
pnpm --filter @rtc-agent/component test
# 运行 E2E 测试(需要 Vite 开发服务器)
pnpm --filter @rtc-agent/component test:e2e
# 运行特定测试文件
npx vitest run packages/component/src/controllers/auth.controller.test.ts
# 监听模式(开发时推荐)
npx vitest

packages/component/src/test-helpers.ts 提供测试基础设施:

工具说明
fixture(template, options?)创建 Lit 组件测试夹具,自动等待更新周期完成
nextFrame()等待一帧,确保 Lit 完成渲染
cleanupFixtures()清理所有已创建的测试夹具,防止测试间污染
provideContext()在 setup 阶段注入 @lit/context,确保组件首次更新前上下文就绪

E2E 测试依赖调试页面 (/debug/index.html) 暴露的 window.rtcAgentDebug API。该 API 在开发模式下自动安装,提供以下能力:

方法说明
waitForReady(timeout?)等待 <rtc-agent> 组件就绪
sendMessage(text)发送消息
getSessionController()获取会话控制器
getActions(controller)获取指定控制器的 actions

GitHub Actions CI 在每次 push/PR 时自动执行:

终端窗口
pnpm install → pnpm build → pnpm typecheck → pnpm test

Node.js 版本:24。测试在 ubuntu-latest 环境运行。

场景策略
大消息列表消息分页加载(cursor pagination),首次加载最近 50 条
长对话滚动虚拟滚动优化(未来版本)
Markdown 渲染按需渲染,代码高亮延迟加载
IndexedDB 读写Persistence Controller 统一管理,批量操作减少 IO
特性实现
键盘导航Tab 键切换焦点,Enter 激活,Esc 关闭弹窗
ARIA 标签所有交互元素添加 aria-label
屏幕阅读器消息列表使用 role="log",新消息自动播报
高对比度支持系统高对比度模式