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

29 KiB

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 先新增,后替换

不要一上来删除旧文件。

推荐流程:

新增 workspace 模块
  ↓
实现只读能力
  ↓
实现写入计划和确认
  ↓
接入 PetWindow
  ↓
确认能编译运行
  ↓
替换旧 FileOperationManager
  ↓
最后删除旧文件操作模块

2.2 PetWindow 不承载业务逻辑

PetWindow 只负责 UI 展示和用户交互,不应该直接处理复杂文件逻辑。

新的业务逻辑应放到:

src/workspace/
src/assistant/

PetWindow 只调用控制器,例如:

m_workspaceController->handleUserMessage(message);

2.3 AI 不直接操作文件

AI 不能直接拿到文件系统权限。

正确流程是:

用户输入
  ↓
WorkspaceAgent 分析任务
  ↓
生成文件操作计划
  ↓
展示计划
  ↓
用户确认
  ↓
WorkspaceTool 执行
  ↓
返回结果

3. 功能范围

3.1 第一阶段必须实现

第一阶段目标:只读工作区分析 + 安全文件操作基础能力

必须支持:

选择工作区
显示当前工作区
扫描工作区文件树
搜索文件名
搜索文本内容
读取文本文件
分析项目结构
总结文件内容
打开文件
打开文件夹
显示文件所在位置
创建文本文件
创建文件夹
修改文本文件
复制文件
移动文件
重命名文件
删除到回收站
记录最近操作

其中:

  • 读操作可以直接执行。
  • 打开文件建议确认。
  • 创建、修改、移动、重命名、删除必须确认。
  • 删除只能移动到回收站。
  • 修改文件必须备份或使用安全写入策略。

3.2 第一阶段禁止实现

以下功能第一阶段不要做:

全盘搜索
永久删除
批量删除
批量移动
批量重命名
执行 shell 命令
运行脚本
运行 exe
自动 git commit
自动安装依赖
自动联网下载并执行文件
读取系统敏感目录
读取工作区外文件

后续如果需要运行命令,应作为第二阶段或第三阶段功能,并单独设计命令白名单和权限系统。


4. 新模块目录结构

新增目录:

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

enum class WorkspacePermissionMode
{
    ReadOnly,
    ConfirmBeforeWrite,
    Advanced
};

说明:

  • ReadOnly:只能读、搜索、分析。
  • ConfirmBeforeWrite:允许写,但每次写操作都必须确认。
  • Advanced:预留,不在第一阶段实现自动写入。

第一阶段默认使用:

WorkspacePermissionMode::ConfirmBeforeWrite

但所有写操作仍然必须确认。


5.2 WorkspaceToolRisk

enum class WorkspaceToolRisk
{
    ReadOnly,
    Low,
    Medium,
    High,
    Dangerous
};

风险等级说明:

ReadOnly:
    搜索、列目录、读取普通文本文件。

Low:
    打开文件夹、显示文件所在位置。

Medium:
    打开普通文件、创建文件、创建文件夹、复制文件。

High:
    修改文件、移动文件、重命名文件、删除到回收站。

Dangerous:
    永久删除、执行命令、运行脚本、修改系统目录。

第一阶段遇到 Dangerous 直接拒绝。


5.3 WorkspaceFileInfo

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

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;
};

注意:

  • 所有路径都必须是工作区内路径。
  • sourcePathtargetPath 必须经过 WorkspaceAccessPolicy 校验。
  • 写操作默认 requiresConfirmation = true
  • 第一阶段禁止覆盖文件,所以 allowOverwrite 默认必须是 false。

5.5 WorkspaceToolResult

struct WorkspaceToolResult
{
    bool success = false;
    QString message;
    QString errorMessage;
    QString outputText;
    QString targetPath;
    QVector<WorkspaceFileInfo> files;
};

6. WorkspaceAccessPolicy 设计

这是最重要的安全模块。

6.1 职责

WorkspaceAccessPolicy 负责:

路径标准化
判断路径是否在工作区内
阻止 ../ 跳出工作区
阻止符号链接跳出工作区
阻止系统目录
阻止危险文件类型
阻止敏感文件默认读取
限制写入行为
限制删除行为

6.2 必须实现的方法

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 路径限制

所有操作必须满足:

目标路径在 workspaceRoot 内
不能包含符号链接路径段
不能是 Windows 系统目录
不能是 Program Files
不能是 ProgramData
不能是回收站目录
不能是工作区外路径

禁止通过以下方式绕过:

../
..\ 
符号链接
快捷方式跳转
相对路径混淆
大小写混淆

6.4 危险后缀

第一阶段默认禁止写入、打开或执行以下文件:

.exe
.bat
.cmd
.ps1
.vbs
.msi
.scr
.reg
.com
.pif
.lnk

其中 .lnk 不要直接打开,因为它可能指向工作区外路径或脚本。


6.5 敏感文件

以下文件读取时必须强确认,第一阶段可以先默认拒绝:

.env
*.pem
*.key
id_rsa
id_ed25519
*.pfx
*.p12
credentials.json
secrets.json
token.json

如果文件名包含以下关键词,也视为敏感:

secret
token
password
credential
private
apikey
api_key

7. WorkspaceScanner 和 WorkspaceIndex

7.1 WorkspaceScanner

负责扫描工作区。

建议使用:

QDirIterator

扫描规则:

最大递归深度:8
最大文件数量:5000
跳过隐藏目录
跳过 build 目录
跳过 .git 目录
跳过 node_modules
跳过 dist
跳过 release_packages
跳过 .vs
跳过 .vscode 可选

建议跳过目录:

.git
.vs
.idea
build
cmake-build-debug
cmake-build-release
node_modules
dist
release
release_packages
logs

7.2 WorkspaceIndex

负责保存扫描结果。

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 抽象

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

功能:

列出工作区某个目录下的文件和文件夹。

限制:

只允许工作区内目录
最多显示 200 项
不递归或浅递归

8.3 ReadFileTool

功能:

读取文本文件。

限制:

只读文本文件
最大读取 128KB
超出部分截断
敏感文件默认拒绝或强确认
不读取二进制文件

支持后缀:

.cpp
.h
.hpp
.c
cc
py
js
ts
json
md
txt
ini
xml
yaml
yml
cmake
pro
css
html

8.4 SearchFilesTool

功能:

按文件名搜索。

限制:

只搜索当前工作区索引
最多返回 30 个结果
按相关性和最近修改时间排序

8.5 SearchTextTool

功能:

在文本文件中搜索关键词。

限制:

最多扫描 1000 个文本文件
单文件最大读取 128KB
最多返回 50 条匹配
每条匹配显示文件路径、行号、片段

8.6 OpenFileTool

功能:

用系统默认程序打开文件。

实现建议:

QDesktopServices::openUrl(QUrl::fromLocalFile(path));

限制:

只能打开工作区内文件
危险后缀拒绝
敏感文件需要确认

打开文件夹同理。


8.7 RevealInExplorer

功能:

在资源管理器中显示文件所在位置。

Windows 可使用:

explorer.exe /select,"path"

但第一阶段如果不想涉及命令,可以先打开所在文件夹。


8.8 CreateFileTool

功能:

创建文本文件。

限制:

只能在工作区内创建
目标文件不能已存在
文件名必须合法
危险后缀拒绝
写操作必须确认

建议使用 QSaveFileQFile 创建。


8.9 WriteFileTool

功能:

写入文本文件。

第一阶段建议只支持:

新建文件写入
或
修改已有文本文件,但写入前自动备份

要求:

写入前必须确认
写入前创建备份
禁止覆盖二进制文件
禁止写敏感文件
禁止写危险后缀

备份目录建议:

<workspaceRoot>/.desktoppet/backups/

备份文件名建议:

relative_path.replace("/", "__") + "." + timestamp + ".bak"

