Files
Qt_DesktopPet/docs/archive/QtDesktopPet_本地工作区Agent_独立窗口化施工文档_已终止.md
T

21 KiB
Raw Blame History

QtDesktopPet 本地工作区 Agent 独立窗口化施工文档

归档说明:该路线已于 2026-07-16 从 QtDesktopPet 当前产品方向中移除,本文仅保留历史设计,不再作为施工依据。

0. 本次施工目标

当前项目已经有“本地工作区 Agent”面板雏形,能够显示:

  • 当前工作区路径
  • 索引项数量
  • 最近扫描时间
  • 上一轮搜索结果
  • 选中文件详情
  • 文本命中
  • 最近读取
  • 读取 / 打开 / 定位 等操作按钮

但当前形态更接近“文件搜索面板”,还不是类似 Codex / Claude Code 的工作区 Agent 面板。

本次施工目标:

将本地工作区 Agent 从桌宠窗口中独立出来,做成一个单独的非模态主窗口,并改造成“左侧工作区导航 + 中间 Agent 对话 + 右侧上下文 / 文件详情 / 变更确认 + 底部任务输入框”的 Codex 风格面板。


1. 产品定位

1.1 桌宠窗口职责

桌宠本体只负责:

1. 桌宠动画显示
2. 气泡提示
3. 托盘控制
4. 打开设置窗口
5. 打开本地工作区 Agent 窗口
6. 显示任务状态,例如“正在分析”“等待确认”“修改完成”

桌宠窗口不应该承载:

1. 文件树
2. 搜索结果列表
3. 多轮 Agent 对话
4. 文件内容预览
5. Diff 预览
6. 修改计划确认
7. 复杂任务日志

1.2 本地工作区 Agent 窗口职责

本地工作区 Agent 独立窗口负责:

1. 选择 / 切换工作区
2. 扫描并索引工作区
3. 显示文件树 / 搜索结果 / 上下文文件
4. 支持用户输入任务
5. 显示 Agent 对话过程
6. 显示工具调用过程
7. 显示已读取文件
8. 显示待确认操作
9. 显示 Diff 或修改计划
10. 执行确认后的文件操作

2. 为什么必须做成独立窗口

2.1 当前问题

如果本地工作区 Agent 和桌宠共用一个窗口,会导致:

1. PetWindow 职责继续膨胀
2. 桌宠动画逻辑和工作区 UI 强耦合
3. UI 尺寸冲突,桌宠本体不适合承载复杂面板
4. 复杂任务状态难以展示
5. 后续 Diff、文件树、搜索、日志、对话区很难布局
6. 用户无法像使用 IDE / Codex 一样长时间停留在 Agent 面板中

2.2 独立窗口优势

独立窗口可以获得:

1. 更像 Codex / Claude Code 的工作流
2. 可最大化 / 最小化 / 单独移动
3. 不影响桌宠动画
4. 可以保存窗口大小和位置
5. 可以长期展示复杂任务
6. 可以后续加入 Diff 面板、文件树、任务日志
7. PetWindow 只作为入口,整体架构更干净

3. 总体架构

新的调用关系应为:

PetWindow
  ↓
openWorkspaceAgentWindow()
  ↓
WorkspaceAgentWindow
  ↓
WorkspacePanel
  ↓
WorkspaceController
  ↓
WorkspaceAgent
  ↓
WorkspaceToolRegistry
  ↓
Workspace Tools

其中:

PetWindow:
    只负责打开窗口和接收状态提示。

WorkspaceAgentWindow:
    独立顶层窗口,负责窗口行为。

WorkspacePanel:
    主 UI 容器,负责布局。

WorkspaceController:
    UI 和业务逻辑之间的桥梁。

WorkspaceAgent:
    处理用户任务、文件分析、工具调用计划。

WorkspaceToolRegistry:
    管理文件工具。

Workspace Tools:
    读取、搜索、打开、创建、移动、删除到回收站等具体工具。

4. 新增 UI 目录结构

建议新增:

