跳转到内容

消息与对话

消息是用户与 AI 交互的载体。用户发送消息,AI 流式返回回复,支持 Markdown 渲染、代码高亮、思考过程展示、工具调用卡片——整个过程实时可见。

类型说明渲染方式
💬 用户消息用户输入的内容纯文本
📝 AI 回复AI 生成的文本Markdown + 代码高亮
🧠 思考过程AI 的推理过程可折叠,Markdown 渲染
⚙️ 工具调用AI 请求执行的工具输入/输出卡片
📄 压缩摘要上下文压缩后的摘要(summary)Markdown 渲染
📃 纯文本未格式化的文本内容(text)纯文本
🔧 工具消息独立的工具角色消息(tool role)输入/输出卡片
📩 用户消息用户输入的内容,含场景注入(user_message)纯文本 + 场景标签
📜 系统提示词持久化系统级指令(prompt)不直接渲染
ℹ️ 系统消息系统通知纯文本

MessageRole 共 4 种:user、assistant、system、tool ContentType 共 9 种:text、markdown、summary、thinking、toolcall_input、toolcall_output、user_message、error、prompt

消息采用本地优先策略:先存本地立即显示,后台异步同步。用户发消息后零等待即可看到消息出现在界面上。

同步状态用户看到的行为
pending消息显示发送中动画
synced消息正常显示
failed消息显示失败标记 + 🔄 重试按钮

💡 重试使用相同的 client_id,服务端幂等去重,不会产生重复消息。

每次 AI 处理构成一个 Turn,它有明确的生命周期:

状态含义用户看到的行为
Pending等待执行消息显示”处理中”
Running正在执行AI 流式输出,工具卡片闪烁
Interrupted等待工具执行工具卡片显示”执行中”
Completed正常完成AI 回复完整显示
Failed执行失败错误提示
Cancelled用户取消已停止标记
Merged合并到其他轮次不单独展示

AI 的回复逐字流式到达,用户无需等待完整回复:

流式消息通过 双频道 传输:

频道用途特性
Topic 频道首条 chunk + 最终完整消息持久化,支持离线恢复
Live 频道中间 chunk非持久化,低延迟,可容忍丢失

💡 最终完整消息通过 Topic 频道推送,即使中间 chunk 丢失,最终也能收到完整内容。

用户可随时停止正在执行的 Turn:

AI 的推理过程默认折叠,用户可选择展开查看:

特性说明
默认折叠节省界面空间
点击展开查看完整推理过程
流式动画生成时有脉冲动画效果
Markdown 渲染支持格式化显示

每次 RTC 工具调用以卡片形式展示,包含输入和输出两部分:

特性说明
分区展示输入参数和输出结果独立展示
JSON 格式化参数和结果自动美化
状态指示运行中(🟠 橙色脉冲)/ 完成(🟢 绿色)
复制按钮一键复制输入/输出内容

工具调用卡片界面

特性说明
📊 排序按发送时间升序(最早的在上)
📑 分页游标分页,从服务端加载历史消息
📜 自动滚动新消息到达时自动滚动到底部
🔔 离开提示用户滚动离开底部时显示”↓ 新消息”按钮
场景处理方式
发送失败标记 failed,显示重试按钮
幂等保证使用 client_id 去重,重试不产生重复消息
RTC 失败指数退避重试(1s → 2s → 4s → … → 30s 封顶)

user_message 是第 7 种 ContentType,用于支持 场景注入——在用户消息中嵌入结构化上下文,服务端将其解析后以系统提示词的形式注入 LLM。

{
"type": "user_message",
"data": {
"text": "请帮我创建一个任务",
"scenarios": [
{
"filepath": "/scenarios/create-task.md",
"title": "Create and Complete a Task",
"file_content": "# Create Task\n\n..."
}
],
"files": []
}
}
字段类型说明
textstring消息文本内容
scenariosScenarioRef[]场景列表(可选),包含完整文件内容
filesFileAttachment[]文件附件列表(可选)
字段类型说明
filepathstring场景文件路径
titlestring场景标题
file_contentstring场景文件完整内容(Markdown 格式)
字段类型说明
fileidstring文件唯一标识(内容标识符)
mimetypestringMIME 类型(如 image/png、application/pdf)
extraobject扩展字段(如 name、size)

File ID 格式规范:

File ID 是文件内容的唯一标识符,格式为 {md5}.{ext}:

  • {md5}:32 个十六进制字符(小写 a-f 或数字 0-9)的文件内容 MD5 哈希值
  • {ext}:1-10 个字母数字字符的文件扩展名(如 txt、jpg、pdf)

示例:

  • ✅ 正确:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt
  • ✅ 正确:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7.jpg
  • ❌ 错误:user-550e8400.../a1b2c3d4...txt(不应包含用户前缀)
  • ❌ 错误:myfile.txt(MD5 格式错误)

