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

21 KiB

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. 新目录结构

建议新增:

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. 核心类型

enum class WorkspacePermissionMode
{
    ReadOnly,
    ConfirmBeforeWrite,
    Advanced
};

第一阶段默认 ConfirmBeforeWrite,但所有写操作仍必须确认。Advanced 只预留,不启用自动写入。

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

风险定义:

  • ReadOnly:列目录、搜索、读取普通文本文件。
  • Low:打开文件夹、显示文件所在位置。
  • Medium:打开普通文件、创建文件、创建文件夹、复制文件。
  • High:修改文件、移动文件、重命名文件、删除到回收站。
  • Dangerous:永久删除、执行命令、运行脚本、修改系统目录。

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

struct WorkspaceFileInfo
{
    QString relativePath;
    QString absolutePath;
    QString fileName;
    QString suffix;
    qint64 sizeBytes = 0;
    QDateTime lastModified;
    bool isDirectory = false;
    bool isTextFile = false;
    bool isHidden = false;
};
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;
};
struct WorkspaceToolResult
{
    bool success = false;
    QString message;
    QString errorMessage;
    QString outputText;
    QString targetPath;
    QVector<WorkspaceFileInfo> files;
};

6. 安全策略

WorkspaceAccessPolicy 是最重要的模块,所有工具必须经过它校验。

职责:

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

建议接口:

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

禁止危险后缀:

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

敏感文件默认拒绝:

.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 第一版使用 QDir + 手动目录栈扫描工作区,后续如需取消、进度回调或更细粒度过滤,再考虑替换为 QDirIterator 或异步扫描。

默认限制:

  • 最大递归深度:8。
  • 最大文件数量:5000。
  • 跳过隐藏目录。
  • 跳过常见产物目录。

跳过目录:

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

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

8. 工具清单

8.1 只读工具

ListFilesTool

  • 列出工作区内目录。
  • 最多显示 200 项。
  • 不递归或浅递归。

ReadFileTool

  • 只读文本文件。
  • 最大读取 128KB。
  • 超出截断。
  • 敏感文件默认拒绝。
  • 不读二进制文件。

支持后缀:

.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

  • 修改已有文本文件前自动备份。
  • 禁止覆盖二进制文件。
  • 禁止写敏感文件。
  • 禁止写危险后缀。
  • 必须确认。

备份目录:

<workspaceRoot>/.desktoppet/backups/

备份命名:

relative_path.replace("/", "__") + "." + yyyyMMdd-HHmmss + ".bak"

CopyFileTool

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

MoveFileTool

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

RenameFileTool

  • 只允许同目录重命名。
  • 文件名不能包含路径分隔符。
  • 不覆盖。
  • 必须确认。

DeleteToTrashTool

  • 只移动到系统回收站。
  • 不永久删除。
  • 单文件删除第一阶段可支持。
  • 文件夹删除需要强确认。
  • 批量删除第一阶段拒绝。

9. WorkspaceAgent

第一版采用半自动 Agent,不做复杂工具循环。

推荐流程:

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

工作区专用系统提示词:

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

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

后续可升级为工具循环,但第一版不做。

10. WorkspaceController

建议接口:

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

聊天入口支持:

打开工作区
选择工作区
当前工作区
扫描工作区
分析这个项目
搜索当前工作区
读取 main.cpp
打开第一个

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

气泡只显示短状态:

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

复杂结果不全部塞进气泡,当前通过独立 Agent 窗口展示。

当前独立 Agent 窗口可显示:

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

12. 意图分发

后续建议新增:

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、测试文档。

删除旧文件前必须执行:

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
  • 修改前生成备份。
  • 修改二进制文件应拒绝。
  • 修改敏感文件应拒绝。

要求:

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

移动和重命名

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

删除到回收站

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

对话上下文

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

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

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

要求:

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

16. 静态推演要求

每完成一个阶段,需要记录:

  • 入口路径。
  • 业务模块调用链。
  • 路径校验点。
  • 用户确认点。
  • 失败回滚策略。
  • 不支持能力的拒绝话术。
  • 对提醒、天气、联网模式、应用启动的回归影响。

17. 最终验收标准

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

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