Files
Qt_DesktopPet/docs/QtDesktopPet_后续功能规划与结构审查.md

1215 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QtDesktopPet 后续功能开发与当前结构审查文档
> 适用仓库:`https://git.emoera.com/Make/Qt_DesktopPet`
> 目的:在继续新增功能前,先收口当前结构风险,并为后续功能扩展确定统一入口和实现边界。
> 注意:本文档不是让 Codex 一次性实现所有功能,而是作为后续开发路线和代码审查依据。
---
## 1. 当前项目状态概览
根据当前 README 和仓库结构,项目已经具备较完整的桌宠应用基础:
- 透明无边框桌宠窗口
- 鼠标拖动、置顶、右键菜单
- 托盘显示、隐藏、退出
- 单实例限制
- PNG 序列帧动画播放
- `idle / talk / think / sleep / happy / drag / error` 多状态动画
- 隐藏时暂停动画,显示时恢复
- 窗口位置、置顶、缩放、性能设置保存
- 文件日志和日志轮转
- AI Provider 分组配置
- OpenAI Compatible 聊天请求
- Google Gemini 原生聊天请求
- SSE 流式输出
- AI 回复气泡
- 聊天输入框
- 对话历史面板
- 本地历史保存和历史上限
- AI 请求取消和对话清空
- 角色文件夹导入和角色切换
- 删除用户导入角色
- 本地一次性/重复提醒、提醒列表、取消提醒和到点通知
- 内置/用户提醒音效切换、导入、删除和试听
- 天气查询、默认城市、公网 IP 定位兜底和多候选提示
- 本地文件操作安全入口:读取文本、列目录、复制、备份、重命名
- 联网模式:输入框开关、OpenAI/Gemini 原生联网、DeepSeek/Custom 不支持提示
- 本地应用启动:登记应用、开始菜单 / App Paths 发现、手选 `.exe` 和二次确认
- Windows 打包脚本和 Inno Setup 安装器脚本
- Release exe 双击不弹控制台窗口
项目已经从早期 MVP 进入到“可扩展桌面应用原型”阶段,可以开始规划工具能力扩展。
但是,在正式加入定时提醒、天气、本地文件操作、联网模式之前,建议先做一轮结构收口。
---
## 2. 当前需要优先审查或优化的地方
### 2.1 审查角色切换是否保存后立即生效
当前已经支持角色导入和角色切换。经当前测试确认:
```text
设置页选择新角色
保存设置
当前桌宠窗口是否立即重新加载新角色包
```
结论:保存后会立即切换,不依赖重启。
当前代码路径:
```text
PetWindow::openSettingsDialog()
applyAppConfig(dialog.appConfig())
PetWindow::applyAppConfig() 比较旧 characterId 与新 characterId
characterId 变化时停止当前动画并调用 loadCharacterPackage()
loadCharacterPackage() 重新构建动画状态并从 idle 状态开始播放
```
后续不需要围绕 2.1 做修复,只需要保留为回归检查项:
```text
设置页切换角色后点击保存,桌宠应立即显示新角色
不需要关闭或重启程序
切换后动画状态应可继续正常播放
```
---
### 2.2 不要继续向 PetWindow 堆功能
目前 `PetWindow` 已经承担了过多职责,后续不能继续把所有新功能塞进去。
`PetWindow` 应该主要负责:
```text
窗口显示
拖动
菜单
子组件组织
基础 UI 信号转发
```
不建议继续负责:
```text
提醒解析
天气查询
联网模式
本地文件读写
AI 工具调度
复杂业务状态管理
```
后续应逐步拆出:
```text
ChatController
ReminderController
WeatherController
FileOperationController
ToolCommandDispatcher
```
即使暂时不大规模重构,也至少要为后续功能增加统一调度层,不要直接把新逻辑写进 `PetWindow::submitChatMessage()`
---
### 2.3 新增 IntentRouter / CommandDispatcher
后续功能包括:
```text
定时提醒
天气查询
本地文件操作
联网模式
本地应用启动
普通 AI 对话
```
这些都来自用户输入框。如果没有统一入口,逻辑会混乱。
可拆成两个模块:
```text
src/intent/
├── IntentTypes.h
├── IntentRouter.h
└── IntentRouter.cpp
src/command/
├── CommandDispatcher.h
└── CommandDispatcher.cpp
```
当前阶段已选择合并为一个轻量模块:
```text
src/assistant/
├── UserIntent.h
├── IntentRouter.h
├── IntentRouter.cpp
├── CommandDispatcher.h
└── CommandDispatcher.cpp
```
当前意图枚举:
```cpp
enum class UserIntentType
{
Chat,
Reminder,
Weather,
FileOperation,
LaunchApp
};
```
建议入口流程:
```text
用户输入
IntentRouter 判断意图
CommandDispatcher 分发
ReminderManager / WeatherManager / FileOperationManager / WebChatManager / AppLaunchManager / ConversationManager
```
第一版意图识别不需要复杂,规则优先即可。
---
### 2.4 意图优先级建议
多个意图可能同时出现,需要固定优先级。
推荐:
```text
Reminder > FileOperation > Weather > LaunchApp > Chat/WebChat
```
原因:
```text
“明天早上提醒我看天气”
虽然包含“天气”,但本质是提醒。
“把天气截图保存到桌面”
可能是文件操作,而不是单纯天气查询。
“搜索一下明天天气”
新版不再作为独立搜索工具处理;如果已有 WeatherTool,应优先走天气工具,否则按普通聊天或输入框联网开关进入 Chat/WebChat。
```
---
### 2.5 检查 CMAKE_AUTOMOC 设置
如果后续新增的 Manager 使用 `QObject``signals``slots`,建议开启:
```cmake
set(CMAKE_AUTOMOC ON)
```
如果继续保持 `CMAKE_AUTOMOC OFF`,则后续模块应避免 `Q_OBJECT`,全部使用普通 C++ 回调或现有信号体系。
建议明确选择一种:
```text
方案 A:开启 AUTOMOC,后续工具模块正常使用 QObject 信号槽
方案 B:保持 OFF,后续模块不得引入 Q_OBJECT
```
当前阶段选择方案 B:继续保持 `CMAKE_AUTOMOC OFF`,新增意图分发模块使用普通 C++ 类和同步返回值,不引入 `Q_OBJECT`
后续如果 Reminder / Weather / WebChat 等模块需要大量跨对象异步信号,再单独评估是否切换到方案 A。
---
### 2.6 README 与实际功能保持同步
当前 README 已经比较完整,但后续每实现一个功能,应同步更新:
```text
当前状态
配置说明
隐私说明
日志说明
用户数据目录
发布包包含内容
```
尤其是以下功能需要额外说明:
```text
提醒数据保存位置
天气 API 请求说明
IP 定位隐私说明
本地文件操作权限说明
联网模式来源和隐私说明
```
---
### 2.7 继续保持角色导入安全策略
当前角色导入已经有较多安全边界,比如:
```text
只导入本地文件夹
验证失败不复制
角色 id 安全字符限制
内置角色不能被覆盖
只允许删除用户导入角色
状态路径安全检查
```
后续本地文件操作模块也应该沿用这种风格:
```text
路径必须安全
不允许任意系统目录
危险操作必须确认
修改前备份
删除必须二次确认
```
---
## 3. 后续功能总路线
建议不要一次做完所有功能,按以下顺序推进:
```text
阶段 0:结构收口
阶段 1:定时提醒
阶段 2:天气查询
阶段 3:本地文件操作
阶段 4:联网模式
阶段 5:语音对话 / 更复杂 Agent 能力
```
当前结构收口和定时提醒已经进入实现阶段。下一步最推荐继续做:
```text
1. 天气查询
2. 本地文件操作安全边界
3. 联网模式
```
---
# 4. 阶段 0:结构收口任务
## 4.1 目标
在正式加新功能之前,先让用户输入有统一分发入口,避免所有功能混进聊天逻辑。
## 4.2 当前新增文件
```text
src/assistant/UserIntent.h
src/assistant/IntentRouter.h
src/assistant/IntentRouter.cpp
src/assistant/CommandDispatcher.h
src/assistant/CommandDispatcher.cpp
```
## 4.3 IntentRouter 职责
```text
判断用户输入属于什么类型:
- 普通聊天
- 定时提醒
- 天气查询
- 本地文件操作
- 联网模式
```
第一版可以使用规则判断,不依赖 AI。
## 4.4 CommandDispatcher 职责
```text
接收用户输入
调用 IntentRouter
根据意图分发到不同 Manager
普通聊天才交给现有 ConversationManager / LLMProvider
```
## 4.5 PetWindow 改造要求
`PetWindow` 只负责把用户输入交给 `CommandDispatcher`,不直接判断业务逻辑。
示例流程:
```text
PetWindow::submitChatMessage()
CommandDispatcher::dispatch(userText)
根据返回信号更新气泡、状态机、历史
```
不要继续在 `PetWindow` 中直接写提醒、天气、搜索或文件逻辑。
---
# 5. 阶段 1:定时提醒功能
## 5.1 功能定位
实现本地一次性和基础重复提醒功能。
用户可以输入:
```text
晚上8点提醒我提交作业
明天9点提醒我开会
10分钟后提醒我喝水
半小时后提醒我休息
2小时后提醒我看消息
```
桌宠创建本地提醒,到点后气泡提示或托盘提示。
当前实现状态:
```text
已新增 src/reminder/ 模块
已支持一次性提醒解析、JSON 持久化、启动后加载、到点触发和状态标记
已支持聊天创建 / 查询 / 取消提醒
已支持设置页按状态查看提醒、取消 pending 提醒、编辑 pending 提醒、清理 20 天前已触发/已取消历史
已支持 reminder_default / reminder_soft 内置音效
已支持用户 wav 音效导入、删除、切换和试听
已限制用户音效删除路径,只允许删除用户音效目录内的安全 sound id
提醒触发时使用当前设置页选择的全局音效,ReminderItem.soundId 仅保留为历史兼容字段
已接入 Qt Multimedia / QSoundEffect 播放提醒音效
已预留 NotificationDispatcher,当前 Windows 仍由托盘通知承接
已支持每天 / 每周 / 每月重复提醒
已支持提醒触发后的“知道了”和“5分钟后再提醒”
已支持提醒数据原子保存
已支持多提醒可见队列,避免同时触发时互相覆盖
已支持 60 秒兜底扫描,覆盖睡眠唤醒、系统时间变化和长间隔 timer 延迟场景
通知后端不可用时会记录日志,不补气泡
```
## 5.2 第一版范围
要做:
```text
一次性提醒
每天 / 每周 / 每月重复提醒
本地保存
程序重启后提醒不丢
到点后触发气泡和托盘通知
提醒触发后标记 triggered
支持查询当前提醒列表
支持取消提醒
```
暂不做:
```text
工作日提醒
自定义间隔重复提醒
农历提醒
复杂日历
跨设备同步
联网日程
语音提醒
```
## 5.3 建议目录
```text
src/reminder/
├── ReminderTypes.h
├── ReminderCommandHandler.h
├── ReminderCommandHandler.cpp
├── ReminderParser.h
├── ReminderParser.cpp
├── ReminderManager.h
├── ReminderManager.cpp
├── ReminderStore.h
├── ReminderStore.cpp
├── ReminderSoundRepository.h
├── ReminderSoundRepository.cpp
├── ReminderSoundPlayer.h
└── ReminderSoundPlayer.cpp
```
## 5.4 数据结构建议
```cpp
struct ReminderItem
{
QString id;
QString title;
QString originalText;
QDateTime remindAt;
ReminderStatus status = ReminderStatus::Pending;
QDateTime createdAt;
QDateTime finishedAt; // triggered/canceled 记录的完成时间;旧数据缺失时按 remindAt 兼容
QString soundId; // 历史兼容字段,触发时不再读取
ReminderRecurrence recurrence;
};
struct ReminderRecurrence
{
ReminderRecurrenceType type = ReminderRecurrenceType::None; // None / Daily / Weekly / Monthly
int interval = 1;
int weekday = 0; // 1-7,仅 weekly 使用
int monthDay = 0; // 1-31,仅 monthly 使用
int hour = -1;
int minute = -1;
QDateTime lastTriggeredAt;
};
```
## 5.5 存储文件
保存到:
```text
QStandardPaths::AppConfigLocation/reminders.json
```
示例:
```json
{
"reminders": [
{
"id": "reminder_001",
"title": "提交作业",
"originalText": "晚上8点提醒我提交作业",
"remindAt": "2026-06-01T20:00:00",
"status": "pending",
"createdAt": "2026-06-01T15:20:00",
"soundId": "",
"recurrence": {
"type": "none",
"interval": 1,
"weekday": 0,
"monthDay": 0,
"hour": -1,
"minute": -1
}
}
]
}
```
旧版 `reminders.json` 没有 `recurrence` 字段时按一次性提醒读取,继续兼容;没有 `finishedAt` 字段时,已触发/已取消历史按 `remindAt` 作为保留时间兜底。
提醒数据保存使用原子写入。写入失败时创建 / 取消会回滚内存变更,到点触发会保留 pending 并等待下次重试,不播放音效、不通知、不气泡。
历史记录默认只保留最近 20 天。自动清理和设置页“清理20天前历史”只删除超过 20 天的 triggered/canceled 记录,不删除 pending。
配置损坏时备份:
```text
reminders.broken.yyyyMMdd-HHmmss.json
```
## 5.6 时间解析策略
第一版规则解析优先,不依赖 AI。
支持:
```text
8点
8点30
20:30
晚上8点
下午3点
明天9点
明天上午10点
后天9点
今天下午3点
6月3日9点
6/3 09:00
下周一上午10点
10分钟后
半小时后
一个半小时后
一小时后
1小时后
两小时后
2小时后
每天9点
每天提醒我9点打卡
每日晚上8点
每周一上午10点
每周一提醒我上午10点周会
每星期五下午3点
每月3号9点
每月3号提醒我9点交报告
```
如果规则解析失败,后续可以再接 AI 解析。当前重复提醒只支持每天 / 每周 / 每月。包含“工作日 / 每两天 / 每月最后一天 / 每季度 / 农历 / 自定义复杂规则”等语义时,返回明确暂不支持提示,不创建一次性提醒。
## 5.7 AI 辅助解析的设计边界
可以后续做 AI 辅助解析,但 AI 不允许直接写文件。
正确流程:
```text
AI 解析用户意图
返回结构化 JSON
程序校验
ReminderManager 创建提醒
ReminderStore 保存
```
禁止:
```text
AI 直接读写 reminders.json
AI 直接修改本地文件
```
AI 解析时必须由程序提供当前本地时间:
```text
currentLocalTime
timeZone
weekday
userText
```
因为 API 模型无法可靠知道用户本机时间。
## 5.8 到点触发
建议行为:
```text
桌宠可见:播放当前全局音效,显示 ChatBubble + 切 happy,无 happy 时回退 talk,不发 Windows 通知
桌宠隐藏:播放当前全局音效,触发 Windows 托盘通知,不在下次显示时补气泡
AI 正在请求或流式回复:按隐藏场景处理,播放当前全局音效并发 Windows 通知,不显示气泡,不进入补气泡队列
Windows 托盘通知后端不可用:记录日志,不补气泡,不进入可见队列
用户拖动中:播放当前全局音效,不打断 drag,拖动结束后显示气泡,不发 Windows 通知
多条提醒同时触发:可见状态下进入队列逐条展示,避免后一条覆盖前一条
桌宠可见触发时显示轻量操作区:“知道了”关闭当前提示,“5分钟后再提醒”固定创建新的 5 分钟一次性提醒
重复提醒触发后先推进下一次 remindAt 并保存;稍后提醒不会影响原重复规则
```
提醒文案:
```text
到时间啦:提交作业
```
## 5.9 给 Codex 的阶段任务
```text
1. 新增 reminder 模块
2. 实现一次性 ReminderItem
3. 实现 ReminderStore JSON 读写
4. 实现 ReminderParser 规则解析
5. 实现 ReminderManager 定时检查
6. 到点后发信号给 UI 层
7. UI 层显示气泡和托盘通知
8. 不要把提醒逻辑写进 PetWindow
9. 不要让 AI 直接写本地文件
```
---
# 6. 阶段 2:天气查询功能
当前天气查询 v1 已进入实现阶段:
- 已新增独立 `src/weather/` 模块
- 已支持 Open-Meteo 市级城市优先的基础地理编码和基础天气查询
- 已支持设置页默认城市
- 已支持默认城市为空时通过公网 IP 定位兜底
- 已支持当前/今天、明天、后天和未来 1-3 天模板回复
- 已支持读取前 5 个地理编码候选;多候选时仍查首项,并在回复中提示同名城市风险和其他候选
- 已支持设置页测试默认城市;测试只展示匹配结果,不自动保存配置
- 已通过 `CommandDispatcher` 将 Weather 意图接入聊天入口
- 已保持 `PetWindow` 只负责 UI 展示,不承载天气解析或网络逻辑
v1 明确暂不支持:
- AI 润色天气回复
- 空气质量
- 天气预警
- 天气提醒联动
- 多天气源切换
- 小时级精细降雨判断
- 穿衣指数
默认城市为空且启用公网 IP 定位时,会请求 ipapi.co 判断城市;回复必须说明“根据公网 IP 判断城市”。设置页默认城市和公网 IP 定位都属于非用户明确城市来源,回复必须说明来源。
当前 v1 推荐填写市级城市名;区县、乡镇、街道不保证精确识别,可能无法匹配或被匹配到上级/同名城市。同名城市当前使用天气源返回的第一个结果,并在回复或测试结果中提示其他候选。后续优先补可交互候选选择、区县级定位和国内天气源增强。
## 6.1 功能定位
天气是独立工具能力,不放进联网模式。
正确流程:
```text
用户问天气
程序识别 Weather 意图
WeatherManager 调用天气 API
拿到结构化天气数据
AI 根据结构化数据自然语言回复
```
不要让 AI 自己搜索天气,也不要让 AI 自己拼 URL。
## 6.2 为什么不用联网模式做天气
用联网模式查询天气有几个问题:
```text
结果格式不稳定
摘要可能过期
地区解析不稳定
无法稳定提取温度、降雨、风力、湿度等字段
AI 总结容易出错
```
天气应该走天气 API。
## 6.3 第一版范围
要做:
```text
识别天气请求
支持默认城市
支持用户指定城市
支持当前天气
支持简单今天/明天查询
AI 不可用时模板兜底回复
查询中切 think
回复时切 talk
失败时切 error
```
暂不做:
```text
天气预警
空气质量详情
分钟级降水
生活指数
地图定位
GPS 定位
自动后台推送
天气提醒
多天气源自动切换
```
## 6.4 建议目录
```text
src/weather/
├── WeatherTypes.h
├── WeatherConfig.h
├── WeatherStore.h
├── WeatherStore.cpp
├── WeatherParser.h
├── WeatherParser.cpp
├── WeatherSummaryFormatter.h
├── WeatherSummaryFormatter.cpp
├── WeatherManager.h
└── WeatherManager.cpp
```
## 6.5 天气源建议
第一版推荐:
```text
Open-MeteoProvider
```
优点:
```text
不需要 API Key
全球可用
适合开源项目默认方案
```
后续再加:
```text
AmapWeatherProvider
OpenWeatherProvider
```
如果主要面向国内用户,高德天气也可以作为第二个 Provider,但需要用户配置 Web 服务 Key。
## 6.6 WeatherConfig
```cpp
struct WeatherConfig
{
bool enabled = true;
QString provider = "open-meteo";
QString defaultLocationName;
double defaultLatitude = 0.0;
double defaultLongitude = 0.0;
bool hasDefaultCoordinate = false;
bool allowIpLocation = false;
bool askBeforeIpLocation = true;
QString apiKey;
int timeoutMs = 10000;
bool useAIResponse = true;
bool showRawDataWhenAIUnavailable = true;
};
```
保存到:
```text
QStandardPaths::AppConfigLocation/weather_config.json
```
## 6.7 地点策略
优先级:
```text
用户明确输入城市
用户设置的默认城市
用户主动选择 IP 定位
追问用户城市
```
不要默认静默使用 IP 定位。
## 6.8 IP 定位原则
IP 定位可以做,但只能作为可选辅助。
原因:
```text
VPN / 代理会导致定位错误
运营商出口可能定位不准
校园网 / 公司网可能不准
用户可能不希望程序自动请求定位服务
```
建议交互:
```text
你还没有设置默认城市。
可以手动输入城市,也可以使用 IP 自动定位。
是否使用 IP 自动定位?
```
识别到城市后仍要确认:
```text
我识别到你可能在西安,要设为默认城市吗?
```
## 6.9 天气意图关键词
```text
天气
气温
温度
冷不冷
热不热
下雨
降雨
带伞
刮风
风力
湿度
空气质量
雾霾
适合出门
穿什么
外面怎么样
```
## 6.10 AI 回复上下文
当前 v1 采用模板优先,不依赖 AI 润色;本节作为 v1.1 预留方向。
程序应把结构化天气数据交给 AI
```text
用户问题:
今天西安天气怎么样?
天气数据:
城市:西安
当前天气:多云
温度:26℃
体感温度:27℃
湿度:60%
风向:东北风
风速:3级
降雨概率:20%
更新时间:2026-06-01 15:00
请根据以上数据,用简洁自然的语气回答。不要编造没有提供的数据。
```
## 6.11 AI 不可用时兜底
如果天气 API 成功但 AI 失败,则模板回复:
```text
西安当前天气:多云,26℃,湿度 60%,风力 3 级。更新时间:15:00。
```
---
# 7. 阶段 3:本地文件操作功能
## 7.1 功能定位
本地文件操作是高风险功能,必须后置,不能早于提醒和天气。
当前本地文件操作 v1 已进入实现阶段:
- 已新增独立 `src/fileops/` 模块
- 已通过 `CommandDispatcher` 将 FileOperation 意图接入聊天入口
- 已支持读取用户主动选择的常见文本文件
- 已支持列出用户主动选择的文件夹
- 已支持复制文件、创建备份、重命名文件
- 写操作会展示操作计划并二次确认
- 聊天文本不会直接变成本地路径,所有路径必须由用户通过文件选择框选择
- 已拒绝删除、覆盖、移动、执行脚本、运行命令和系统目录访问
- 已拒绝符号链接路径,降低路径逃逸风险
v1 明确暂不支持:
- zip 打包
- 删除文件
- 覆盖文件
- 移动文件
- 执行脚本或命令
- 修改源码
目标是让桌宠能辅助用户处理本地文件,例如:
```text
帮我整理这个文件夹里的图片
帮我把这些日志文件打包
帮我读取这个 txt 总结一下
帮我把这个 md 转成备份副本
```
## 7.2 基本原则
AI 不能直接操作本地文件。
正确流程:
```text
AI 理解用户意图
生成操作计划
程序校验路径和权限
展示计划给用户确认
程序执行
执行结果反馈给 AI / 用户
```
禁止:
```text
AI 直接读写任意文件
AI 直接删除文件
AI 直接覆盖文件
AI 自己决定访问系统目录
```
## 7.3 安全边界
必须实现:
```text
工作目录白名单
路径标准化
禁止符号链接逃逸
禁止访问系统目录
禁止访问用户隐私目录,除非用户显式选择
修改前备份
删除前二次确认
批量操作前显示操作计划
```
## 7.4 建议目录
```text
src/fileops/
├── FileOperationTypes.h
├── FileOperationManager.h
├── FileOperationManager.cpp
├── FileSandbox.h
├── FileSandbox.cpp
├── FileBackupManager.h
└── FileBackupManager.cpp
```
## 7.5 第一版建议只做低风险操作
第一版可做:
```text
读取用户主动选择的文本文件
列出用户主动选择的文件夹
复制文件
创建备份
打包 zip
重命名文件,需确认
```
当前 v1 中 zip 打包延期,因为 Qt 公共 API 没有稳定内置写 zip 能力;不为此引入重依赖。后续如果要补 zip,优先选择明确许可和可维护的压缩库。
暂不做:
```text
删除文件
覆盖文件
移动大量文件
修改源码
执行脚本
运行命令
访问系统目录
```
## 7.6 修改/删除必须二次确认
即使用户说“删掉它”,也必须确认:
```text
即将删除:
D:/xxx/a.txt
D:/xxx/b.txt
此操作会移动到回收站/备份后删除。
是否继续?
```
## 7.7 应用启动独立模块
当前已新增独立 `src/launcher/` 模块,不放进 `src/fileops/`
```text
src/launcher/
├── AppLaunchTypes.h
├── AppLaunchStore.h
├── AppLaunchStore.cpp
├── AppDiscovery.h
├── AppDiscovery.cpp
├── AppLaunchManager.h
└── AppLaunchManager.cpp
```
应用启动支持:
```text
打开 Codex
启动酷狗音乐
帮我打开 VSCode
```
解析和发现顺序:
```text
用户在设置页登记的应用别名
Windows 开始菜单快捷方式
Windows App Paths 注册表
未知应用时由用户手动选择 .exe
```
启动安全边界:
```text
启动前始终二次确认
只允许 .exe 或开始菜单 .lnk
不执行 .bat / .cmd / .ps1 / .vbs / .js / .msi
不执行聊天文本里的命令
不拼接聊天文本参数
不以管理员权限启动
```
配置保存到:
```text
QStandardPaths::AppConfigLocation/launcher_config.json
```
损坏时备份为:
```text
launcher_config.broken.yyyyMMdd-HHmmss.json
```
---
# 8. 阶段 4:联网模式
联网能力已从旧“搜索引擎聚合器”重做为 Web 端 AI 对话式联网模式。
当前已落地:
- 已删除旧 `src/search/` 模块,不再维护 Google/百度/360/搜狗页面解析、SearXNG 旧配置、多源聚合和旧 `search_config.json` 兼容。
- 已新增独立 `src/web/` 模块:`WebConfig``WebStore``WebCapabilityDetector``WebChatManager` 和 Web citation 类型。
- 输入框新增“联网”开关;开关开启后,普通聊天进入 WebChat 流程。
- 支持 OpenAI 官方 Provider 的 Responses API Web Search。
- 支持 Google Gemini Provider 的 Google Search grounding。
- DeepSeek 官方 API 当前不提供托管联网搜索工具,显示“不支持原生联网”。
- Custom / 第三方 OpenAI-Compatible 默认无法确认联网能力,不发送未知联网参数,不做旧搜索页抓取。
- 设置页改为“联网模式”:显示当前能力状态、开关记忆、默认开关、Provider 模式、超时、来源展示和测试联网模式。
-`search_config.json` 已废弃;新版使用 `web_config.json`,损坏时备份为 `web_config.broken.yyyyMMdd-HHmmss.json`
边界:
- 不再默认每次联网,模型可判断稳定常识无需联网。
- 不做搜索结果页 HTML 解析,避免登录、帮助、反馈、验证码页面污染答案。
- 不实现 Tavily / Brave / Bing Search API、自建搜索后端、网页全文抓取或长期缓存。
- 天气仍是独立工具能力,不放进联网模式。
后续可选:
- 更多 AI Provider 原生联网适配。
- 结构化搜索 API 或自建联网后端,用于不支持原生联网的模型。
- 更强的引用 UI、证据片段摘录和来源可点击展示。
# 9. 建议最终开发顺序
## 9.1 第一步:收口架构
```text
1. 角色切换保存后立即生效已确认,后续作为回归项保留
2. 新增 IntentRouter
3. 新增 CommandDispatcher
4. 调整 PetWindow 输入流程
5. 当前阶段保持 CMAKE_AUTOMOC OFF,新增模块不使用 Q_OBJECT
```
## 9.2 第二步:定时提醒
```text
当前已落地一次性提醒、每天/每周/每月重复提醒、提醒列表、取消提醒、编辑 pending 提醒、20 天历史保留、到点气泡/托盘通知、稍后提醒和提醒音效管理。
后续可继续补工作日/自定义间隔、跨平台通知实现和更复杂的提醒管理能力。
```
## 9.3 第三步:天气查询
```text
当前已落地天气 v1WeatherTypes、WeatherConfig / WeatherStore、WeatherParser、WeatherManager、模板回复、设置页默认城市、公网 IP 定位兜底和 Weather 意图接入。
当前已落地天气 v1.2 / v1.3:多候选城市提示和设置页默认城市测试。后续可继续补可交互候选选择、区县级定位、国内天气源增强、AI 润色、空气质量、天气预警、多天气源切换、小时级降雨判断和天气提醒联动。
```
## 9.4 第四步:本地文件操作
```text
当前已落地 FileSandbox、FileOperationTypes、FileOperationManager、FileBackupManager 和用户确认 UI。
v1 支持读取文本、列出文件夹、复制、备份、重命名。
v1 不支持 zip、删除、覆盖、移动、脚本/命令执行和系统目录访问。
```
## 9.5 第五步:联网模式
```text
当前已落地 WebConfig、WebStore、WebCapabilityDetector、WebChatManager 和输入框联网开关。新版支持 OpenAI/Gemini 原生联网;DeepSeek/Custom 明确提示不支持或无法确认;旧搜索聚合与 SearXNG 旧配置已废弃。
```
## 9.6 第六步:应用启动
```text
当前已落地 AppLaunchStore、AppDiscovery、AppLaunchManager 和设置页应用登记。
v1 支持已登记应用、开始菜单快捷方式、App Paths 注册表和用户确认手选 .exe。
v1 不支持脚本、聊天参数、命令执行、管理员权限和跨平台应用发现。
```
---
# 10. 给 Codex 的总提示
下面这段可以直接作为后续任务总说明:
```text
当前不要急着直接实现提醒、天气、文件操作或联网模式。
请先审查当前 QtDesktopPet 项目结构,并完成以下准备工作:
1. 角色切换在设置保存后已确认立即生效,后续只需保留回归检查。
2. 新增 IntentRouter / CommandDispatcher,使用户输入先经过统一意图分发。
3. 意图类型包括 Chat、Reminder、Weather、FileOperation、LaunchApp;联网模式由输入框开关决定,不再是独立 Search 意图。
4. 意图优先级为 Reminder > FileOperation > Weather > LaunchApp > Chat/WebChat。
5. 普通聊天继续走现有 AI 对话流程。
6. 新功能不得继续直接塞进 PetWindow。
7. 后续 Reminder、Weather、FileOperation、LaunchApp、WebChat 均应作为独立模块接入。
8. 当前阶段保持 CMAKE_AUTOMOC OFF,后续模块不要使用 Q_OBJECT;确需 Qt 信号槽时再单独评估。
9. 保持现有隐私策略:API Key、Authorization、完整用户消息、完整错误响应不得写入日志。
10. 保持现有文件安全策略:路径校验、危险操作确认、修改前备份。
```
---
# 11. 当前结论
项目已经可以进入“工具能力扩展阶段”,但不建议直接开写业务功能。
建议先做:
```text
结构收口 → IntentRouter / CommandDispatcher → 定时提醒 → 天气 → 本地文件操作 → 联网模式
```
其中:
```text
定时提醒:已作为第一个工具能力落地
天气:建议第二个落地
本地文件操作:风险较高,第三个落地
联网模式:通用 AI 对话增强,最后落地
```