Files
Qt_DesktopPet/docs/archive/DesktopPet_本地工作区Agent_施工计划_已终止.md
T

872 lines
21 KiB
Markdown

# DesktopPet 本地工作区 Agent 施工计划
> 归档说明:该路线已于 2026-07-16 从 QtDesktopPet 当前产品方向中移除,本文仅保留历史设计,不再作为施工依据。
## 1. 定位
本地工作区 Agent 是下一阶段核心功能。它不是继续维护旧版“文件操作 v1”,而是新增一个独立的工作区系统:
> 用户选择一个本地工作区目录后,桌宠可以读取、搜索、分析该目录内的文件,并在用户确认后创建、修改、复制、移动、重命名或删除到回收站。
第一阶段优先实现文件级工具,不做 Shell 命令执行,不做脚本执行,不做自动安装依赖。
## 2. 总原则
- 不允许 AI 直接获得全盘文件权限。
- 不允许 AI 自由执行系统命令。
- 不允许永久删除文件。
- 不允许绕过用户确认修改本地文件。
- 不允许默认读取敏感文件。
- 所有写操作必须先生成计划,展示路径、动作和风险,用户确认后才能执行。
- 所有文件路径必须限制在用户选择的工作区内。
- `PetWindow` 只负责 UI 入口、展示和确认,不承载复杂业务逻辑。
- 新模块先新增、后替换旧 `src/fileops/`
## 3. 分期目标
当前执行状态:
- v1a.1/v1b/v1b.5 已落地到 `src/workspace/``src/ui/WorkspaceAgentWindow.*`
- 当前不持久化工作区路径,不执行写操作,不替换旧 `src/fileops/`
- v1b 已支持打开工作区内普通文件、打开文件夹、显示文件所在位置。
- v1b.5 已提供独立 Agent 工作区窗口、右键/托盘入口和默认 `Alt+A` 呼出快捷键;窗口包含左侧结果导航、中间任务对话、右侧详情/上下文和 v1c 预留变更区。
### v1a:只读工作区
目标:
- 选择工作区。
- 显示当前工作区。
- 扫描工作区文件树。
- 搜索文件名。
- 搜索文本内容。
- 读取文本文件。
- 分析项目结构。
- 总结文件内容。
验收:
- 工作区外路径被拒绝。
- 系统目录被拒绝。
- `.git/build/node_modules/dist/release_packages` 等目录被跳过。
- 敏感文件默认拒绝读取。
- 二进制文件拒绝读取。
### v1b:打开和定位
状态:已落地。
目标:
- 打开工作区内普通文件。
- 打开工作区内文件夹。
- 显示文件所在位置。
验收:
- 危险后缀拒绝打开。
- `.lnk` 不直接打开。
- 工作区外路径拒绝。
- 打开文件必须二次确认,打开文件夹作为低风险操作直接执行。
### v1c:低风险写入
进入 v1c 前已完成:
- `创建 test.txt / 新建文件 / 写入 README / 修改 main.cpp` 明确拒绝,不再误进入旧 fileops 读取文件流程。
- 独立 Agent 窗口可以分区展示上一轮结果、文本命中、上下文、选中项详情和最近读取文件。
- 窗口支持对选中结果执行读取、打开和显示位置。
- 窗口可通过桌宠右键菜单、托盘菜单和可配置全局快捷键呼出。
目标:
- 创建文本文件。
- 创建文件夹。
- 复制单个文件。
- 同目录重命名文件。
验收:
- 所有写操作必须确认。
- 目标文件或目录已存在时拒绝覆盖。
- 文件名非法时拒绝。
- 危险后缀拒绝创建或写入。
### v1d:高风险写入
目标:
- 修改已有文本文件。
- 移动单个文件。
- 删除文件到回收站。
- 删除文件夹到回收站。
验收:
- 修改前必须备份。
- 移动和删除必须强确认。
- 删除只进入回收站。
- 批量删除第一阶段拒绝。
- 失败时不能破坏原文件。
### v1e:替换旧文件操作
目标:
- `FileOperation` 意图迁移为 `Workspace`
- `PetWindow::handleFileOperationChatMessage()` 过渡为调用 `WorkspaceController`
- 新模块覆盖旧能力后删除旧 `src/fileops/`
验收:
-`FileOperationManager` 有效引用。
- CMake 不再登记旧 fileops 文件。
- README 和测试文档改为“本地工作区 Agent”。
## 4. 新目录结构
建议新增:
```text
src/workspace/
├── WorkspaceTypes.h
├── WorkspaceSession.h
├── WorkspaceSession.cpp
├── WorkspaceIndex.h
├── WorkspaceIndex.cpp
├── WorkspaceScanner.h
├── WorkspaceScanner.cpp
├── WorkspaceAccessPolicy.h
├── WorkspaceAccessPolicy.cpp
├── WorkspaceTool.h
├── WorkspaceToolRegistry.h
├── WorkspaceToolRegistry.cpp
├── WorkspaceAgent.h
├── WorkspaceAgent.cpp
├── WorkspaceController.h
├── WorkspaceController.cpp
├── WorkspaceHistory.h
├── WorkspaceHistory.cpp
└── tools/
├── ListFilesTool.h
├── ListFilesTool.cpp
├── ReadFileTool.h
├── ReadFileTool.cpp
├── SearchFilesTool.h
├── SearchFilesTool.cpp
├── SearchTextTool.h
├── SearchTextTool.cpp
├── OpenFileTool.h
├── OpenFileTool.cpp
├── CreateFileTool.h
├── CreateFileTool.cpp
├── CreateDirectoryTool.h
├── CreateDirectoryTool.cpp
├── WriteFileTool.h
├── WriteFileTool.cpp
├── CopyFileTool.h
├── CopyFileTool.cpp
├── MoveFileTool.h
├── MoveFileTool.cpp
├── RenameFileTool.h
├── RenameFileTool.cpp
├── DeleteToTrashTool.h
└── DeleteToTrashTool.cpp
```
第一阶段继续保持 `CMAKE_AUTOMOC OFF`,新增业务类不使用 `Q_OBJECT`
## 5. 核心类型
```cpp
enum class WorkspacePermissionMode
{
ReadOnly,
ConfirmBeforeWrite,
Advanced
};
```
第一阶段默认 `ConfirmBeforeWrite`,但所有写操作仍必须确认。`Advanced` 只预留,不启用自动写入。
```cpp
enum class WorkspaceToolRisk
{
ReadOnly,
Low,
Medium,
High,
Dangerous
};
```
风险定义:
- `ReadOnly`:列目录、搜索、读取普通文本文件。
- `Low`:打开文件夹、显示文件所在位置。
- `Medium`:打开普通文件、创建文件、创建文件夹、复制文件。
- `High`:修改文件、移动文件、重命名文件、删除到回收站。
- `Dangerous`:永久删除、执行命令、运行脚本、修改系统目录。
第一阶段遇到 `Dangerous` 直接拒绝。
```cpp
struct WorkspaceFileInfo
{
QString relativePath;
QString absolutePath;
QString fileName;
QString suffix;
qint64 sizeBytes = 0;
QDateTime lastModified;
bool isDirectory = false;
bool isTextFile = false;
bool isHidden = false;
};
```
```cpp
enum class WorkspaceActionType
{
Unknown,
ListFiles,
SearchFiles,
SearchText,
ReadFile,
OpenFile,
OpenDirectory,
RevealInExplorer,
CreateFile,
CreateDirectory,
WriteFile,
CopyFile,
MoveFile,
RenameFile,
DeleteToTrash
};
```
```cpp
struct WorkspaceActionPlan
{
QString id;
WorkspaceActionType type = WorkspaceActionType::Unknown;
WorkspaceToolRisk risk = WorkspaceToolRisk::ReadOnly;
QString title;
QString description;
QString sourcePath;
QString targetPath;
QString relativeSourcePath;
QString relativeTargetPath;
QString content;
QString searchKeyword;
QStringList warnings;
bool requiresConfirmation = false;
bool allowOverwrite = false;
bool confirmed = false;
};
```
```cpp
struct WorkspaceToolResult
{
bool success = false;
QString message;
QString errorMessage;
QString outputText;
QString targetPath;
QVector<WorkspaceFileInfo> files;
};
```
## 6. 安全策略
`WorkspaceAccessPolicy` 是最重要的模块,所有工具必须经过它校验。
职责:
- 路径标准化。
- 判断路径是否在工作区内。
- 阻止 `../` 跳出工作区。
- 阻止符号链接跳出工作区。
- 阻止系统目录。
- 阻止危险文件类型。
- 阻止敏感文件默认读取。
- 限制写入行为。
- 限制删除行为。
建议接口:
```cpp
class WorkspaceAccessPolicy
{
public:
explicit WorkspaceAccessPolicy(const QString &workspaceRoot);
QString workspaceRoot() const;
QString normalizePath(const QString &path) const;
QString toAbsolutePath(const QString &relativeOrAbsolutePath) const;
QString toRelativePath(const QString &absolutePath) const;
bool isInsideWorkspace(const QString &path, QString *errorMessage = nullptr) const;
bool hasSymlinkSegment(const QString &path, QString *errorMessage = nullptr) const;
bool isSystemPath(const QString &path) const;
bool isDangerousSuffix(const QString &path) const;
bool isSensitiveFile(const QString &path) const;
bool isSupportedTextFile(const QString &path) const;
bool canReadFile(const QString &path, QString *errorMessage = nullptr) const;
bool canReadDirectory(const QString &path, QString *errorMessage = nullptr) const;
bool canCreateFile(const QString &path, QString *errorMessage = nullptr) const;
bool canCreateDirectory(const QString &path, QString *errorMessage = nullptr) const;
bool canWriteFile(const QString &path, QString *errorMessage = nullptr) const;
bool canMoveFile(const QString &sourcePath, const QString &targetPath, QString *errorMessage = nullptr) const;
bool canDeleteToTrash(const QString &path, QString *errorMessage = nullptr) const;
};
```
禁止危险后缀:
```text
.exe .bat .cmd .ps1 .vbs .msi .scr .reg .com .pif .lnk
```
敏感文件默认拒绝:
```text
.env
*.pem
*.key
id_rsa
id_ed25519
*.pfx
*.p12
credentials.json
secrets.json
token.json
```
文件名包含以下关键词也视为敏感:
```text
secret
token
password
credential
private
apikey
api_key
```
## 7. 扫描和索引
`WorkspaceScanner` 第一版使用 `QDir` + 手动目录栈扫描工作区,后续如需取消、进度回调或更细粒度过滤,再考虑替换为 `QDirIterator` 或异步扫描。
默认限制:
- 最大递归深度:8。
- 最大文件数量:5000。
- 跳过隐藏目录。
- 跳过常见产物目录。
跳过目录:
```text
.git
.vs
.idea
build
cmake-build-debug
cmake-build-release
node_modules
dist
release
release_packages
logs
```
`WorkspaceIndex` 第一版只做内存索引:
```cpp
class WorkspaceIndex
{
public:
void clear();
void setFiles(const QVector<WorkspaceFileInfo> &files);
QVector<WorkspaceFileInfo> allFiles() const;
QVector<WorkspaceFileInfo> findByName(const QString &keyword, int maxResults) const;
QVector<WorkspaceFileInfo> findBySuffix(const QStringList &suffixes, int maxResults) const;
QVector<WorkspaceFileInfo> recentFiles(int maxResults) const;
};
```
## 8. 工具清单
### 8.1 只读工具
`ListFilesTool`
- 列出工作区内目录。
- 最多显示 200 项。
- 不递归或浅递归。
`ReadFileTool`
- 只读文本文件。
- 最大读取 128KB。
- 超出截断。
- 敏感文件默认拒绝。
- 不读二进制文件。
支持后缀:
```text
.cpp .h .hpp .c .cc .py .js .ts .json .md .txt .ini .xml .yaml .yml .cmake .pro .css .html
```
`SearchFilesTool`
- 只搜索当前工作区索引。
- 最多返回 30 个结果。
- 按相关性和最近修改时间排序。
`SearchTextTool`
- 最多扫描 1000 个文本文件。
- 单文件最大读取 128KB。
- 最多返回 50 条匹配。
- 每条显示文件路径、行号、片段。
### 8.2 打开工具
`OpenFileTool`
- 用系统默认程序打开文件。
- 只能打开工作区内普通文件。
- 危险后缀拒绝。
- 敏感文件需要确认或第一版拒绝。
`OpenDirectoryTool`
- 打开工作区内目录。
- 工作区外路径拒绝。
`RevealInExplorerTool`
- 第一版可以先打开所在文件夹。
- 如果后续使用 `explorer.exe /select`,必须固定程序路径和参数,不接受聊天文本命令。
### 8.3 写入工具
`CreateFileTool`
- 只能在工作区内创建。
- 目标不能已存在。
- 文件名必须合法。
- 危险后缀拒绝。
- 必须确认。
`CreateDirectoryTool`
- 只能在工作区内创建。
- 目标不能已存在。
- 必须确认。
`WriteFileTool`
- 修改已有文本文件前自动备份。
- 禁止覆盖二进制文件。
- 禁止写敏感文件。
- 禁止写危险后缀。
- 必须确认。
备份目录:
```text
<workspaceRoot>/.desktoppet/backups/
```
备份命名:
```text
relative_path.replace("/", "__") + "." + yyyyMMdd-HHmmss + ".bak"
```
`CopyFileTool`
- 只复制单文件。
- 源和目标都必须在工作区内。
- 不覆盖。
- 必须确认。
`MoveFileTool`
- 只移动单文件。
- 源和目标都必须在工作区内。
- 不覆盖。
- 必须确认。
`RenameFileTool`
- 只允许同目录重命名。
- 文件名不能包含路径分隔符。
- 不覆盖。
- 必须确认。
`DeleteToTrashTool`
- 只移动到系统回收站。
- 不永久删除。
- 单文件删除第一阶段可支持。
- 文件夹删除需要强确认。
- 批量删除第一阶段拒绝。
## 9. WorkspaceAgent
第一版采用半自动 Agent,不做复杂工具循环。
推荐流程:
```text
用户输入
WorkspaceController 判断工作区任务
程序根据关键词和索引检索相关文件
读取少量相关文件
把文件树摘要、相关文件内容、用户问题交给模型
模型返回分析结果或修改建议
涉及写操作时生成 WorkspaceActionPlan
用户确认
执行工具
```
工作区专用系统提示词:
```text
你是 QtDesktopPet 的本地工作区助手。
你只能基于用户授权的工作区文件进行分析。
你不能假设自己看过未读取的文件。
你不能要求访问工作区外路径。
你不能执行系统命令。
你不能生成危险操作指令。
涉及创建、修改、移动、重命名、删除文件时,必须先生成清晰的操作计划,等待用户确认。
涉及敏感文件、密钥、凭证时,必须提醒风险。
回答代码问题时要引用具体文件路径。
当信息不足时,说明还需要读取哪些文件。
```
后续可升级为工具循环,但第一版不做。
## 10. WorkspaceController
建议接口:
```cpp
class WorkspaceController
{
public:
explicit WorkspaceController();
bool hasWorkspace() const;
QString workspaceRoot() const;
bool openWorkspace(const QString &rootPath, QString *errorMessage = nullptr);
void closeWorkspace();
WorkspaceToolResult scanWorkspace();
WorkspaceToolResult handleMessage(const QString &message);
bool hasPendingPlan() const;
WorkspaceActionPlan pendingPlan() const;
WorkspaceToolResult confirmPendingPlan();
void cancelPendingPlan();
private:
WorkspaceSession m_session;
WorkspaceAgent m_agent;
std::optional<WorkspaceActionPlan> m_pendingPlan;
};
```
原则:
- `handleMessage()` 不直接执行高风险写操作。
- 需要确认时保存到 `m_pendingPlan`
- UI 调用 `confirmPendingPlan()` 后才执行。
- 所有错误通过 `WorkspaceToolResult` 返回,不在工具层弹窗。
## 11. UI 接入
聊天入口支持:
```text
打开工作区
选择工作区
当前工作区
扫描工作区
分析这个项目
搜索当前工作区
读取 main.cpp
打开第一个
```
如果没有选择工作区,提示用户选择目录。
气泡只显示短状态:
```text
已打开工作区。
正在扫描文件。
找到了 12 个相关文件。
需要你确认修改计划。
操作已完成。
```
复杂结果不全部塞进气泡,当前通过独立 Agent 窗口展示。
当前独立 Agent 窗口可显示:
- 当前工作区路径。
- 文件树。
- 搜索结果。
- 已读取文件。
- AI 分析结果。
- 待确认操作计划。
- 执行结果。
- 最近操作历史。
## 12. 意图分发
后续建议新增:
```cpp
enum class UserIntentType
{
Chat,
Reminder,
Weather,
Workspace,
FileOperation,
LaunchApp
};
```
意图原则:
- `Reminder` 保持最高优先级。
- 明确天气问答走 `Weather`
- 明确工作区、代码、项目分析走 `Workspace`
- 当前阶段,未明确“工作区/项目/代码”且没有工作区文件名特征的普通文件读写请求仍可走旧 `FileOperation`
- 明确应用名启动走 `LaunchApp`
- 其余走 `Chat` 或输入框联网模式。
不能用宽关键词简单吞掉所有请求:
- “打开微信”应走 `LaunchApp`
- “打开文件夹”这种泛请求不走 `Workspace`;“打开 docs / 打开这个项目里的 docs”走 `Workspace`
- “搜索 Qt 最新版本”不应走工作区搜索。
- “搜索这个项目里的 main”应走工作区搜索。
## 13. 迁移步骤
1. 新增 `src/workspace/`,不改旧 `src/fileops/`
2. CMake 登记 workspace 新文件。
3. `PetWindow` 增加 `WorkspaceController` 成员。
4. 新增工作区打开、扫描、搜索、读取入口。
5. v1b 支持打开和定位;写操作计划和确认框从后续阶段开始。
6. 新模块覆盖旧文件操作能力后,`handleFileOperationChatMessage()` 转发到 `WorkspaceController`
7. 确认无旧引用后删除 `src/fileops/`
8. 更新 CMake、README、测试文档。
删除旧文件前必须执行:
```text
rg "FileOperationManager|FileSandbox|FileBackupManager|src/fileops|FileOperation"
```
确认没有有效代码引用后再删。
## 14. 日志要求
允许记录:
- 打开工作区路径。
- 扫描文件数量。
- 执行的工具名称。
- 操作是否成功。
- 错误摘要。
禁止记录:
- API Key。
- Authorization Header。
- 完整敏感文件内容。
- `.env` 内容。
- 密钥文件内容。
- 用户完整隐私文本。
使用项目已有 `Logger`,不要新增零散调试输出。
## 15. 测试清单
### 工作区选择
- 选择普通项目目录。
- 选择空目录。
- 选择不存在目录。
- 选择 `C:/Windows`,应拒绝。
- 选择 `Program Files`,应拒绝。
- 选择中文路径。
- 选择包含空格的路径。
### 扫描
- 扫描普通 Qt 项目。
- 扫描包含 build 目录的项目。
- 扫描包含 `.git` 的项目。
- 扫描大量文件目录。
- 扫描中文文件名。
- 扫描深层目录。
要求:
- 不崩溃。
- 不扫系统目录。
- 不进入跳过目录。
- 结果数量受限制。
### 搜索文件
- 搜索 `main`
- 搜索 `.cpp`
- 搜索 `README`
- 搜索不存在文件。
- 搜索中文文件名。
要求:
- 最多返回 30 条。
- 显示相对路径。
- 结果可用于后续“打开第几个”。
### 搜索文本
- 搜索 `class`
- 搜索 `include`
- 搜索中文关键词。
- 搜索不存在关键词。
- 搜索超大文件。
要求:
- 显示路径、行号、片段。
- 跳过二进制文件。
- 跳过超大文件。
- 不读取敏感文件。
### 读取文件
- 读取 `.cpp`
- 读取 `.md`
- 读取 `.json`
- 读取图片应拒绝。
- 读取 `.exe` 应拒绝。
- 读取 `.env` 应拒绝或强确认。
- 读取工作区外文件应拒绝。
### 创建文件
- 在工作区创建 `test.txt`
- 创建已存在文件应拒绝。
- 创建非法文件名应拒绝。
- 创建 `.bat` 应拒绝。
- 创建到工作区外应拒绝。
### 修改文件
- 修改普通 `.txt`
- 修改 `.cpp`
- 修改前生成备份。
- 修改二进制文件应拒绝。
- 修改敏感文件应拒绝。
要求:
- 必须确认。
- 必须备份。
- 失败不能破坏原文件。
### 移动和重命名
- 移动普通文件。
- 移动到已存在目标应拒绝。
- 重命名普通文件。
- 重命名为非法文件名应拒绝。
- 移动到工作区外应拒绝。
### 删除到回收站
- 删除普通文件到回收站。
- 删除文件夹到回收站。
- 删除工作区外文件应拒绝。
- 永久删除请求应拒绝。
- 批量删除请求第一阶段应拒绝。
### 对话上下文
```text
用户:搜索 README
用户:打开第一个
用户:搜索 fileops
用户:读取第二个
用户:找一下包含 FileOperationManager 的文件
用户:总结这些文件的作用
```
要求:
- 系统能记住上一轮搜索结果。
- “第一个”“第二个”能正确解析。
- 上下文过期后要求用户重新选择。
## 16. 静态推演要求
每完成一个阶段,需要记录:
- 入口路径。
- 业务模块调用链。
- 路径校验点。
- 用户确认点。
- 失败回滚策略。
- 不支持能力的拒绝话术。
- 对提醒、天气、联网模式、应用启动的回归影响。
## 17. 最终验收标准
本轮重构完成后至少达到:
1. 用户可以选择一个本地项目目录作为工作区。
2. 程序可以扫描工作区并建立文件索引。
3. 用户可以通过对话搜索文件。
4. 用户可以通过对话读取和分析文本文件。
5. 用户可以要求分析项目结构。
6. 用户可以创建文本文件和文件夹。
7. 用户可以移动、重命名、删除到回收站。
8. 所有写操作必须展示计划并等待确认。
9. 所有路径必须限制在工作区内。
10. 不允许永久删除。
11. 不允许执行脚本或命令。
12. 不允许默认读取敏感文件。
13. 旧文件操作功能被新 Workspace 系统替代。
14. 项目可以由用户手动构建通过。