8.10 CopyFileTool

限制:

只能复制单文件
不能覆盖目标文件
源和目标都必须在工作区内
写操作必须确认

8.11 MoveFileTool

限制:

只能移动单文件
不能覆盖目标文件
源和目标都必须在工作区内
写操作必须确认

8.12 RenameFileTool

限制:

只能在同目录内重命名
不能覆盖目标文件
文件名不能包含路径分隔符
写操作必须确认

8.13 DeleteToTrashTool

功能:

移动到系统回收站。

实现建议:

QFile file(path);
file.moveToTrash();

或根据 Qt 版本使用对应的 moveToTrash 方法。

限制:

只允许工作区内文件
不做永久删除
删除文件夹需要强确认
删除敏感文件需要强确认
删除危险后缀文件需要强确认

第一阶段禁止批量删除。


9. WorkspaceAgent 设计

9.1 第一版采用半自动 Agent

第一版不要急着实现复杂 function calling。

建议采用半自动流程:

用户输入
  ↓
WorkspaceController 判断是否是工作区任务
  ↓
程序先根据关键词和工作区索引检索相关文件
  ↓
读取少量相关文件
  ↓
把文件树摘要、相关文件内容、用户问题交给模型
  ↓
模型返回分析结果或修改建议
  ↓
涉及写操作时生成 WorkspaceActionPlan
  ↓
用户确认
  ↓
执行工具

这样比完全由模型自由调用工具更容易控制。


9.2 后续可升级为工具循环

未来可以升级为:

model
  ↓
tool call
  ↓
tool result
  ↓
model
  ↓
tool call
  ↓
...

但第一版不强制做。


9.3 工作区模式系统提示词

工作区模式不要使用普通桌宠聊天提示词。

新增工作区专用提示词:

你是 QtDesktopPet 的本地工作区助手。

你只能基于用户授权的工作区文件进行分析。
你不能假设自己看过未读取的文件。
你不能要求访问工作区外路径。
你不能执行系统命令。
你不能生成危险操作指令。
涉及创建、修改、移动、重命名、删除文件时,必须先生成清晰的操作计划,等待用户确认。
涉及敏感文件、密钥、凭证时,必须提醒风险。
回答代码问题时要引用具体文件路径。
当信息不足时,说明还需要读取哪些文件。

10. WorkspaceController 设计

WorkspaceController 负责连接 UI 和工作区 Agent。

建议接口:

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 入口

在聊天系统中增加:

工作区模式

可以通过以下方式触发:

打开工作区
选择工作区
分析这个项目
搜索当前工作区

如果用户没有选择工作区,则提示选择目录。

第一版可以直接用:

QFileDialog::getExistingDirectory(...)

让用户选择工作区。


11.2 气泡显示策略

桌宠气泡只显示简短状态:

已打开工作区。
正在扫描文件。
找到了 12 个相关文件。
需要你确认修改计划。
操作已完成。

复杂结果不要全部塞进气泡。


11.3 工作区面板

建议新增:

WorkspacePanel

第一版可以晚点做,先用对话框和聊天历史展示。

最终面板建议显示:

当前工作区路径
文件树
搜索结果
读取过的文件
AI 分析结果
待确认操作计划
执行结果
最近操作历史

12. 和旧文件操作的迁移关系

当前旧入口可能是:

handleFileOperationChatMessage(...)

新方案中应改为:

handleWorkspaceMessage(...)

迁移步骤:

第一步:
    新增 workspace 模块,不改旧 fileops。

第二步:
    CMakeLists.txt 加入 workspace 新文件。

第三步:
    在 PetWindow 中新增 WorkspaceController 成员。

第四步:
    IntentRouter 中把文件相关意图改为 Workspace。

第五步:
    handleFileOperationChatMessage 内部临时转发到 WorkspaceController。

第六步:
    确认新模块可用后,删除旧 FileOperationManager 相关调用。

第七步:
    删除旧 src/fileops 旧文件并更新 CMakeLists.txt。

