Files
EzVibeR/docs/usage/05-聊天功能.md
Claude Agent 205c57e9b7 Update: Usage
2026-06-20 14:55:47 +08:00

7.7 KiB
Raw Permalink Blame History

05 · 聊天功能

聊天面板位于桌宠窗口右侧(默认 340 px 宽)。可一键收起让模型占满窗口。

第一次启动时聊天面板默认展开。改 chatCollapsed 状态:在工具栏点 💬 按钮(顶部第一个)即可。

1. 面板顶部一条

[●] [会话下拉(标题 消息数)]  [+新建] [✎重命名] [🗑删除]  ___  [🔔提醒中心] [🔍搜索导出]
元素 行为
● 状态点 🟢就绪 / 🟠思考中 / 🔴API key 未配置 / 未知
会话下拉 切换已有会话,按 updated_at 倒序
新建一个空会话(标题默认 对话 MM-DD HH:MM
重命名当前会话(标题 ≤ 40 字符)
🗑 删除当前会话(确认弹窗)
🔔 跳到「提醒中心」伪会话(激活态高亮)
🔍 展开/收起第二行工具栏(搜索 + 导出)

在「提醒中心」时,✎ 和 🗑 自动禁用(提醒中心不可重命名/删除)。

2. 第二行(点击 🔍 展开)

元素 行为
搜索框 输入关键字回车 → 当前会话内即时过滤 + 黄色高亮
🌐 全部 弹出全局搜索弹窗(跨会话),点命中条目跳过去
⬇ MD 把当前会话导出为 Markdown 文件,浏览器自动下载
⬇ JSON 把当前会话导出为 JSON 文件,浏览器自动下载

3. 消息流

时间顺序展示当前会话的所有消息。跨日时自动插入灰色圆角日期分割线:

  • 今天(今天的全部消息前)
  • 昨天(昨天的全部消息前)
  • YYYY-MM-DD(更早的)

分割线不存盘,是按消息 ts 现场算的,所以不用管它,刷新/重启会自动重算。

3.1 消息类型与颜色

类型 来源 样式
user 你输入 右对齐气泡
assistant LLM 回复 左对齐气泡
reminder 系统定时提醒 / 手动触发 绿松石色气泡(🪧 action_type
screenshot 截图预览(不持久化 中央居中,带"取消/发送给AI"按钮
system 错误提示(如 [401] API key 无效 灰色文字

3.2 思考气泡

如果 LLM 是 DeepSeek / QwQ / o1 这类带推理的模型,回复里会含 <think>...</think> 块。

  • 自动折叠为 💭 思考过程 ▶ 小标签
  • 点击展开看到完整推理
  • 支持多个 <think> 块拼接、容错未闭合块、<thinking> 标签
  • 展开后再次点击收起

3.3 截图气泡的生命周期

[桌宠身体被点击] → 后端截图 → emit('ezvibe:screenshot-captured')
                  → 前端 save_chat_image 存盘
                  → 推一条 role='screenshot' 消息(含 imagePath / imagePngPath
                  → 渲染为带输入框和"取消/发送给AI"按钮的预览气泡
            ┌─────┴─────┐
   [点"取消"]        [输入文字 → 点"发送给AI"]
        │                    │
        └─→ 立刻 removeMessage立即消失
                            └─→ 立刻 removeMessage
                            └─→ 推一条 role='user' (含 imagePath + 文字)
                            └─→ 调 invoke('chat', { message, imagePath })
                            └─→ LLM 回复后推一条 role='assistant'

⚠️ screenshot 消息三层防御不写盘:

  1. 前端 removeMessage 顺手清 persistTimers 里的 debounce
  2. 后端 append_message 拒绝 role=screenshot
  3. 后端 load_session_messages 跳过 role=screenshot 行 所以即使你狂点也不会"复活"。

3.4 截图发送给 AI 的限制

  • 图片后缀必须是 .png / .jpg / .jpeg
  • 路径必须sessions/<id>/images/xxx 形式(前端用 appDataDir() + join 拼绝对路径)
  • 拒绝绝对路径 / 路径遍历(.. / 非法 session id
  • 文件大小上限 20 MB(防止 OOM
  • 给 LLM 用的是 JPEG 预览80% 质量,几百 KB不是 PNG 原图 — LLM 视觉够用且体积小 10 倍

4. 输入框

[ 多行文本框 (Enter发送 / Shift+Enter换行) ]  [发送]
行为 说明
Enter 发送(前提:输入非空 且 LLM 已配置)
Shift+Enter 换行
空消息 发送按钮 disabled
LLM 未配置 placeholder 提示「请先到配置中心填写 API key」
思考中loading 整个输入区 disabled状态点变橙色底部出现"桌宠正在思考…"

5. 多会话管理

5.1 新建会话

→ 新会话立刻出现在下拉里,自动切过去,标题默认 对话 MM-DD HH:MM

5.2 切换会话

点下拉选别的会话。切换时自动加载该会话的所有历史消息JSONL 读盘)。

5.3 自动标题

  • 触发条件:消息数 ≥ 5从未生成过标题
  • 时机:前端检测到 append_message 返回的新 msg_count 达到阈值时,调 check_title_trigger + generate_session_title
  • 实现:异步调 LLM 总结前 5 条消息,输出 ≤ 20 字符短标题(中文 ≤ 12 字 / 英文 ≤ 20 字)
  • 失败降级LLM 报错就保持默认 对话 MM-DD HH:MM,下次还满足条件会再试

5.4 重命名

点 ✎ → 顶部弹输入框 → 输入新标题(≤ 40 字符)→ 回车确认。Esc 取消。

5.5 删除

点 🗑 → 确认弹窗 → 整个会话目录 + 索引条目都删(包括该会话的所有截图)。

5.6 提醒中心(伪会话)

  • 标题固定 🔔 提醒中心ID 固定 __reminders__
  • 不可重命名 / 不可删除 / 不参与 LLM 自动标题
  • 所有定时触发的健康提醒自动写入这个会话(后端直接落盘,不依赖前端)
  • 来新提醒时自动跳转到提醒中心视图(即使你正在看别的会话)

6. 搜索

6.1 当前会话搜索

  • 🔍 展开第二行工具栏 → 输入关键字
  • 即时过滤(输入就过滤)
  • 命中片段在气泡里以黄色背景高亮<mark> 标签)
  • 切回空输入恢复显示全部

6.2 全局搜索

  • 点工具栏 🌐 全部 按钮 → 弹出模态框
  • 列出所有会话中包含该关键字的消息
  • 每条命中显示上下文(命中前 20 字 + 命中词 + 命中后 40 字)
  • 点任意命中 → 切到那个会话并关弹窗

全文搜索是字面量匹配text.find()),不模糊不忽略大小写。中文按字节匹配。

7. 导出

7.1 格式

格式 文件名 内容
Markdown <session-id>-<sanitized-title>.md 标题 + 元信息 + 每条消息带 emoji 角色(👤/🤖/🔔/📸/⚙️+ 时间戳 + 文本 + 图片相对路径
JSON <session-id>-<sanitized-title>.json pretty-printed JSONsession: {meta}messages: [...] 数组

7.2 导出位置

浏览器默认下载目录ExportPayload.suggested_filename 字段前端会直接用。

7.3 提醒中心能不能导出?

。但因为是伪会话,导出内容主要是各种 reminder 类型的消息。

8. 常见疑问

Q: 我能同时开几个聊天窗口吗? A: 不能。聊天面板是桌宠窗口的一部分(右侧栏),不是独立窗口。多个对话 = 多个会话(用下拉切换)。

Q: 对话历史存在哪? A: 见 08-数据存储与备份.md

Q: 我清空了 localStorage 会不会丢? A: 不会。localStorage 没用,所有会话数据在磁盘。

Q: 我能编辑 / 删除某条已发送消息吗? A: 不能。当前版本没有编辑或单条删除功能(只能删除整个会话)。


下一步:06-健康提醒.md