💡 File ID vs File Key:File ID 是客户端使用的内容标识符({md5}.{ext}),服务端在存储时会构造完整的 S3 Key:user-{userId}/{fileid}。客户端只需传递 File ID,服务端会自动添加用户前缀进行验证和存储。

💡 注入机制:服务端从 UserMessageContent.Scenarios 提取场景,以 <scenarios> XML 标签注入系统消息。最终消息顺序为:[system] Attachments → [system] Scenarios → [system] Command prompts → [conversation history]。

用户可以在消息中附加图片和文本文件,Agent 能够识别图片内容(视觉理解)和读取文本内容,从而基于附件信息进行推理和回答。

操作方式说明
附件按钮点击输入区域工具栏的附件图标,打开文件选择对话框(接受 image/*、text/*)
粘贴上传使用 Ctrl+V / Cmd+V 粘贴剪贴板中的图片或文件
文件预览点击已附加的文件缩略图,打开全屏预览模态框(图片支持缩放查看,文本文件显示内容)
上传重试文件上传失败时,点击重试图标手动重新上传(文件保留在内存中,无需重新选择)

上传流程:文件先在本地缓存(生成 File ID),立即显示缩略图预览,然后后台上传至对象存储。上传失败时会显示错误状态和重试按钮,用户可手动重试或继续发送消息(允许带失败附件发送)。

类别MIME 类型最大大小处理方式
图片(支持)JPEG、PNG、BMP、TIFF原始 20MB / base64 5MB自动缩放至 2000x2000,多级 JPEG 压缩
图片(不支持)WebP、GIF-当前不支持,请转换为 JPEG 或 PNG
文本text/*256KBUTF-8 校验,超长截断
  1. 读取:从对象存储读取原始数据(限制 20MB)
  2. 检测:通过 magic bytes 检测真实 MIME 类型
  3. 解码:自动应用 EXIF 方向校正
  4. 快速路径:若已满足尺寸要求,直接返回
  5. 缩放:使用 Lanczos 算法缩放至 2000×2000 边界框内
  6. 压缩:依次尝试 JPEG 质量 80→60→40→20,直到 base64 编码后 ≤ 5MB
  7. 兜底:若仍超限,缩小至 400×400 并以最低质量输出
  8. 注入:以 base64 格式嵌入 LLM 请求的 image content part
  1. 读取:从对象存储读取文本数据(限制 256KB)
  2. 校验:验证文件内容为合法 UTF-8 编码
  3. 截断:若超过 256KB,在 UTF-8 字符边界处安全截断,并附加截断提示
  4. 包裹:使用 XML 标签包裹:<file_content name="文件名" type="MIME 类型">内容</file_content>
  5. 追加:将包裹后的文本追加到用户消息的 Content 字段
条件说明
所有文件上传完成存在上传中(loading)或失败(error)的文件时,发送按钮禁用
上传失败处理失败的文件可重试,或删除后重新上传

💡 文件附件在消息发送时随 user_message 一同提交,服务端并行加载所有文件以提升多文件场景的响应速度。当用户连续发送多条带图片的消息时,服务端会将相邻的同角色消息的 MultiContent(图片内容)合并,确保所有图片都被 LLM 识别。

前端通过 rtc-token-usage Web Component 在输入区域工具栏实时展示 Token 消耗和成本信息。

显示项数据来源说明
圆环进度compression_progress当前上下文占压缩阈值的百分比
总 Tokentotal_tokens累计消耗的总 Token 数
总成本total_cost_usd累计成本(美元)
输入/输出total_input_tokens / total_output_tokens分类 Token 统计
缓存命中率cached_read / input缓存读取占总输入的比例(上限 99%)
预估下轮estimated_next_round_tokens基于 EWMA 的下一轮 Token 预估
压缩倒计时rounds_until_compression距离下次自动压缩的轮次数

后端推送的 session.updated 事件中的 snake_case 字段会映射为前端 camelCase 属性:

协议字段(snake_case)前端属性(camelCase)说明
current_context_tokenscurrentContextTokens当前上下文 Token 数
estimated_next_round_tokensestimatedNextRoundTokens预估下轮 Token 数(圆环进度分子)
compression_thresholdcompressionThreshold压缩触发阈值(圆环进度分母)
compression_progresscompressionProgress压缩进度(0-100)
rounds_until_compressionroundsUntilCompression距压缩轮次数
total_tokenstotalTokens累计总 Token
total_cost_usdtotalCostUsd累计成本

圆环进度计算公式:estimatedNext / compressionThreshold * 100%

进度范围颜色含义
< 50%🔵 蓝色上下文充裕
50% - 70%🟡 黄色接近压缩阈值
> 70%🔴 红色即将触发压缩

💡 当 roundsUntilCompression 在 0-3 轮时,tooltip 底部显示 “X 轮后压缩 (Y%)” 提示;小于等于 1 轮时升级为警告色。