src/ui/workspace/
├── WorkspaceAgentWindow.h
├── WorkspaceAgentWindow.cpp
├── WorkspacePanel.h
├── WorkspacePanel.cpp
├── WorkspaceTopBar.h
├── WorkspaceTopBar.cpp
├── WorkspaceSidebar.h
├── WorkspaceSidebar.cpp
├── WorkspaceChatView.h
├── WorkspaceChatView.cpp
├── WorkspaceInspector.h
├── WorkspaceInspector.cpp
├── WorkspaceInputBar.h
├── WorkspaceInputBar.cpp
├── WorkspacePlanReviewWidget.h
├── WorkspacePlanReviewWidget.cpp
├── WorkspaceDiffView.h
└── WorkspaceDiffView.cpp

第一阶段可以先实现:

WorkspaceAgentWindow
WorkspacePanel
WorkspaceTopBar
WorkspaceSidebar
WorkspaceChatView
WorkspaceInspector
WorkspaceInputBar

WorkspacePlanReviewWidgetWorkspaceDiffView 可以先放空壳,后续接写操作确认。


5. WorkspaceAgentWindow 设计

5.1 类型选择

建议使用:

class WorkspaceAgentWindow : public QWidget

或者:

class WorkspaceAgentWindow : public QMainWindow

推荐第一版使用 QWidget,因为当前项目 UI 结构大多基于 QWidget,迁移成本低。

窗口必须是独立顶层窗口,不要作为 PetWindow 的子控件。

创建时:

m_workspaceAgentWindow = std::make_unique<WorkspaceAgentWindow>();
m_workspaceAgentWindow->show();
m_workspaceAgentWindow->raise();
m_workspaceAgentWindow->activateWindow();

不要传 this 作为 parent。


5.2 窗口行为

建议窗口属性:

setWindowTitle(QStringLiteral("本地工作区 Agent"));
resize(1180, 760);
setMinimumSize(960, 600);
setWindowFlags(Qt::Window);

不要使用:

Qt::Tool

原因:

Qt::Tool 更像附属工具窗,可能不显示在任务栏,不适合 Codex 风格主面板。


5.3 关闭行为

建议关闭窗口时只隐藏,不销毁。

实现思路:

void WorkspaceAgentWindow::closeEvent(QCloseEvent *event)
{
    event->ignore();
    hide();
}

这样:

1. 工作区上下文不会丢失
2. 搜索结果不会丢失
3. Agent 对话不会丢失
4. 再次打开速度更快

退出程序时由主程序统一析构。


6. PetWindow 接入方案

6.1 新增成员

PetWindow.h 中增加前置声明:

class WorkspaceAgentWindow;

新增成员:

std::unique_ptr<WorkspaceAgentWindow> m_workspaceAgentWindow;

6.2 新增方法

PetWindow 中新增:

void openWorkspaceAgentWindow();

实现逻辑:

void PetWindow::openWorkspaceAgentWindow()
{
    if (!m_workspaceAgentWindow)
    {
        m_workspaceAgentWindow = std::make_unique<WorkspaceAgentWindow>();
    }

    m_workspaceAgentWindow->show();
    m_workspaceAgentWindow->raise();
    m_workspaceAgentWindow->activateWindow();
}

注意:

WorkspaceAgentWindow 不要设置 PetWindow 为 parent。

6.3 菜单入口

在桌宠右键菜单增加:

打开本地工作区 Agent

点击后调用:

openWorkspaceAgentWindow();

后续也可以在聊天中识别:

打开工作区
打开 Agent
打开本地工作区

然后调用该窗口。


7. WorkspacePanel 布局设计

7.1 总体布局

目标布局:

┌─────────────────────────────────────────────────────────────┐
│ TopBar:工作区路径 / 索引状态 / 模式 / 按钮                   │
├──────────────┬────────────────────────────┬─────────────────┤
│ Sidebar      │ ChatView                   │ Inspector       │
│ 文件树/搜索   │ Agent 对话 / 工具调用过程    │ 详情/命中/变更    │
├──────────────┴────────────────────────────┴─────────────────┤
│ InputBar:任务输入框 / 发送 / 停止 / 附加文件 / 模式切换       │
└─────────────────────────────────────────────────────────────┘

7.2 推荐 Qt 布局

使用:

QVBoxLayout *rootLayout;
QHBoxLayout *bodyLayout;

结构:

rootLayout
    ├── WorkspaceTopBar
    ├── bodyLayout
           ├── WorkspaceSidebar
           ├── WorkspaceChatView
           └── WorkspaceInspector
    └── WorkspaceInputBar

建议宽度比例:

Sidebar:    280 px
ChatView:   stretch 1
Inspector:  320 px

