Files
Qt_DesktopPet/docs/archive/DesktopPet 本地工作区 Agent 开发文档_草案.md

1741 lines
29 KiB
Markdown

# DesktopPet 本地工作区 Agent 开发文档
## 0. 文档目标
本次开发目标不是继续维护旧版“文件操作 v1”,而是将其重构升级为一个类似 Codex / Claude Code 思路的 **本地工作区 Agent**
新的功能定位:
> 用户选择一个本地工作区目录后,桌宠可以读取、搜索、分析该目录内的文件,并在用户确认后创建、修改、移动、重命名或删除文件。
注意:
1. 不允许 AI 直接获得全盘文件权限。
2. 不允许 AI 自由执行系统命令。
3. 不允许永久删除文件。
4. 不允许绕过用户确认修改本地文件。
5. 所有写操作必须先生成计划,展示路径和风险,用户确认后才能执行。
6. 当前阶段优先实现文件级工具,不做 shell 命令执行。
------
## 1. 当前项目背景
当前项目是 QtDesktopPet,技术栈为:
- C++17
- Qt 6 Widgets
- Qt 6 Network
- Qt 6 Multimedia
- CMake
- Windows 优先
当前项目已有:
- 桌宠窗口
- 动画状态
- AI 对话
- 天气
- 提醒
- 本地应用启动
- 简单文件操作 v1
旧版文件操作 v1 只适合简单功能,例如:
- 读取文本文件
- 列出文件夹
- 复制文件
- 备份文件
- 重命名文件
新的目标不是在旧版基础上打补丁,而是设计一个独立的工作区系统。
------
## 2. 总体开发原则
### 2.1 先新增,后替换
不要一上来删除旧文件。
推荐流程:
```text
新增 workspace 模块
实现只读能力
实现写入计划和确认
接入 PetWindow
确认能编译运行
替换旧 FileOperationManager
最后删除旧文件操作模块
```
### 2.2 PetWindow 不承载业务逻辑
`PetWindow` 只负责 UI 展示和用户交互,不应该直接处理复杂文件逻辑。
新的业务逻辑应放到:
```text
src/workspace/
src/assistant/
```
`PetWindow` 只调用控制器,例如:
```cpp
m_workspaceController->handleUserMessage(message);
```
### 2.3 AI 不直接操作文件
AI 不能直接拿到文件系统权限。
正确流程是:
```text
用户输入
WorkspaceAgent 分析任务
生成文件操作计划
展示计划
用户确认
WorkspaceTool 执行
返回结果
```
------
## 3. 功能范围
## 3.1 第一阶段必须实现
第一阶段目标:**只读工作区分析 + 安全文件操作基础能力**。
必须支持:
```text
选择工作区
显示当前工作区
扫描工作区文件树
搜索文件名
搜索文本内容
读取文本文件
分析项目结构
总结文件内容
打开文件
打开文件夹
显示文件所在位置
创建文本文件
创建文件夹
修改文本文件
复制文件
移动文件
重命名文件
删除到回收站
记录最近操作
```
其中:
- 读操作可以直接执行。
- 打开文件建议确认。
- 创建、修改、移动、重命名、删除必须确认。
- 删除只能移动到回收站。
- 修改文件必须备份或使用安全写入策略。
------
## 3.2 第一阶段禁止实现
以下功能第一阶段不要做:
```text
全盘搜索
永久删除
批量删除
批量移动
批量重命名
执行 shell 命令
运行脚本
运行 exe
自动 git commit
自动安装依赖
自动联网下载并执行文件
读取系统敏感目录
读取工作区外文件
```
后续如果需要运行命令,应作为第二阶段或第三阶段功能,并单独设计命令白名单和权限系统。
------
# 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
```
旧目录 `src/fileops/` 暂时不要删除。等新模块完全接入后,再移除旧模块。
------
# 5. 核心类型设计
## 5.1 WorkspacePermissionMode
```cpp
enum class WorkspacePermissionMode
{
ReadOnly,
ConfirmBeforeWrite,
Advanced
};
```
说明:
- `ReadOnly`:只能读、搜索、分析。
- `ConfirmBeforeWrite`:允许写,但每次写操作都必须确认。
- `Advanced`:预留,不在第一阶段实现自动写入。
第一阶段默认使用:
```cpp
WorkspacePermissionMode::ConfirmBeforeWrite
```
但所有写操作仍然必须确认。
------
## 5.2 WorkspaceToolRisk
```cpp
enum class WorkspaceToolRisk
{
ReadOnly,
Low,
Medium,
High,
Dangerous
};
```
风险等级说明:
```text
ReadOnly:
搜索、列目录、读取普通文本文件。
Low:
打开文件夹、显示文件所在位置。
Medium:
打开普通文件、创建文件、创建文件夹、复制文件。
High:
修改文件、移动文件、重命名文件、删除到回收站。
Dangerous:
永久删除、执行命令、运行脚本、修改系统目录。
```
第一阶段遇到 `Dangerous` 直接拒绝。
------
## 5.3 WorkspaceFileInfo
```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;
};
```
用途:
- 文件树展示
- 文件名搜索
- 后缀过滤
- 快速判断是否可读
------
## 5.4 WorkspaceActionPlan
```cpp
enum class WorkspaceActionType
{
Unknown,
ListFiles,
SearchFiles,
SearchText,
ReadFile,
OpenFile,
OpenDirectory,
RevealInExplorer,
CreateFile,
CreateDirectory,
WriteFile,
CopyFile,
MoveFile,
RenameFile,
DeleteToTrash
};
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;
};
```
注意:
- 所有路径都必须是工作区内路径。
- `sourcePath``targetPath` 必须经过 `WorkspaceAccessPolicy` 校验。
- 写操作默认 `requiresConfirmation = true`
- 第一阶段禁止覆盖文件,所以 `allowOverwrite` 默认必须是 false。
------
## 5.5 WorkspaceToolResult
```cpp
struct WorkspaceToolResult
{
bool success = false;
QString message;
QString errorMessage;
QString outputText;
QString targetPath;
QVector<WorkspaceFileInfo> files;
};
```
------
# 6. WorkspaceAccessPolicy 设计
这是最重要的安全模块。
## 6.1 职责
`WorkspaceAccessPolicy` 负责:
```text
路径标准化
判断路径是否在工作区内
阻止 ../ 跳出工作区
阻止符号链接跳出工作区
阻止系统目录
阻止危险文件类型
阻止敏感文件默认读取
限制写入行为
限制删除行为
```
------
## 6.2 必须实现的方法
```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;
};
```
------
## 6.3 路径限制
所有操作必须满足:
```text
目标路径在 workspaceRoot 内
不能包含符号链接路径段
不能是 Windows 系统目录
不能是 Program Files
不能是 ProgramData
不能是回收站目录
不能是工作区外路径
```
禁止通过以下方式绕过:
```text
../
..\
符号链接
快捷方式跳转
相对路径混淆
大小写混淆
```
------
## 6.4 危险后缀
第一阶段默认禁止写入、打开或执行以下文件:
```text
.exe
.bat
.cmd
.ps1
.vbs
.msi
.scr
.reg
.com
.pif
.lnk
```
其中 `.lnk` 不要直接打开,因为它可能指向工作区外路径或脚本。
------
## 6.5 敏感文件
以下文件读取时必须强确认,第一阶段可以先默认拒绝:
```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 和 WorkspaceIndex
## 7.1 WorkspaceScanner
负责扫描工作区。
建议使用:
```cpp
QDirIterator
```
扫描规则:
```text
最大递归深度:8
最大文件数量:5000
跳过隐藏目录
跳过 build 目录
跳过 .git 目录
跳过 node_modules
跳过 dist
跳过 release_packages
跳过 .vs
跳过 .vscode 可选
```
建议跳过目录:
```text
.git
.vs
.idea
build
cmake-build-debug
cmake-build-release
node_modules
dist
release
release_packages
logs
```
------
## 7.2 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;
private:
QVector<WorkspaceFileInfo> m_files;
};
```
第一版不需要数据库,不需要向量索引,内存索引即可。
------
# 8. 工具系统设计
## 8.1 WorkspaceTool 抽象
```cpp
class WorkspaceTool
{
public:
virtual ~WorkspaceTool() = default;
virtual QString name() const = 0;
virtual QString displayName() const = 0;
virtual WorkspaceToolRisk risk() const = 0;
virtual WorkspaceToolResult run(const WorkspaceActionPlan &plan) = 0;
};
```
所有工具必须通过 `WorkspaceAccessPolicy` 校验路径。
------
## 8.2 ListFilesTool
功能:
```text
列出工作区某个目录下的文件和文件夹。
```
限制:
```text
只允许工作区内目录
最多显示 200 项
不递归或浅递归
```
------
## 8.3 ReadFileTool
功能:
```text
读取文本文件。
```
限制:
```text
只读文本文件
最大读取 128KB
超出部分截断
敏感文件默认拒绝或强确认
不读取二进制文件
```
支持后缀:
```text
.cpp
.h
.hpp
.c
cc
py
js
ts
json
md
txt
ini
xml
yaml
yml
cmake
pro
css
html
```
------
## 8.4 SearchFilesTool
功能:
```text
按文件名搜索。
```
限制:
```text
只搜索当前工作区索引
最多返回 30 个结果
按相关性和最近修改时间排序
```
------
## 8.5 SearchTextTool
功能:
```text
在文本文件中搜索关键词。
```
限制:
```text
最多扫描 1000 个文本文件
单文件最大读取 128KB
最多返回 50 条匹配
每条匹配显示文件路径、行号、片段
```
------
## 8.6 OpenFileTool
功能:
```text
用系统默认程序打开文件。
```
实现建议:
```cpp
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
```
限制:
```text
只能打开工作区内文件
危险后缀拒绝
敏感文件需要确认
```
打开文件夹同理。
------
## 8.7 RevealInExplorer
功能:
```text
在资源管理器中显示文件所在位置。
```
Windows 可使用:
```cpp
explorer.exe /select,"path"
```
但第一阶段如果不想涉及命令,可以先打开所在文件夹。
------
## 8.8 CreateFileTool
功能:
```text
创建文本文件。
```
限制:
```text
只能在工作区内创建
目标文件不能已存在
文件名必须合法
危险后缀拒绝
写操作必须确认
```
建议使用 `QSaveFile``QFile` 创建。
------
## 8.9 WriteFileTool
功能:
```text
写入文本文件。
```
第一阶段建议只支持:
```text
新建文件写入
修改已有文本文件,但写入前自动备份
```
要求:
```text
写入前必须确认
写入前创建备份
禁止覆盖二进制文件
禁止写敏感文件
禁止写危险后缀
```
备份目录建议:
```text
<workspaceRoot>/.desktoppet/backups/
```
备份文件名建议:
```text
relative_path.replace("/", "__") + "." + timestamp + ".bak"
```
------
## 8.10 CopyFileTool
限制:
```text
只能复制单文件
不能覆盖目标文件
源和目标都必须在工作区内
写操作必须确认
```
------
## 8.11 MoveFileTool
限制:
```text
只能移动单文件
不能覆盖目标文件
源和目标都必须在工作区内
写操作必须确认
```
------
## 8.12 RenameFileTool
限制:
```text
只能在同目录内重命名
不能覆盖目标文件
文件名不能包含路径分隔符
写操作必须确认
```
------
## 8.13 DeleteToTrashTool
功能:
```text
移动到系统回收站。
```
实现建议:
```cpp
QFile file(path);
file.moveToTrash();
```
或根据 Qt 版本使用对应的 `moveToTrash` 方法。
限制:
```text
只允许工作区内文件
不做永久删除
删除文件夹需要强确认
删除敏感文件需要强确认
删除危险后缀文件需要强确认
```
第一阶段禁止批量删除。
------
# 9. WorkspaceAgent 设计
## 9.1 第一版采用半自动 Agent
第一版不要急着实现复杂 function calling。
建议采用半自动流程:
```text
用户输入
WorkspaceController 判断是否是工作区任务
程序先根据关键词和工作区索引检索相关文件
读取少量相关文件
把文件树摘要、相关文件内容、用户问题交给模型
模型返回分析结果或修改建议
涉及写操作时生成 WorkspaceActionPlan
用户确认
执行工具
```
这样比完全由模型自由调用工具更容易控制。
------
## 9.2 后续可升级为工具循环
未来可以升级为:
```text
model
tool call
tool result
model
tool call
...
```
但第一版不强制做。
------
## 9.3 工作区模式系统提示词
工作区模式不要使用普通桌宠聊天提示词。
新增工作区专用提示词:
```text
你是 QtDesktopPet 的本地工作区助手。
你只能基于用户授权的工作区文件进行分析。
你不能假设自己看过未读取的文件。
你不能要求访问工作区外路径。
你不能执行系统命令。
你不能生成危险操作指令。
涉及创建、修改、移动、重命名、删除文件时,必须先生成清晰的操作计划,等待用户确认。
涉及敏感文件、密钥、凭证时,必须提醒风险。
回答代码问题时要引用具体文件路径。
当信息不足时,说明还需要读取哪些文件。
```
------
# 10. WorkspaceController 设计
`WorkspaceController` 负责连接 UI 和工作区 Agent。
建议接口:
```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` 后才执行。
------
# 11. UI 接入建议
## 11.1 PetWindow 入口
在聊天系统中增加:
```text
工作区模式
```
可以通过以下方式触发:
```text
打开工作区
选择工作区
分析这个项目
搜索当前工作区
```
如果用户没有选择工作区,则提示选择目录。
第一版可以直接用:
```cpp
QFileDialog::getExistingDirectory(...)
```
让用户选择工作区。
------
## 11.2 气泡显示策略
桌宠气泡只显示简短状态:
```text
已打开工作区。
正在扫描文件。
找到了 12 个相关文件。
需要你确认修改计划。
操作已完成。
```
复杂结果不要全部塞进气泡。
------
## 11.3 工作区面板
建议新增:
```text
WorkspacePanel
```
第一版可以晚点做,先用对话框和聊天历史展示。
最终面板建议显示:
```text
当前工作区路径
文件树
搜索结果
读取过的文件
AI 分析结果
待确认操作计划
执行结果
最近操作历史
```
------
# 12. 和旧文件操作的迁移关系
当前旧入口可能是:
```cpp
handleFileOperationChatMessage(...)
```
新方案中应改为:
```cpp
handleWorkspaceMessage(...)
```
迁移步骤:
```text
第一步:
新增 workspace 模块,不改旧 fileops。
第二步:
CMakeLists.txt 加入 workspace 新文件。
第三步:
在 PetWindow 中新增 WorkspaceController 成员。
第四步:
IntentRouter 中把文件相关意图改为 Workspace。
第五步:
handleFileOperationChatMessage 内部临时转发到 WorkspaceController。
第六步:
确认新模块可用后,删除旧 FileOperationManager 相关调用。
第七步:
删除旧 src/fileops 旧文件并更新 CMakeLists.txt。
```
注意:删除旧文件前必须确认没有任何 include 或成员变量引用旧类。
------
# 13. IntentRouter 调整
当前 `IntentRouter` 只按关键词判断文件操作,后续应改成更宽泛的工作区意图。
建议:
```cpp
enum class UserIntentType
{
Chat,
Reminder,
Weather,
Workspace,
LaunchApp
};
```
工作区关键词:
```text
文件
文件夹
目录
项目
代码
源码
工作区
分析这个项目
搜索
读取
打开文件
创建文件
修改文件
删除文件
移动文件
重命名
```
注意:
```text
打开微信
打开浏览器
打开 QQ
```
这类应该走 `LaunchApp`,不要误判成 Workspace。
建议优先级:
```text
Reminder
Weather
Workspace
LaunchApp
Chat
```
但如果文本中出现明确应用名,可优先 LaunchApp。
------
# 14. CMake 修改计划
新增 workspace 文件后,需要在 `CMakeLists.txt` 中加入:
```text
src/workspace/WorkspaceTypes.h
src/workspace/WorkspaceSession.h
src/workspace/WorkspaceSession.cpp
src/workspace/WorkspaceIndex.h
src/workspace/WorkspaceIndex.cpp
src/workspace/WorkspaceScanner.h
src/workspace/WorkspaceScanner.cpp
src/workspace/WorkspaceAccessPolicy.h
src/workspace/WorkspaceAccessPolicy.cpp
src/workspace/WorkspaceTool.h
src/workspace/WorkspaceToolRegistry.h
src/workspace/WorkspaceToolRegistry.cpp
src/workspace/WorkspaceAgent.h
src/workspace/WorkspaceAgent.cpp
src/workspace/WorkspaceController.h
src/workspace/WorkspaceController.cpp
src/workspace/WorkspaceHistory.h
src/workspace/WorkspaceHistory.cpp
src/workspace/tools/ListFilesTool.h
src/workspace/tools/ListFilesTool.cpp
src/workspace/tools/ReadFileTool.h
src/workspace/tools/ReadFileTool.cpp
src/workspace/tools/SearchFilesTool.h
src/workspace/tools/SearchFilesTool.cpp
src/workspace/tools/SearchTextTool.h
src/workspace/tools/SearchTextTool.cpp
src/workspace/tools/OpenFileTool.h
src/workspace/tools/OpenFileTool.cpp
src/workspace/tools/CreateFileTool.h
src/workspace/tools/CreateFileTool.cpp
src/workspace/tools/CreateDirectoryTool.h
src/workspace/tools/CreateDirectoryTool.cpp
src/workspace/tools/WriteFileTool.h
src/workspace/tools/WriteFileTool.cpp
src/workspace/tools/CopyFileTool.h
src/workspace/tools/CopyFileTool.cpp
src/workspace/tools/MoveFileTool.h
src/workspace/tools/MoveFileTool.cpp
src/workspace/tools/RenameFileTool.h
src/workspace/tools/RenameFileTool.cpp
src/workspace/tools/DeleteToTrashTool.h
src/workspace/tools/DeleteToTrashTool.cpp
```
注意:
当前项目 `CMAKE_AUTOMOC` 是关闭的。如果新增类不使用 `Q_OBJECT`,可以继续保持现状。如果新增 QWidget 并需要 signals / slots,则需要重新考虑 `CMAKE_AUTOMOC`
第一阶段建议 workspace 业务类都不要使用 `Q_OBJECT`,避免牵连构建配置。
------
# 15. 日志要求
不要记录敏感内容。
允许记录:
```text
打开工作区路径
扫描文件数量
执行的工具名称
操作是否成功
错误摘要
```
禁止记录:
```text
API Key
Authorization header
完整敏感文件内容
.env 内容
密钥文件内容
用户完整隐私文本
```
使用项目已有 Logger,不要使用 `OutputDebugStringA`
------
# 16. 错误处理
所有工具错误都必须返回 `WorkspaceToolResult`,不要直接弹窗。
错误示例:
```text
路径不在当前工作区内。
目标文件已存在。
该文件类型不允许写入。
该文件可能包含敏感信息,已拒绝读取。
删除操作已取消。
无法移动到回收站。
```
UI 层负责展示错误。
------
# 17. 测试清单
## 17.1 工作区选择
测试:
```text
选择普通项目目录
选择空目录
选择不存在目录
选择 C:/Windows,应该拒绝
选择 Program Files,应该拒绝
选择包含中文路径的目录
选择包含空格路径的目录
```
------
## 17.2 扫描
测试:
```text
扫描普通 Qt 项目
扫描包含 build 目录的项目
扫描包含 .git 的项目
扫描大量文件目录
扫描中文文件名
扫描深层目录
```
要求:
```text
不崩溃
不扫系统目录
不进入跳过目录
结果数量受限制
```
------
## 17.3 搜索文件
测试:
```text
搜索 main
搜索 .cpp
搜索 README
搜索不存在文件
搜索中文文件名
```
要求:
```text
最多返回 30 条
显示相对路径
结果可用于后续“打开第几个”
```
------
## 17.4 搜索文本
测试:
```text
搜索 class
搜索 include
搜索中文关键词
搜索不存在关键词
搜索超大文件
```
要求:
```text
显示路径、行号、片段
跳过二进制文件
跳过超大文件
不读取敏感文件
```
------
## 17.5 读取文件
测试:
```text
读取 .cpp
读取 .md
读取 .json
读取图片,应该拒绝
读取 exe,应该拒绝
读取 .env,应该拒绝或强确认
读取工作区外文件,应该拒绝
```
------
## 17.6 创建文件
测试:
```text
在工作区创建 test.txt
创建已存在文件,应该拒绝
创建非法文件名,应该拒绝
创建 .bat,应该拒绝
创建到工作区外,应该拒绝
```
------
## 17.7 修改文件
测试:
```text
修改普通 txt
修改 cpp
修改已存在文件前生成备份
修改二进制文件,应该拒绝
修改敏感文件,应该拒绝
```
要求:
```text
必须确认
必须备份
失败不能破坏原文件
```
------
## 17.8 移动和重命名
测试:
```text
移动普通文件
移动到已存在目标,应该拒绝
重命名普通文件
重命名为非法文件名,应该拒绝
移动到工作区外,应该拒绝
```
------
## 17.9 删除到回收站
测试:
```text
删除普通文件到回收站
删除文件夹到回收站
删除工作区外文件,应该拒绝
永久删除请求,应该拒绝
批量删除请求,第一阶段应该拒绝
```
------
## 17.10 对话上下文
测试:
```text
用户:搜索 README
用户:打开第一个
用户:搜索 fileops
用户:读取第二个
用户:找一下包含 FileOperationManager 的文件
用户:总结这些文件的作用
```
要求:
```text
系统能记住上一轮搜索结果
“第一个”“第二个”能正确解析
上下文过期后要求用户重新选择
```
------
# 18. 推荐开发任务拆分
## 任务 1:新增类型和安全策略
目标:
```text
新增 WorkspaceTypes.h
新增 WorkspaceAccessPolicy
不接 UI
保证项目可编译
```
验收:
```text
能判断路径是否在工作区内
能拒绝系统目录
能拒绝符号链接
能拒绝危险后缀
```
------
## 任务 2:新增扫描和索引
目标:
```text
实现 WorkspaceScanner
实现 WorkspaceIndex
支持扫描工作区文件树
```
验收:
```text
可以扫描普通项目
可以跳过 build/.git/node_modules
可以按文件名搜索
```
------
## 任务 3:新增只读工具
目标:
```text
ListFilesTool
ReadFileTool
SearchFilesTool
SearchTextTool
```
验收:
```text
能列目录
能读文本文件
能搜索文件名
能搜索文本内容
不读取二进制和敏感文件
```
------
## 任务 4:新增打开工具
目标:
```text
OpenFileTool
OpenDirectory
RevealInExplorer
```
验收:
```text
能打开普通文件
能打开文件夹
危险后缀拒绝
工作区外路径拒绝
```
------
## 任务 5:新增写入工具
目标:
```text
CreateFileTool
CreateDirectoryTool
WriteFileTool
CopyFileTool
MoveFileTool
RenameFileTool
DeleteToTrashTool
```
验收:
```text
所有写操作必须要求 confirmed
未确认时拒绝执行
目标已存在时拒绝覆盖
删除只进回收站
写入前备份
```
------
## 任务 6:新增 WorkspaceController
目标:
```text
统一管理工作区、索引、工具、待确认计划
```
验收:
```text
能 openWorkspace
能 scanWorkspace
能 handleMessage
能保存 pendingPlan
能确认执行 pendingPlan
```
------
## 任务 7:接入 PetWindow
目标:
```text
PetWindow 增加 WorkspaceController
聊天消息中的工作区相关请求转发给 WorkspaceController
```
验收:
```text
用户可以选择工作区
可以搜索文件
可以读取文件
写操作会弹确认
确认后执行
```
------
## 任务 8:替换旧 fileops
目标:
```text
旧 handleFileOperationChatMessage 改为调用 workspace
删除旧 FileOperationManager 依赖
更新 CMake
```
验收:
```text
项目无旧 FileOperationManager 引用
项目能编译
README 更新为“本地工作区助手”
```
------
# 19. README 更新要求
README 中文件操作部分应改为:
```text
本地工作区助手:
- 用户选择一个工作区目录后,桌宠可以读取、搜索和分析其中的文本文件。
- 支持文件名搜索、文本搜索、文件读取、项目结构分析。
- 支持创建、修改、移动、重命名和删除到回收站,但所有写操作都需要用户确认。
- 不支持永久删除。
- 不支持执行脚本或系统命令。
- 不允许访问工作区外路径。
- 敏感文件和危险后缀会被拦截或要求强确认。
```
------
# 20. 最终验收标准
本轮重构完成后,至少应达到:
```text
1. 用户可以选择一个本地项目目录作为工作区。
2. 程序可以扫描工作区并建立文件索引。
3. 用户可以通过对话搜索文件。
4. 用户可以通过对话读取和分析文本文件。
5. 用户可以要求分析项目结构。
6. 用户可以创建文本文件和文件夹。
7. 用户可以移动、重命名、删除到回收站。
8. 所有写操作必须展示计划并等待确认。
9. 所有路径必须限制在工作区内。
10. 不允许永久删除。
11. 不允许执行脚本或命令。
12. 不允许默认读取敏感文件。
13. 旧文件操作功能被新 Workspace 系统替代。
14. 项目可以正常编译。
```
------
# 21. 特别注意
这是一次架构升级,不是简单加几个文件函数。
不要把功能写成:
```text
AI 说删就删
AI 说改就改
AI 说运行就运行
```
必须写成:
```text
AI 提出计划
程序校验路径和风险
用户确认
程序执行白名单工具
```
这个边界必须守住。
最终目标是:
> 让 DesktopPet 具备“读工作区、理解工作区、规划修改、确认后执行”的能力,形成桌宠形态的本地工作区 Agent。