注意:删除旧文件前必须确认没有任何 include 或成员变量引用旧类。


13. IntentRouter 调整

当前 IntentRouter 只按关键词判断文件操作,后续应改成更宽泛的工作区意图。

建议:

enum class UserIntentType
{
    Chat,
    Reminder,
    Weather,
    Workspace,
    LaunchApp
};

工作区关键词:

文件
文件夹
目录
项目
代码
源码
工作区
分析这个项目
搜索
读取
打开文件
创建文件
修改文件
删除文件
移动文件
重命名

注意:

打开微信
打开浏览器
打开 QQ

这类应该走 LaunchApp,不要误判成 Workspace。

建议优先级:

Reminder
Weather
Workspace
LaunchApp
Chat

但如果文本中出现明确应用名,可优先 LaunchApp。


14. CMake 修改计划

新增 workspace 文件后,需要在 CMakeLists.txt 中加入:

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. 日志要求

不要记录敏感内容。

允许记录:

打开工作区路径
扫描文件数量
执行的工具名称
操作是否成功
错误摘要

禁止记录:

API Key
Authorization header
完整敏感文件内容
.env 内容
密钥文件内容
用户完整隐私文本

使用项目已有 Logger,不要使用 OutputDebugStringA


16. 错误处理

所有工具错误都必须返回 WorkspaceToolResult,不要直接弹窗。

错误示例:

路径不在当前工作区内。
目标文件已存在。
该文件类型不允许写入。
该文件可能包含敏感信息,已拒绝读取。
删除操作已取消。
无法移动到回收站。

UI 层负责展示错误。


17. 测试清单

17.1 工作区选择

测试:

选择普通项目目录
选择空目录
选择不存在目录
选择 C:/Windows,应该拒绝
选择 Program Files,应该拒绝
选择包含中文路径的目录
选择包含空格路径的目录

17.2 扫描

测试:

扫描普通 Qt 项目
扫描包含 build 目录的项目
扫描包含 .git 的项目
扫描大量文件目录
扫描中文文件名
扫描深层目录

要求:

不崩溃
不扫系统目录
不进入跳过目录
结果数量受限制

17.3 搜索文件

测试:

搜索 main
搜索 .cpp
搜索 README
搜索不存在文件
搜索中文文件名

要求:

最多返回 30 条
显示相对路径
结果可用于后续“打开第几个”

17.4 搜索文本

测试:

搜索 class
搜索 include
搜索中文关键词
搜索不存在关键词
搜索超大文件

要求:

显示路径、行号、片段
跳过二进制文件
跳过超大文件
不读取敏感文件

17.5 读取文件

测试:

读取 .cpp
读取 .md
读取 .json
读取图片,应该拒绝
读取 exe,应该拒绝
读取 .env,应该拒绝或强确认
读取工作区外文件,应该拒绝

17.6 创建文件

测试:

在工作区创建 test.txt
创建已存在文件,应该拒绝
创建非法文件名,应该拒绝
创建 .bat,应该拒绝
创建到工作区外,应该拒绝

17.7 修改文件

测试:

修改普通 txt
修改 cpp
修改已存在文件前生成备份
修改二进制文件,应该拒绝
修改敏感文件,应该拒绝

要求:

必须确认
必须备份
失败不能破坏原文件

17.8 移动和重命名

测试:

移动普通文件
移动到已存在目标,应该拒绝
重命名普通文件
重命名为非法文件名,应该拒绝
移动到工作区外,应该拒绝

17.9 删除到回收站

测试:

删除普通文件到回收站
删除文件夹到回收站
删除工作区外文件,应该拒绝
永久删除请求,应该拒绝
批量删除请求,第一阶段应该拒绝

17.10 对话上下文

测试:

用户:搜索 README
用户:打开第一个

用户:搜索 fileops
用户:读取第二个

用户:找一下包含 FileOperationManager 的文件
用户:总结这些文件的作用

要求:

系统能记住上一轮搜索结果
“第一个”“第二个”能正确解析
上下文过期后要求用户重新选择

18. 推荐开发任务拆分

任务 1:新增类型和安全策略

目标:

新增 WorkspaceTypes.h
新增 WorkspaceAccessPolicy
不接 UI
保证项目可编译

验收:

能判断路径是否在工作区内
能拒绝系统目录
能拒绝符号链接
能拒绝危险后缀

任务 2:新增扫描和索引

目标:

实现 WorkspaceScanner
实现 WorkspaceIndex
支持扫描工作区文件树

验收:

可以扫描普通项目
可以跳过 build/.git/node_modules
可以按文件名搜索

任务 3:新增只读工具

目标:

ListFilesTool
ReadFileTool
SearchFilesTool
SearchTextTool

验收:

能列目录
能读文本文件
能搜索文件名
能搜索文本内容
不读取二进制和敏感文件

任务 4:新增打开工具

目标:

OpenFileTool
OpenDirectory
RevealInExplorer

验收:

能打开普通文件
能打开文件夹
危险后缀拒绝
工作区外路径拒绝

任务 5:新增写入工具

目标:

CreateFileTool
CreateDirectoryTool
WriteFileTool
CopyFileTool
MoveFileTool
RenameFileTool
DeleteToTrashTool

验收:

所有写操作必须要求 confirmed
未确认时拒绝执行
目标已存在时拒绝覆盖
删除只进回收站
写入前备份

任务 6:新增 WorkspaceController

目标:

统一管理工作区、索引、工具、待确认计划

验收:

能 openWorkspace
能 scanWorkspace
能 handleMessage
能保存 pendingPlan
能确认执行 pendingPlan

任务 7:接入 PetWindow

目标:

PetWindow 增加 WorkspaceController
聊天消息中的工作区相关请求转发给 WorkspaceController

验收:

用户可以选择工作区
可以搜索文件
可以读取文件
写操作会弹确认
确认后执行

任务 8:替换旧 fileops

目标:

旧 handleFileOperationChatMessage 改为调用 workspace
删除旧 FileOperationManager 依赖
更新 CMake

验收:

项目无旧 FileOperationManager 引用
项目能编译
README 更新为“本地工作区助手”

19. README 更新要求

README 中文件操作部分应改为:

本地工作区助手:

- 用户选择一个工作区目录后,桌宠可以读取、搜索和分析其中的文本文件。
- 支持文件名搜索、文本搜索、文件读取、项目结构分析。
- 支持创建、修改、移动、重命名和删除到回收站,但所有写操作都需要用户确认。
- 不支持永久删除。
- 不支持执行脚本或系统命令。
- 不允许访问工作区外路径。
- 敏感文件和危险后缀会被拦截或要求强确认。

20. 最终验收标准

本轮重构完成后,至少应达到:

1. 用户可以选择一个本地项目目录作为工作区。
2. 程序可以扫描工作区并建立文件索引。
3. 用户可以通过对话搜索文件。
4. 用户可以通过对话读取和分析文本文件。
5. 用户可以要求分析项目结构。
6. 用户可以创建文本文件和文件夹。
7. 用户可以移动、重命名、删除到回收站。
8. 所有写操作必须展示计划并等待确认。
9. 所有路径必须限制在工作区内。
10. 不允许永久删除。
11. 不允许执行脚本或命令。
12. 不允许默认读取敏感文件。
13. 旧文件操作功能被新 Workspace 系统替代。
14. 项目可以正常编译。

21. 特别注意

这是一次架构升级,不是简单加几个文件函数。

不要把功能写成:

AI 说删就删
AI 说改就改
AI 说运行就运行

必须写成:

AI 提出计划
程序校验路径和风险
用户确认
程序执行白名单工具

这个边界必须守住。

最终目标是:

让 DesktopPet 具备“读工作区、理解工作区、规划修改、确认后执行”的能力,形成桌宠形态的本地工作区 Agent。