可以使用:

bodyLayout->setStretch(0, 0);
bodyLayout->setStretch(1, 1);
bodyLayout->setStretch(2, 0);

8. 顶部栏 WorkspaceTopBar

8.1 显示内容

顶部栏显示:

本地工作区 Agent

工作区:D:/programming/成品项目/项目/Qt_DesktopPet    [切换工作区]
索引项:389    最近扫描:2026-06-23 09:49:02    [重新索引]
模式:只读 / 确认写入    [设置]

8.2 按钮

需要以下按钮:

选择工作区
重新索引
清空上下文
停止任务
权限模式

第一版按钮可以先实现:

选择工作区
重新索引
关闭

9. 左侧栏 WorkspaceSidebar

9.1 Tab 结构

左侧栏建议使用 QTabWidget

文件
搜索
上下文

9.2 文件 Tab

显示文件树。

第一版可以先不用完整树形结构,继续使用当前已有的索引结果列表。

后续再升级为:

QTreeView + QFileSystemModel

或自定义模型。

按钮:

读取
打开
定位
加入上下文
复制路径

9.3 搜索 Tab

包含:

搜索输入框
搜索类型:文件名 / 文本内容
搜索按钮
结果列表

搜索结果点击后:

1. 更新右侧 Inspector
2. 可双击读取
3. 可加入上下文

9.4 上下文 Tab

显示 Agent 当前已经读取或参考过的文件:

已加入上下文:
- README.md
- CMakeLists.txt
- src/workspace/WorkspaceController.cpp

每项支持:

移出上下文
打开
定位
重新读取

10. 中间区 WorkspaceChatView

10.1 职责

中间区是 Agent 面板核心。

它负责显示:

1. 用户输入
2. Agent 回复
3. 工具调用
4. 工具返回结果
5. 文件读取记录
6. 搜索结果摘要
7. 修改计划
8. 错误提示

10.2 消息类型

新增消息类型:

enum class WorkspaceMessageType
{
    User,
    Assistant,
    ToolCall,
    ToolResult,
    FileRead,
    SearchResult,
    Plan,
    Diff,
    Warning,
    Error
};

消息结构:

struct WorkspaceMessage
{
    WorkspaceMessageType type = WorkspaceMessageType::Assistant;
    QString title;
    QString content;
    QStringList relatedFiles;
    QDateTime createdAt;
};

10.3 显示样式

第一版可以用:

QTextEdit

或者:

QScrollArea + QVBoxLayout + 自定义 message widget

推荐第一版用 QScrollArea + QVBoxLayout

原因:

1. 后续每种消息可以有不同样式
2. 工具调用可以做折叠
3. Diff 可以单独嵌入控件
4. 比 QTextEdit 更适合 Agent UI

11. 右侧栏 WorkspaceInspector

11.1 Tab 结构

右侧栏建议使用 QTabWidget

详情
命中
变更

11.2 详情 Tab

显示当前选中文件:

src/workspace/WorkspaceAccessPolicy.h

类型:文本文件
大小:1434 字节
修改时间:2026-06-23 04:59:27
相对路径:src/workspace/WorkspaceAccessPolicy.h

[读取] [打开] [定位] [加入上下文]

11.3 命中 Tab

显示文本搜索命中:

README.dev.md:333
搜索包含 class 的文件:搜索文本内容,显示路径、行号和片段

src/workspace/WorkspaceAccessPolicy.h:5
class WorkspaceAccessPolicy

11.4 变更 Tab

用于后续显示待确认修改:

待确认变更:

1. src/ui/workspace/WorkspacePanel.cpp
   - 调整为三栏布局

2. src/ui/workspace/WorkspaceInputBar.cpp
   - 新增任务输入栏

[查看 Diff] [确认应用] [取消]

第一版可以先显示:

暂无待确认变更

12. 底部输入栏 WorkspaceInputBar

12.1 基本控件

底部输入栏包含:

任务输入框
发送按钮
停止按钮
附加文件按钮
模式按钮

第一版可以只做:

任务输入框
发送按钮
停止按钮

输入框 placeholder

输入任务,例如:分析这个项目结构,搜索 workspace 相关代码,读取第二个文件……

12.2 快捷命令

后续支持:

/scan      重新扫描工作区
/search    搜索文件或文本
/read      读取文件
/clear     清空上下文
/mode      切换权限模式

第一版不强制实现。


13. 当前面板迁移方案

当前截图中的内容迁移如下:

13.1 当前“上一轮结果”

迁移到:

WorkspaceSidebar -> 搜索 Tab

13.2 当前“选中项”

迁移到:

WorkspaceInspector -> 详情 Tab

13.3 当前“文本命中”

迁移到:

WorkspaceInspector -> 命中 Tab

13.4 当前“最近读取”

迁移到:

WorkspaceSidebar -> 上下文 Tab

或者:

WorkspaceInspector -> 详情 Tab 下方

推荐放到左侧“上下文 Tab”。


13.5 当前底部按钮

当前按钮:

读取
打开
位置
关闭

迁移为:

详情 Tab:
    读取
    打开
    定位
    加入上下文

TopBar:
    关闭

InputBar:
    发送
    停止

14. 样式建议

当前面板深色风格可以保留。

建议统一颜色变量:

const QString BackgroundColor = "#0f172a";
const QString PanelColor = "#17233a";
const QString BorderColor = "#2b4164";
const QString PrimaryColor = "#2d5be3";
const QString TextColor = "#ffffff";
const QString MutedTextColor = "#b9c7dd";

不要在每个控件里到处写重复样式。

建议新建:

src/ui/workspace/WorkspaceStyle.h

或在 WorkspacePanel.cpp 内先集中管理。


15. WorkspaceController 对接

UI 不直接调用底层文件工具。

UI 调用:

WorkspaceController

建议接口:

class WorkspaceController
{
public:
    bool hasWorkspace() const;
    QString workspaceRoot() const;

    bool openWorkspace(const QString &rootPath, QString *errorMessage = nullptr);
    bool rescan(QString *errorMessage = nullptr);

    QVector<WorkspaceFileInfo> indexedFiles() const;
    QVector<WorkspaceFileInfo> lastSearchResults() const;
    QVector<WorkspaceTextMatch> lastTextMatches() const;
    QVector<WorkspaceFileInfo> recentlyReadFiles() const;

    WorkspaceToolResult searchFiles(const QString &keyword);
    WorkspaceToolResult searchText(const QString &keyword);
    WorkspaceToolResult readFile(const QString &relativeOrAbsolutePath);
    WorkspaceToolResult openFile(const QString &relativeOrAbsolutePath);
    WorkspaceToolResult revealFile(const QString &relativeOrAbsolutePath);

    WorkspaceToolResult handleUserTask(const QString &message);
};

第一版 handleUserTask 可以先做规则分发,不必实现完整模型工具调用。


16. Agent 对话第一版行为

第一版不要急着做完整自动 Agent。

先做规则驱动:

用户输入包含“搜索”:
    调 searchFiles 或 searchText

用户输入包含“读取 / 打开第几个 / 第二个”:
    使用上一轮搜索结果

用户输入包含“分析项目”:
    读取 README.md、CMakeLists.txt、main.cpp、src 目录结构,然后交给 AI

用户输入普通问题:
    作为普通 AI 对话,但附加当前工作区摘要

17. 确认机制

涉及写操作时,必须进入确认流程。

窗口中显示:

Agent 准备执行以下操作:

操作:移动文件
源路径:src/old/FileOperationManager.cpp
目标路径:src/workspace/old/FileOperationManager.cpp
风险:高

是否确认?

按钮:

确认执行
取消

第一版可以先只展示计划,不真正实现写操作。


18. 施工顺序

阶段 1:独立窗口

目标:

新增 WorkspaceAgentWindow
新增 WorkspacePanel
PetWindow 右键菜单可以打开独立窗口
窗口可以独立移动、最小化、最大化
关闭窗口时隐藏,不销毁

验收:

桌宠窗口和 Agent 窗口彼此独立
关闭 Agent 窗口不退出程序
再次打开保留状态

阶段 2:迁移现有面板

目标:

把当前已有的工作区路径、索引项、搜索结果、选中项、文本命中、最近读取迁移到 WorkspacePanel

验收:

新窗口中能看到当前截图已有功能
读取 / 打开 / 定位功能正常

阶段 3:三栏布局

目标:

顶部 TopBar
左侧 Sidebar
中间 ChatView
右侧 Inspector
底部 InputBar

验收:

界面从“文件检索器”变成“Agent 工作台”
中间区域为对话主区域
左侧和右侧为辅助区域

阶段 4:任务输入栏

目标:

底部可以输入任务
点击发送后添加用户消息
系统根据规则返回 Agent 消息

验收:

用户输入“搜索 workspace”
左侧显示搜索结果
中间显示工具调用过程
右侧显示选中文件详情

阶段 5:工作区选择

目标:

顶部增加“选择工作区”
使用 QFileDialog 选择目录
选择后扫描索引
更新 TopBar 状态

验收:

可以切换工作区
切换后搜索结果清空
索引数量更新
最近扫描时间更新

阶段 6Agent 对话只读分析

目标:

支持“分析这个项目”
自动读取 README.md、CMakeLists.txt、main.cpp 和 src 目录结构
调用现有 AI 对话能力返回分析结果

验收:

用户可以在面板中输入“分析这个项目”
系统能显示读取了哪些文件
AI 能给出项目结构分析

阶段 7:确认计划与变更区

目标:

右侧增加“变更”Tab
支持展示待确认操作计划

验收:

写操作不会直接执行
会先显示计划
用户确认后才执行

19. CMake 修改

新增文件后,需要加入 CMakeLists.txt

第一阶段至少加入:

src/ui/workspace/WorkspaceAgentWindow.h
src/ui/workspace/WorkspaceAgentWindow.cpp
src/ui/workspace/WorkspacePanel.h
src/ui/workspace/WorkspacePanel.cpp
src/ui/workspace/WorkspaceTopBar.h
src/ui/workspace/WorkspaceTopBar.cpp
src/ui/workspace/WorkspaceSidebar.h
src/ui/workspace/WorkspaceSidebar.cpp
src/ui/workspace/WorkspaceChatView.h
src/ui/workspace/WorkspaceChatView.cpp
src/ui/workspace/WorkspaceInspector.h
src/ui/workspace/WorkspaceInspector.cpp
src/ui/workspace/WorkspaceInputBar.h
src/ui/workspace/WorkspaceInputBar.cpp

注意:

当前项目 CMAKE_AUTOMOC 是关闭的。

所以第一版新增 UI 类尽量不要使用 Q_OBJECT

需要回调时优先使用:

std::function

例如:

void setSendCallback(std::function<void(const QString &)> callback);

20. 编码要求

20.1 大括号风格

使用 Allman 风格:

if (condition)
{
    doSomething();
}

20.2 不使用 OutputDebugStringA

不要使用:

OutputDebugStringA

日志使用项目已有 Logger,或者在必要时使用控制台输出。


20.3 不引入复杂依赖

第一版不要引入:

QML
WebView
第三方 Diff 库
SQLite
向量数据库
Everything SDK

先用 Qt Widgets 原生控件完成闭环。


21. 验收清单

完成后必须满足:

1. Agent 面板是独立顶层窗口。
2. 桌宠窗口关闭 / 隐藏不影响 Agent 面板。
3. Agent 面板关闭时默认隐藏,不丢失状态。
4. 可从桌宠右键菜单打开 Agent 面板。
5. Agent 面板有顶部工作区栏。
6. Agent 面板有左侧文件 / 搜索 / 上下文区域。
7. Agent 面板有中间对话区。
8. Agent 面板有右侧详情 / 命中 / 变更区域。
9. Agent 面板有底部任务输入栏。
10. 可以选择工作区。
11. 可以重新索引。
12. 可以搜索文件。
13. 可以读取文件。
14. 可以打开文件。
15. 可以定位文件。
16. 可以显示最近读取。
17. 可以输入任务并在中间对话区显示用户消息和 Agent 回复。
18. 不发生 PetWindow 继续膨胀的问题。
19. 项目可以正常编译。

22. 最终目标

本次改造完成后,界面形态应从:

文件检索面板

升级为:

Codex 风格的本地工作区 Agent 面板

桌宠负责陪伴和入口,Agent 窗口负责复杂任务。

最终产品体验应类似:

用户打开桌宠
  ↓
点击“本地工作区 Agent”
  ↓
弹出独立工作区窗口
  ↓
选择项目目录
  ↓
输入“分析这个项目”
  ↓
Agent 搜索、读取、分析文件
  ↓
在对话区展示过程和结论
  ↓
需要修改时展示计划和 Diff
  ↓
用户确认后执行

这是后续接近 Codex / Claude Code 工作流的基础。