AI应用demo(二)打造个人的code agent

一、文档生成

参考 ai coding工具共性(六)spec driven(2)claude code实战&SDD-CSDN博客

先让ai梳理需求

帮我梳理 claude code这个产品的核心功能模块,按类别分组,每个模块用一两句话说明它做什么。

再让ai生成初步文档

我想实现一个类似claude code的code agent,我的需求是:做一个可视化的web界面来和用户交互,用户选择工作区、输入指令、运行--》agent输出--》如果涉及文件改动,需要用户点击确认--》文件落盘。后端语言使用python,可以使用langchin、mcp等主流框架,考虑用户指令涉及的修改文件比较多,需要像cursor、claude code这些主流软件一样实现流式修改文件。代码规范:目录需要按功能划分,代码不要分割成很多函数,这只是个人demo,不需要过于包装,代码简单可读即可,你帮我出一个详细的设计文档,让ai可以一键生成代码

关键逻辑补充

对于生成的文档,追问细节(claude code是怎么实现的),ai回答后,让它补充到文档中。

比如claude code和llm是怎么交互的?

用户指令 → Claude Code 构造 prompt → LLM 返回 tool call → 执行工具 → 结果反馈给 LLM → 循环直到完成

带了哪些信息给llm?

怎么找到关键文件的?

Claude Code 给 LLM 配了一套工具,然后让 LLM 自主规划搜索路径,通过多轮 tool call + 结果反馈的 ReAct 循环,逐步定位目标文件------本质上是 LLM 在"自己摸索"代码库。

简答:混合检索,不是只靠一种。

在 Claude Code 这类 Agent 里,典型优先级通常是:

    1. 关键词/符号检索(主力)

    最常用、最快、可解释性最好(函数名、类名、报错、路径词)。

    1. 结构化线索检索

    路径模式、import/call 关系、邻近代码块扩展。

    1. 语义检索(按需)

    当用户描述很抽象时再启用("处理登录态的逻辑在哪")。

一般会是下面几层,从快到慢:

  • L0:会话内上下文
    当前对话、你刚打开的文件、最近修改、光标附近代码,这些是"最高优先级、零检索成本"的信息。
  • L1:符号/结构级检索(高精度)
    先用代码结构信息(函数、类、引用关系、import 图)缩小范围,比纯文本 grep 更懂代码语义。
  • L2:关键词检索(高召回)
    类似 ripgrep/BM25,速度非常快,擅长精确词命中(函数名、配置项、报错文本)。
  • L3:语义检索(向量)
    当你说"找处理鉴权的地方"这种不带精确关键词的问题时,embedding 检索能补上关键词检索的盲区。
  • L4:重排与裁剪(质量控制)
    候选片段会再做相关性排序、去重、邻近扩展(补 imports/调用方),并控制 token 预算再喂给 LLM。

diff是谁决定的?

  • 选哪些文件:LLM 根据上下文自主决定 read/edit 哪些文件
  • 改成什么内容:LLM 直接输出新代码,App 原样写入
  • 改动范围大小:一次改1个文件还是10个,LLM 说了算

App 本身不会对"改动内容的正确性"做任何校验,它只是个忠实的执行器。

"返回修改块/补丁语义,而不是返回整个文档内容

后续处理是什么?

对于 LLM 产出的 diff,Claude Code 这类 Agent 一般会做一整套后处理,不是直接写盘:

  • 格式与结构校验

    先检查 diff/patch 是否可解析、文件路径是否合法、操作类型是否受支持。

  • 安全校验

    防路径越权(如 ../)、防改动工作区外文件、必要时限制敏感文件写入。

  • 冲突检测

    用文件哈希或版本戳比对当前文件是否已变化;变了就报冲突,不盲写。

  • 预览与确认

    把改动展示给用户(按文件、按 hunk),通常需要用户确认后才 apply。

  • 应用策略

    不是"整包替换",通常按 patch 精确应用;失败时做回滚/部分失败提示。

  • 验证步骤(可选但推荐)

    自动跑 lint/test/typecheck;失败会反馈并可能触发下一轮修复。

  • 状态与审计记录

    更新任务状态(waiting_confirm/applied/failed),记录失败原因与上下文。

内置tools是怎么用的?

在 Claude Code 里,内置 tools 本质上是给 LLM 的"可执行手脚",让它不只会说,还能查、改、跑、验。可按职责分这几类:

  • 代码与文件工具

    读文件、搜索代码、改文件、看 diff。

    作用:拿证据、定位改动点、生成精确修改而不是瞎写。

  • 终端执行工具

    跑命令(测试、构建、安装依赖、git 状态等)。

    作用:把"建议"变成"可验证结果"。

  • 项目上下文工具

    获取工作区状态、打开文件、光标、诊断信息等。

    作用:让 LLM 基于当前 IDE 情境做决策。

  • 版本控制/协作工具

    看分支、提交、PR/MR(取决于环境权限)。

    作用:把改动进入团队协作流程。

  • 外部系统工具(可选)

    比如 Jira、GitLab、文档系统、聊天系统。

    作用:跨系统查信息或执行工作流。

  • 浏览器/自动化工具(可选)

    用于页面操作、E2E 验证、抓取结果。

    作用:验证前端行为而不只看静态代码。

其他细节打磨

其他不确定(代码怎么实现的)也可以让ai列出来,比如后端项目结构、前端交互细节、task有哪些状态,然后对照文档,继续沟通改进。比如结构精简、交互调整。

最后的文档

你是一个资深的软件架构师、技术负责人(Tech Lead)、产品经理和技术文档专家。

我会给你一份经历过多轮迭代的软件需求/设计文档。

背景:

  • 文档经过多次补充与修改

  • 存在明显的"更新痕迹"

  • 有些内容可能重复、前后矛盾、表达不一致

  • 有些章节可能已经过时,但未被清理

  • 文档风格不统一,部分内容像讨论稿而不是正式方案

你的目标不是局部修改,而是:

**把这份文档 review 并重构为"项目启动前可直接定稿"的正式版本。**

需求

复制代码
# 类 Claude Code 可视化 Code Agent 需求与总体设计文档(V1)

## 一、文档说明

### 1.1 文档定位

本文档为 Code Agent 项目 V1 的需求与总体设计基线,用于项目启动、评审、开发对齐与测试验收。

- 面向角色:产品经理、Tech Lead、前后端工程师、测试工程师。
- 使用阶段:立项评审 -> 开发实施 -> 联调验收。
- 权威性:本文档是范围、流程和约束的统一口径。

### 1.2 文档关系

- 本文档:定义产品目标、系统边界、状态机、核心流程、验收标准。
- `design/后端设计.md`:后端实现细则(API、存储、执行编排、错误处理)。
- `design/前端设计.md`:前端实现细则(页面、状态展示、交互行为、E2E)。

若细则文档与本文冲突,以本文为准。

---

## 二、项目背景与目标

### 2.1 背景

目标是实现一个简化版 "Claude Code" 的可视化代码助手,用户通过 Web 界面提交自然语言任务,由 Agent 在受控条件下进行代码分析与改动提案,并在用户确认后写入工作区文件。

### 2.2 核心目标

用户可以稳定完成以下闭环:

1. 登录系统。
2. 选择工作区。
3. 输入任务指令。
4. 查看流式执行输出与关键步骤。
5. 查看文件改动 diff。
6. 确认后写盘。

### 2.3 MVP 范围

- 单用户、单工作区、单任务会话。
- 支持 REST + WebSocket 协议。
- 支持混合检索与多轮补充上下文。
- 支持文件修改提案预览与确认写盘。
- 支持任务状态追踪与标准错误码返回。

### 2.4 非目标(V1 不做)

- 多人协作编辑与复杂权限体系。
- 跨仓库检索与跨项目上下文共享。
- 自动 Git 提交、推送、MR 流程。
- 自动降级成功、离线兜底等复杂容错策略。

---

## 三、术语定义

- **Task**:一次用户指令执行实例,覆盖检索、分析、提案、确认全生命周期。
- **Change**:Task 下单文件改动提案。
- **Diff**:改动前后差异展示,不代表写盘已发生。
- **Phase**:`running` 状态内部阶段,如 `retrieval`、`retrieve_more`、`patch_planning`。
- **Workspace**:用户被授权的项目根目录。

---

## 四、系统总体架构

```text
前端(React/Vue) <-> 后端(FastAPI) <-> MySQL / Redis / 文件系统
```

### 4.1 前端职责

- 工作区选择与任务输入。
- 流式输出展示(token/status/diff/error/done)。
- 变更列表与 diff 预览。
- 确认写盘、取消任务等用户操作。

### 4.2 后端职责

- 任务生命周期管理与状态机控制。
- LLM 调用编排与上下文注入。
- 检索、diff 生成、写盘安全校验。
- 持久化与可观测信息输出。

### 4.3 存储职责

- MySQL:任务主数据、工作区、变更记录等长期数据。
- Redis:实时状态、流式缓存、会话短期数据。
- 文件系统:工作区读写(必须在沙箱范围内)。

---

## 五、核心设计原则

1. **受控执行**:LLM 只给建议,写盘必须经校验与用户确认。
2. **检索优先**:仅注入必要上下文,不做全仓全文透传。
3. **协议驱动**:前后端通过固定 REST/WS 契约协作。
4. **状态一致**:前端状态以后端状态机为准,不推断业务结果。
5. **可追踪**:关键链路需提供错误码、状态、耗时、日志信息。

---

## 六、任务流程与状态机

### 6.1 主状态机(后端权威)

- 主链路:`running -> waiting_confirm -> done`
- 分析链路:`running -> done`
- 失败链路:`running -> failed`
- 取消链路:`running/waiting_confirm -> cancelled`

### 6.2 状态约束

- 进入 `waiting_confirm` 前必须有可展示 diff。
- `done` 可由纯分析任务直接到达。
- `cancelled` 仅允许从 `running` 或 `waiting_confirm` 进入。

### 6.3 澄清策略(V1)

当意图不明确或上下文不足时:

- 本次任务返回澄清建议并结束为 `done`。
- 用户通过新任务补充信息并继续。
- V1 不引入独立 `waiting_user_input` 中间态。

---

## 七、上下文构建与检索策略

### 7.1 上下文构建原则

- 先传候选文件路径,再按需读取代码片段。
- 仅传相关目录片段与命中证据,不传完整目录树和全量文件内容。
- 采用 token 预算限制,超限时截断并返回可解释信息。

### 7.2 混合检索策略

1. 关键词/符号检索优先。
2. 召回不足时补充语义检索。
3. 融合重排后裁剪注入。
4. 仅增量补充,避免重复上下文。
5. 文件路径/文件名命中优先于内容命中(优先高精度信号)。
6. 融合排序后做"多样性约束"(避免结果过度集中到单目录/单类型文件)。

检索实现口径(快且准):
- 快:先走低成本的路径、文件名、符号线索,减少全仓扫描与无效注入。
- 准:将关键词命中与语义命中做融合重排,再截取最小必要片段。
- 稳:所有轮次受预算与轮次上限约束,超限返回可解释原因。

### 7.3 多轮补充机制

- 当模型返回 `need_more_context=true` 时继续检索。
- 每轮必须包含新增检索证据与预算更新。
- 受 `max_context_rounds` 与 token 上限双重约束。
- 若 `need_more_context=true` 但缺少 `next_search_queries`,立即终止并返回错误原因。

---

## 八、API 与协议约束

### 8.1 REST 接口

- `POST /api/auth/login`
- `POST /api/workspace/select`
- `POST /api/tasks`
- `GET /api/tasks/{task_id}`
- `POST /api/tasks/{task_id}/confirm`
- `POST /api/tasks/{task_id}/cancel`

统一响应格式:

```json
{
  "code": 0,
  "message": "ok",
  "data": {}
}
```

### 8.2 WebSocket 协议

- 连接:`/ws/tasks/{task_id}/stream`
- 事件:`token` / `status` / `diff` / `error` / `done`
- 前端以 `payload.status` 驱动状态展示,不可自行推断后端结果。

---

## 九、文件改动与确认写盘

### 9.1 改动提案

- LLM 输出结构化改动提案,后端完成 schema 校验后生成 diff。
- 改动写入前必须进入 `waiting_confirm` 并展示可选变更。

### 9.2 确认写盘硬约束

- 未确认不得写盘。
- `confirm` 时必须校验 `old_hash`,冲突返回 `3001`。
- `confirm` 时按操作类型校验载荷:  
  - `operation in {update,create}`:`new_content` 必须为非空字符串;  
  - `operation == patch`:`diff_unified` 必须为非空字符串。
- `patch` 写盘采用"strict unified diff -> fallback"两阶段应用;若所有阶段均无法命中替换锚点,返回 `3002`,禁止部分写入。
- 所有写盘路径必须位于 workspace 根目录内。

---

## 十、前端交互规范(总览)

### 10.1 页面结构

- 登录页
- 工作区选择页
- Agent 主界面(左:目录树,中:Chat,右:任务详情与 diff)

### 10.2 交互约束

- `submitting/streaming/applying` 时禁用发送按钮。
- `submitting/streaming/waiting_confirm` 时允许"终止任务"。
- `waiting_confirm` 默认不全选变更。
- 选择为空时"确认修改"按钮置灰。
- 关键 phase 可展示,但最终结果以后端状态为准。

---

## 十一、后端实现约束(总览)

### 11.1 分层约束

- `api`:协议层,不承载复杂业务。
- `services`:流程编排和状态推进。
- `llm`:模型调用、工具协议、响应解析。
- `repositories`:数据访问,不承载决策逻辑。
- `infra`:文件系统与运行时基础能力。

### 11.2 Tool 调用约束

- 写工具必须受阶段控制。
- `apply_patch` 仅允许在 `waiting_confirm` 阶段执行。
- 所有 tool 调用必须在 workspace 沙箱内。

---

## 十二、错误码基线

- `0`:成功
- `1001`:工作区不存在或不可访问
- `1002`:工作区越权访问
- `1101`:用户名或密码错误
- `1102`:账号被禁用
- `1103`:登录频率受限
- `2001`:模型调用失败
- `2002`:模型输出格式不合法
- `2003`:上下文不足(预算/轮次上限)
- `3001`:写入冲突
- `3002`:写入失败
- `9000`:系统异常(含 `invalid new_content`)

---

## 十三、非功能要求(NFR)

- **可靠性**:任务可取消、可失败、可恢复。
- **性能**:上下文注入受预算控制,避免无界增长。
- **安全性**:路径沙箱、确认写盘、防冲突。
- **可观测性**:任务状态、阶段、错误码、耗时可追踪。
- **可维护性**:文档边界清晰,约束来源唯一。

---

## 十四、测试与验收标准

### 14.1 必测链路

1. 登录成功/失败链路。
2. 工作区选择与安全校验链路。
3. 正常链路:`create -> stream -> waiting_confirm -> confirm -> done`。
4. 分析链路:`running -> done`(无 diff)。
5. 取消链路:`running/waiting_confirm -> cancelled`。
6. 异常链路:`2001/2002/2003/3001/9000`。

### 14.2 验收判定

满足以下条件可视为 V1 可验收:

- 状态机行为与文档一致。
- API/WS 契约稳定并完成联调。
- 写盘安全约束均有自动化覆盖。
- 关键错误码路径可复现、可定位。
- 端到端闭环稳定可演示。

---

## 十五、里程碑建议

- **M1**:需求与协议冻结(本文档评审通过)。
- **M2**:最小闭环打通(登录到确认写盘)。
- **M3**:异常与稳定性补齐(冲突、取消、超限等)。
- **M4**:验收回归通过并准备发布。

---

## 十六、实施说明

- 当前版本为 V1 定稿基线,后续变更必须走评审并记录版本差异。
- 建议在 `后端设计.md` 与 `前端设计.md` 中补充"与总览一致性"章节,避免实现口径漂移。
# 类Claude Code的可视化Code Agent设计文档

## 一、项目概述

本项目旨在实现一个简化版的"Claude Code"式代码智能助手(Code Agent),通过可视化Web界面与用户交互,实现以下流程:

1. 用户登录(username/password)  
2. 用户选择工作区(本地项目目录)  
3. 用户输入自然语言指令  
4. Agent调用模型生成响应,并展示当前执行步骤  
5. 若涉及文件修改,展示修改预览并等待用户确认  
6. 用户确认后将修改落盘  

后端使用 **Python** 实现,可选框架包括 **LangChain** 或 **MCP**。前端采用 **React/Vue + WebSocket** 实现流式交互。

### 范围与目标

- **本期目标(MVP)**:单工作区、单会话、单用户,支持文本指令、流式响应、文件修改预览、用户确认写入。
- **非目标(MVP不做)**:多人协作编辑、复杂权限系统、跨仓库检索、自动提交远端仓库。
- **成功标准**:用户可在前端完成"输入指令 -> 预览修改 -> 确认落盘"闭环,且有可追踪的任务记录与失败错误码。

### 术语定义

- **Task**:一次用户指令执行实例,包含从检索到确认写入的完整生命周期。
- **Change**:某个 Task 下的单文件修改提案(可被用户选择性确认)。
- **Diff**:文件修改前后差异展示,不等于直接写盘结果。
- **Phase**:`running` 状态下的子阶段(如 `retrieval`、`retrieve_more`、`patch_planning`)。

---

## 二、系统架构

### 1. 总体架构

```
┌──────────────────────────────┐
│          前端界面            │
│  - 工作区选择                │
│  - 指令输入框                │
│  - Agent输出流式展示         │
│  - 文件修改预览与确认        │
└──────────────┬──────────────┘
               │ WebSocket / REST
┌──────────────┴──────────────┐
│          后端服务            │
│  - 指令解析与模型调用        │
│  - 文件修改流式生成          │
│  - 文件写入与版本管理        │
│  - 工作区管理                │
└──────────────┬──────────────┘
               │
┌──────────────┴──────────────┐
│          文件系统            │
│  - 用户项目目录              │
│  - 临时修改缓存              │
└──────────────────────────────┘
```

---

## 三、功能模块设计

### 1. 前端模块

| 模块 | 功能说明 |
|------|-----------|
| **工作区选择器** | 允许用户选择本地或服务器上的项目目录。 |
| **指令输入区** | 用户输入自然语言任务描述。 |
| **输出展示区** | 实时展示Agent的流式输出。 |
| **文件修改预览区** | 展示模型建议的文件修改diff,用户可确认或拒绝。 |

**技术建议:**
- 使用 React/Vue + TailwindCSS  
- WebSocket 实现流式输出  
- Diff 组件可使用 `react-diff-viewer` 或 `diff2html`  

---

### 2. 后端模块

| 模块 | 功能说明 |
|------|-----------|
| **API层** | 提供 REST 接口(工作区选择、任务提交、确认修改)与 WebSocket 通道(流式输出)。 |
| **Agent核心模块** | 负责调用模型接口(OpenAI API),解析用户指令,生成修改建议。 |
| **文件修改管理模块** | 负责生成文件diff、缓存修改、等待用户确认后落盘。 |
| **工作区管理模块** | 管理用户选择的项目路径,提供文件读写接口。 |
| **任务状态机模块** | 管理任务生命周期(running/waiting_confirm/done/failed/cancelled)。 |

---

## 四、前后端项目结构总览

```text
project_root/
├── app/                           # 后端服务(FastAPI)
│   ├── main.py                    # 应用入口
│   ├── api/                       # 路由与协议适配层
│   │   └── api.py                 # REST/WS 路由 + DTO/事件模型
│   ├── services/                  # 核心流程编排层(task/confirm)
│   ├── domain/                    # 领域类、枚举与状态机
│   ├── llm/                       # LLM 模块(llm_client)
│   │   └── tool_registry.py       # 内置工具定义与schema
│   ├── repositories/              # MySQL/Redis 访问层
│   ├── infra/                     # 文件系统等基础设施
│   ├── utils/                     # 通用工具
│   └── config.py                  # 配置管理(含 APP_PORT)
├── frontend/                      # 前端应用(React/Vue)
│   ├── src/
│   │   ├── pages/                 # 页面容器
│   │   ├── components/            # UI组件
│   │   ├── stores/                # 状态管理
│   │   ├── services/              # 接口调用与WS客户端
│   │   └── styles/                # 主题与样式
│   └── package.json
├── design/                        # 设计文档
│   ├── 需求设计文档.md
│   ├── 后端设计.md
│   └── 前端设计.md
└── requirements.txt               # 后端依赖
```

说明:
- 本节用于全栈目录对齐,详细实现规范仍以 `design/后端设计.md` 与 `design/前端设计.md` 为准。
- 后端结构采用"编排(services) 与 LLM(llm) 解耦"原则,`services` 仅保留核心流程文件。
- `api` 层可合并为 `api.py`(路由 + schema);`config.py` 独立维护全局配置。
- 内置 tools 独立定义在 `llm/tool_registry.py`,通过 schema 注入模型,避免工具定义散落在业务代码中。
- `llm_client.py` 合并网关、模型调用、prompt组装与响应解析;`domain_types.py` 合并领域类、枚举与状态机定义。
- 检索不单独拆 `retrieval_service.py`,由 `task_service.py` 直接编排并调用内置检索 tools。

---
## 五、详细设计文档索引

为避免总览文档过长,详细实现已拆分:

- 后端实现细节:`design/后端设计.md`
  - API 契约、WebSocket 协议、状态机
  - MySQL schema 与 Redis key 规范
  - 并发策略、错误码与配置规范
- 前端实现细节:`design/前端设计.md`
  - 页面布局、样式 token、状态模型
  - 接口映射、交互细则与 E2E 用例

---

## 六、交互流程

1. 用户登录并通过身份校验  
2. 选择工作区并进入 Agent 主界面  
3. 前端通过 WebSocket 发送指令  
4. 后端调用模型接口,流式返回输出  
5. 前端根据 `status` 展示关键处理步骤  
6. 若输出包含文件修改建议,展示 diff 与确认栏  
7. 用户确认后,后端执行文件写入  

### 任务状态流转(建议)

`running -> waiting_confirm -> done`  
`running -> failed`  
`running/waiting_confirm -> cancelled`

说明:
- 进入 `waiting_confirm` 时必须已有可展示的 `diff` 列表。
- `done` 后记录备份点,支持后续回滚能力扩展。

---

## 七、未来扩展方向

- 增加多文件修改预览与批量确认  
- 集成Git版本控制  
- 增加任务历史记录与回滚功能  
- 支持多模型切换与上下文记忆  

---

## 八、开发环境建议

- **后端框架**:FastAPI + LangChain(可选)  
- **前端框架**:React + WebSocket  
- **依赖管理**:Poetry 或 pip  
- **运行环境**:Python 3.10+  

## 九、非功能要求(NFR)

- **可靠性**:任务执行可中断、可超时、可恢复;异常必须返回标准错误码。
- **性能**:上下文检索与装配需受 token 预算控制,避免无界增长。
- **安全性**:仅允许工作区内合法路径写入,禁止路径逃逸与未确认自动写盘。
- **可观测性**:至少暴露任务状态、阶段、错误码、耗时等基础指标。
- **可维护性**:总览与实现文档分层,避免同一约束在多文档重复定义。
- **排障性**:关键链路(登录、选区、建任务、LLM 调用、确认、取消、WS 连接)需有可检索日志。

---

## 十、核心设计原则

- **受控执行**:LLM 只生成建议,文件落盘必须经过结构校验、安全校验和用户确认。
- **检索优先**:上下文通过关键词/符号检索与按需语义检索构建,不传完整工作区。
- **协议驱动**:前后端通过固定 REST + WebSocket 协议协作,避免隐式约定。
- **状态一致**:前端状态以任务状态机为准,不在客户端推断业务结果。
- **可恢复**:任务主数据落 MySQL,会话与实时态落 Redis,服务重启后可恢复。

### 1. 指令解析与执行链路

- **自然语言解析**:用户输入的任务描述由 LLM 解析为具体操作意图(如修改文件、新增函数等)。
- **目标文件定位(混合检索)**:先使用关键词/符号检索(如函数名、类名、报错信息、路径关键词)召回候选文件;当用户描述偏语义(如"登录态处理逻辑")时,再补充语义检索(向量检索)。语义检索不是每次必用,而是按查询类型按需启用。
- **上下文构建与裁剪**:不会默认把完整工作区目录树和全部文件内容传给 LLM,而是仅传递"相关目录片段 + 命中文件路径 + 关键代码片段"。执行顺序为"先带候选文件路径,再按需读取文件片段并注入上下文"。在 token 预算内按相关性排序并截断,减少噪声并控制成本。
- **流式响应**:通过 WebSocket 将 LLM 输出实时推送至前端,用户可实时查看生成过程。
- **受控决策**:LLM 负责生成建议,但系统仍需执行结构校验、路径安全校验、冲突检测与用户确认,避免高风险自动写入。
- **迭代式检索执行**:一次检索不足时,Agent 会继续发起下一轮文件搜索/读取,再将新增上下文补充给 LLM,直到能够完成任务。

#### 混合检索策略(关键设计)

- **默认策略**:关键词/符号检索优先(高精度、低成本、可解释)。
- **按需语义**:仅当关键词召回不足或用户描述抽象时启用语义检索(向量)。
- **融合重排**:将关键词命中与语义命中合并后重排,再做上下文裁剪。
- **算法可插拔**:允许使用 BM25、向量召回、规则重排等任一组合,但对上保持统一检索接口。
- **实现不绑死算法**:设计层要求"混合检索能力",不强制依赖单一检索引擎。

#### 信息不足时的继续处理机制(关键约束)

- **分批上下文**:默认只发送首批高相关片段,不一次性发送全部候选文件。
- **不足判定信号**:当 LLM 输出出现"缺少定义/调用链/配置/测试上下文"等信号时,任务保持 `running`,进入补充检索阶段。
- **补充检索范围**:按"同文件邻近片段 -> import 依赖 -> 调用方/被调用方 -> 配置与测试文件"逐级扩展,避免盲目全仓扫描。
- **增量补充原则**:仅补充新增证据片段,避免重复传输已读内容,控制 token 消耗。
- **轮次上限保护**:设置最大补充轮次与 token 预算,超限后返回"信息仍不足"的明确原因与建议操作。
- **可解释性输出**:前端应可看到当前阶段(retrieval/analysis/patch_planning)与补充原因,避免"卡住"体验。

### 2. 传递给 LLM 的上下文参数

- **系统与开发指令**:角色设定、工具使用约束、安全边界、输出格式要求。
- **用户会话信息**:当前用户指令、多轮历史消息、用户附加约束。
- **工作区与 IDE 状态**:操作系统、工作区路径、当前打开文件、光标位置、最近访问文件等环境信息。
- **检索结果与文件片段**:候选文件路径、代码片段、必要的目录结构信息(非完整目录树)。
- **工具执行结果**:搜索输出、命令行输出、lint/test 结果、diff 预览等。
- **模型调用参数**:模型名称、温度、最大输出 token、是否流式输出、停止条件等。

上下文装配顺序:
1. 系统与开发指令  
2. 用户当前任务与会话摘要  
3. 首批检索结果(先路径候选,再增量片段)  
4. 最近一轮工具执行结果  
5. 模型调用参数与输出格式约束  

### 3. 文件修改与确认流程

- **修改预览**:LLM 生成的改动以 diff 形式展示,用户可逐行查看差异。
- **用户确认**:用户点击"确认修改"后,系统才将变更写入文件;未确认前不做任何写入。
- **临时缓存**:确认前修改内容保存在临时缓存中,不覆盖原文件。
- **确认按钮约束**:当未勾选任何变更时,"确认修改"按钮必须置灰,避免空选择提交。
- **写盘安全约束**:确认阶段若 `new_content` 为空字符串,必须拒绝写盘并返回错误,防止目标文件被清空。

### 4. 前端 UI 逻辑约束

- **页面布局约束**:顶部栏(56px)、左侧栏(280px)、主工作区上下分栏、底部固定输入区。
- **视觉规范约束**:主色 `#3B82F6`,成功 `#22C55E`,警告 `#F59E0B`,错误 `#EF4444`,代码区使用等宽字体。
- **状态模型约束**:`idle/submitting/streaming/waiting_confirm/applying/done|error|cancelled`。
- **一致性约束**:前端状态切换需与后端 `task.status` 一致,前端仅做展示与交互,不自行推断最终结果。
- **终止交互约束**:前端需提供"终止当前任务"入口;点击后调用取消接口并停止当前流式连接。
- **最近工作区约束**:登录成功后若后端返回最近一次工作区,前端应默认回填并允许用户覆盖。

---

## 十一、代码生成约束

- Agent 输出采用结构化 JSON,服务端做 Schema 校验后才生成 diff。
- `POST /api/tasks` 由前端提交态置灰防重复,后端不再维护幂等键存储。
- 变更记录的 `change_id` 仅保证任务内可定位,不做全局唯一约束,避免重复任务提交被数据库唯一键拦截。
- Redis 不维护 `change_id` 的跨任务幂等,仅保留按 `task_id` 组织的短期运行态缓存。
- `confirm` 必须校验 `old_hash`,冲突返回 `3001`。
- `confirm` 额外校验 `new_content` 非空字符串;校验失败返回 `9000/invalid new_content`。
- 所有 Redis 写入需设置 TTL,防止无界增长。
- `config.py` 必须支持 `APP_PORT` 环境变量,避免本地端口冲突。
- 多轮补充检索必须可中断、可超时、可回退,不允许无限循环。
- V1 采用"失败快返"策略:`OPENAI_API_KEY` 未配置、网关错误、网络错误均直接失败透传,不做 mock 降级与成功态兜底。
- V1 禁止在任务主链路增加大范围 `try/except` 吞异常;仅允许必要的最小边界清理逻辑。
### 11.1 约束规范

- `MUST`(强约束):必须实现并有测试;未满足不得标记完成。
- `SHOULD`(默认约束):原则上实现;若不实现需在评审记录中说明原因。
- `MAY`(可选约束):作为优化项管理,不阻塞主链路验收。

执行建议:
1. 每条"约束"后追加级别标签(`[MUST]` / `[SHOULD]` / `[MAY]`)。
2. 评审时逐条核对"文档约束 -> 代码实现 -> 测试用例"三者映射。
3. 对延期项集中维护清单,避免执行口径漂移。

### 11.2 核心约束分级清单

| 约束项 | 级别 | 验收方式 | 备注 |
|---|---|---|---|
| 未确认不得写盘(先 diff 再 confirm) | MUST | E2E:`create -> waiting_confirm -> confirm` | |
| 确认时 `old_hash` 冲突返回 `3001` | MUST | 集成测试:冲突写入场景 | |
| 确认时 `new_content` 为空拒绝写盘(`9000`) | MUST | 单元/集成测试:空内容写盘保护 | |
| `need_more_context` 驱动多轮补充检索 | MUST | 单元测试:多轮 loop 收敛 | |
| 补充检索轮次上限(`max_context_rounds`) | MUST | 配置 + 单测/日志验证 | |
| `need_more_context=true` 但无 `next_search_queries` 时终止 | MUST | 单元测试:限制项断言 | |
| 任务状态机一致性(前后端状态对齐) | MUST | 联调:状态流转核对 | |
| Key缺失/网关/网络异常失败透传(不降级) | MUST | 集成测试:缺 key 与网关故障场景 | V1 口径 |
| 可观测性日志覆盖关键链路 | SHOULD | 日志审计清单 | |
| Redis TTL 防无界增长 | SHOULD | 代码检查 + 运行时键抽样 | |
| 上下文超限错误可解释(`2003`) | SHOULD | 失败路径测试 | |

---

## 十二、文档边界与合并策略

- 本文档仅保留产品与系统总览,不包含 DDL、Redis key 细节、页面组件细节。
- 后端实现规范见 `design/后端设计.md`。
- 前端实现规范见 `design/前端设计.md`。
- 不建议将本总览文档合并到后端文档:总览面向全栈协作与架构对齐,后端文档面向实现与接口落地,读者与维护节奏不同。

---

## 十三、总结

本文档用于统一范围、流程与原则,指导前后端按拆分文档并行实现。实现阶段以 `design/后端设计.md` 与 `design/前端设计.md` 为准。

后端

复制代码
# Code Agent 后端设计

## 1. 目标与范围

- 负责工作区管理、任务执行、模型编排、变更确认写入。
- 提供 REST + WebSocket 双协议。
- 保障可恢复、可追踪、可并发控制。

### 1.1 文档定位

- 本文档是后端实现基线,面向开发与联调,不承担产品范围定义。
- 术语与范围以 `design/需求设计文档.md` 为上位约束,冲突时以总览文档为准。

### 1.2 后端项目结构拆分(推荐)

```text
app/
├── main.py
├── api/
│   └── api.py                      # REST/WS 路由 + DTO/事件模型
├── services/
│   ├── task_service.py             # 任务主流程(含 loop 编排)
│   └── confirm_service.py          # 预检 + 应用改动
├── llm/
│   ├── llm_client.py               # 统一 LLM 接口(含调用、prompt组装、响应解析)
│   └── tool_registry.py            # 内置 tools 定义与 schema
├── domain/
│   └── domain_types.py             # 领域类 + 状态机 + 枚举定义
├── repositories/
│   ├── mysql_repo.py               # MySQL 访问(task/workspace/change)
│   └── redis_repo.py               # Redis 访问(runtime/conversation)
├── infra/
│   └── runtime_support.py          # 文件读写
└── config.py
```

分层职责约束:
- `services` 仅做核心流程编排与决策,不实现模型协议细节。
- `llm` 负责模型交互细节;`services` 只调用 `llm.llm_client`。
- 状态迁移与枚举集中在 `domain/domain_types.py`,禁止在路由层硬编码状态跳转。
- `repositories` 仅负责存储读写,不承载业务分支。

### 1.3 包名与文件清单(骨架规范)

> 当前精简骨架共 **11 个 Python 文件**(不含测试与 `__init__.py`)。

| 包 | 文件 | 主要职责 | 关键类/函数(建议签名) |
|---|---|---|---|
| `app` | `main.py` | 应用启动 | `create_app()`, `main()` |
| `app` | `config.py` | 配置管理 | `class Settings` |
| `app.api` | `api.py` | REST/WS 路由 + DTO/事件结构 | `create_task(req)`, `get_task(task_id)`, `CreateTaskRequest`, `WsEvent` |
| `app.services` | `task_service.py` | 主流程编排(意图判定+loop) | `run_task(task_id: str) -> None` |
| `app.services` | `confirm_service.py` | confirm/apply | `confirm_apply(task_id: str, change_ids: list[str])` |
| `app.llm` | `llm_client.py` | LLM 统一调用(含 chat/prompt组装/响应解析) | `chat(...)`, `build_messages(...)`, `parse_response(...)`, `run_agent_loop(...)` |
| `app.llm` | `tool_registry.py` | 内置 tools 注册与参数校验 | `list_tools()`, `get_tool_schema(name)` |
| `app.domain` | `domain_types.py` | 领域类 + 状态机 + 枚举 | `class Task`, `class Change`, `class Workspace`, `TaskStatus`, `transition(...)` |
| `app.repositories` | `mysql_repo.py` | MySQL 读写 | `create_task(...)`, `update_task(...)` |
| `app.repositories` | `redis_repo.py` | Redis 读写 | `set_status(...)`, `append_stream(...)` |
| `app.infra` | `runtime_support.py` | 文件基础能力 | `apply_patch(...)` |

精简原则:
- 小体量、强相关逻辑优先合并(如 `domain_types.py`、`llm_client.py`、`runtime_support.py`)。
- `services` 只保留核心流程文件(`task_service.py`、`confirm_service.py`)。
- 后续仅在单文件复杂度明显上升时再拆分,不预拆。
- `api` 层采用单文件 `api.py`(路由 + schema);`config.py` 仍保持独立,避免跨层耦合。

检索执行约束(由 `task_service.py` 直接调 tool 实现):
- 检索能力通过内置 tools 提供:`search_code`、`semantic_search`、`read_snippet`。
- `task_service` 负责检索编排(先关键词后语义、融合重排、预算裁剪)。
- 必须输出可解释证据(`path`, `line/snippet`, `score/source`),用于前端展示与 LLM 输入。

## 1.4 内置 Tool 设计(独立模块)

为仿照 Claude Code 的可工具化执行模式,定义独立模块 `app/llm/tool_registry.py`,统一管理工具清单、参数 schema、调用权限与路由。

### Tool Registry 职责

- 声明内置 tool 列表(名称、用途、是否只读、可用阶段)
- 提供 tool 入参/出参 JSON Schema
- 为 `llm.gateway` 提供可注入给模型的工具定义
- 校验模型发起的 tool 调用是否合法

建议接口:

```python
def list_tools() -> list[dict]: ...
def get_tool_schema(name: str) -> dict: ...
def is_tool_allowed(name: str, phase: str, requires_patch: bool) -> bool: ...
```

### 内置 Tool 清单(MVP:8个)

1. `search_code`(只读)  
   - 作用:关键词/符号检索代码  
   - 入参:`query`, `path`, `limit`  
   - 出参:`[{path, line, snippet}]`

2. `semantic_search`(只读)  
   - 作用:语义检索相关代码片段  
   - 入参:`query`, `path`, `limit`  
   - 出参:`[{path, score, snippet}]`

检索执行策略(适用于 `search_code` + `semantic_search`):
- Step1:先执行 `search_code` 召回高精度候选。
- Step2:若候选数量不足或覆盖面不够,再执行 `semantic_search`。
- Step3:融合结果并重排(可基于规则/BM25/向量得分)。
- Step4:按 token 预算裁剪后注入 `retrieval_context`。

检索性能与精度优化(MUST):
- 分层优先级:路径提示命中 > 文件名命中 > 符号/标识符命中 > 关键词命中。
- 混合评分:路径与文件名用于高精度定位,内容预览用于召回补充;避免只依赖单一规则。
- 结果多样性重排:限制同目录/同后缀文件过度集中,降低"同文件簇"噪声。
- 预算裁剪:按相关性排序后做上下文预算裁剪(字符/token 预算),禁止无界增长。
- 增量合并:多轮补检索仅合并新增片段,去重键至少包含 `path + start_line + end_line`。

3. `read_snippet`(只读)  
   - 作用:读取文件片段用于证据补充  
   - 入参:`path`, `start_line`, `end_line`  
   - 出参:`{path, content}`

4. `list_directory`(只读)  
   - 作用:查看目录结构(受工作区限制)  
   - 入参:`path`, `depth`  
   - 出参:`[{name, type, path}]`

5. `get_task_state`(只读)  
   - 作用:读取任务状态  
   - 入参:`task_id`  
   - 出参:`{status}`

6. `prepare_diff`(写前处理)  
   - 作用:将 `final_changes` 转换为 diff 预览  
   - 入参:`changes[]`  
   - 出参:`{diffs[], change_ids[]}`

7. `validate_patch`(写前处理)  
   - 作用:做路径安全、冲突、schema 校验  
   - 入参:`task_id`, `selected_changes[]`  
   - 出参:`{ok, violations[], conflicts[]}`

8. `apply_patch`(写操作)  
   - 作用:执行确认后的文件写入  
   - 入参:`task_id`, `selected_changes[]`  
   - 出参:`{applied_files, failed_files[]}`

### 调用约束(关键)

- `analysis_only` 场景禁止 `apply_patch`。
- `requires_patch=false` 时仅允许只读 tools。
- `apply_patch` 仅允许在 `waiting_confirm` 阶段触发。
- 所有 tool 调用必须在 `workspace_root` 沙箱内执行。

### Tool Schema 模板(统一)

所有 tool 建议使用统一包装结构,便于 `llm.gateway` 与 `tool_registry` 复用:

```json
{
  "name": "search_code",
  "description": "Search code by keyword/symbol",
  "input_schema": {
    "type": "object",
    "properties": {},
    "required": []
  },
  "output_schema": {
    "type": "object",
    "properties": {
      "ok": {"type": "boolean"},
      "data": {},
      "error": {
        "type": ["object", "null"],
        "properties": {
          "code": {"type": "integer"},
          "message": {"type": "string"}
        }
      }
    },
    "required": ["ok", "data", "error"]
  }
}
```

### 8 个内置 Tool 的输入输出示例

#### 1) `search_code`

输入:

```json
{
  "query": "UserController getById",
  "path": "app/",
  "limit": 20
}
```

输出:

```json
{
  "ok": true,
  "data": [
    {"path": "app/api/user_api.py", "line": 42, "snippet": "def get_by_id(...):"}
  ],
  "error": null
}
```

#### 2) `semantic_search`

输入:

```json
{
  "query": "where user profile is updated",
  "path": "app/",
  "limit": 10
}
```

输出:

```json
{
  "ok": true,
  "data": [
    {"path": "app/services/user_service.py", "score": 0.92, "snippet": "def update_profile(...):"}
  ],
  "error": null
}
```

#### 3) `read_snippet`

输入:

```json
{
  "path": "app/services/user_service.py",
  "start_line": 30,
  "end_line": 90
}
```

输出:

```json
{
  "ok": true,
  "data": {
    "path": "app/services/user_service.py",
    "content": "def update_profile(...): ..."
  },
  "error": null
}
```

#### 4) `list_directory`

输入:

```json
{
  "path": "app/",
  "depth": 2
}
```

输出:

```json
{
  "ok": true,
  "data": [
    {"name": "services", "type": "dir", "path": "app/services"},
    {"name": "task_service.py", "type": "file", "path": "app/services/task_service.py"}
  ],
  "error": null
}
```

#### 5) `get_task_state`

输入:

```json
{
  "task_id": "task_123"
}
```

输出:

```json
{
  "ok": true,
  "data": {
    "status": "running"
  },
  "error": null
}
```

#### 6) `prepare_diff`

输入:

```json
{
  "changes": [
    {"file_path": "app/services/user_service.py", "operation": "update", "new_content": "..."}
  ]
}
```

输出:

```json
{
  "ok": true,
  "data": {
    "change_ids": ["chg_1"],
    "diffs": [
      {"change_id": "chg_1", "file_path": "app/services/user_service.py", "diff_unified": "@@ ..."}
    ]
  },
  "error": null
}
```

#### 7) `validate_patch`

输入:

```json
{
  "task_id": "task_123",
  "selected_changes": ["chg_1", "chg_2"]
}
```

输出:

```json
{
  "ok": true,
  "data": {
    "valid": false,
    "violations": ["path_outside_workspace"],
    "conflicts": ["app/services/user_service.py"]
  },
  "error": null
}
```

#### 8) `apply_patch`

输入:

```json
{
  "task_id": "task_123",
  "selected_changes": ["chg_1", "chg_2"]
}
```

输出:

```json
{
  "ok": true,
  "data": {
    "applied_files": 1,
    "failed_files": [
      {"file_path": "app/services/user_service.py", "reason": "hash_conflict"}
    ]
  },
  "error": null
}
```

## 2. API 契约

### 2.1 REST

- `POST /api/auth/login`
- `POST /api/workspace/select`
- `POST /api/tasks`
- `GET /api/tasks/{task_id}`
- `POST /api/tasks/{task_id}/confirm`
- `POST /api/tasks/{task_id}/cancel`

统一响应:

```json
{
  "code": 0,
  "message": "ok",
  "data": {}
}
```

统一约束:
- 除 `GET /api/tasks/{task_id}` 外,写操作接口建议支持 `X-Request-Id`(链路追踪)。
- 所有错误响应必须返回 `{code,message,data}`,其中 `data` 至少包含 `task_id`(如可用)。

#### A. `POST /api/workspace/select`

请求体:

```json
{
  "user_id": "u_001",
  "workspace_path": "c:/project/demo",
  "readonly": false
}
```

响应体:

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "workspace_id": "ws_001",
    "workspace_path": "c:/project/demo",
    "readonly": false,
    "capabilities": ["read", "write", "diff"]
  }
}
```

接口逻辑:
1. 校验 `workspace_path` 是否存在且可访问。
2. 执行路径安全检查(禁止越权目录、符号链接逃逸)。
3. 创建或更新 `workspaces` 记录。
4. 返回 `workspace_id` 与能力集。

#### A0. `POST /api/auth/login`

请求体:

```json
{
  "username": "alice",
  "password": "plain_password_input"
}
```

响应体:

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "user_id": "u_001",
    "username": "alice",
    "display_name": "Alice",
    "token": "jwt_or_session_token",
    "expires_in": 7200
  }
}
```

接口逻辑:
1. 根据 `username` 查询用户记录。
2. 使用安全哈希算法校验密码(明文密码仅用于输入,不落库)。
3. 校验通过后签发会话令牌(JWT 或 server-side session)。
4. 返回用户基本信息与会话有效期;校验失败返回统一错误码。

错误码建议:
- `1101`:用户名或密码错误
- `1102`:账号被禁用
- `1103`:登录频率受限

#### B. `POST /api/tasks`

请求体:

```json
{
  "user_id": "u_001",
  "workspace_id": "ws_001",
  "instruction": "重构 user service 并补充单测",
  "options": {
    "stream": true,
    "temperature": 0.2,
    "max_output_tokens": 4096
  }
}
```

响应体:

```json
{
  "code": 0,
  "message": "accepted",
  "data": {
    "task_id": "task_123",
    "status": "running"
  }
}
```

接口逻辑:
1. 校验 `workspace_id` 是否属于 `user_id`。
2. 写入 `tasks`(初始状态 `running`),并初始化 Redis 实时状态。
3. 异步启动任务执行器,直接进入检索与分析阶段。

请求参数约束:
- `instruction` 非空,建议长度 `1..8000`。
- `options.temperature` 建议范围 `0.0..1.0`。

#### C. `GET /api/tasks/{task_id}`

响应体:

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "task_id": "task_123",
    "status": "waiting_confirm",
    "summary": "已生成 2 个文件变更建议",
    "changes": [
      {
        "change_id": "chg_1",
        "file_path": "app/core/agent.py",
        "operation": "update",
        "risk_level": "low"
      }
    ]
  }
}
```

接口逻辑:
1. 查询 MySQL `tasks` 主记录。
2. 读取 Redis 实时状态(若存在则覆盖 `status` 展示值)。
3. 查询 `task_changes` 返回变更摘要(不返回完整 `new_content`)。
4. 按统一响应结构返回任务详情。

#### D. `POST /api/tasks/{task_id}/confirm`

请求体:

```json
{
  "action": "apply",
  "selected_changes": ["chg_1", "chg_2"]
}
```

`action` 当前仅支持 `apply`,保留后续扩展 `reject` 的兼容位。

响应体:

```json
{
  "code": 0,
  "message": "applied",
  "data": {
    "task_id": "task_123",
    "applied_files": 2
  }
}
```

接口逻辑:
1. 校验任务状态必须为 `waiting_confirm`。
2. 读取 `selected_changes` 对应的 `task_changes`。
3. 逐文件校验 `old_hash`,冲突时返回 `3001`。
4. 分操作执行写入参数校验:  
   - `operation in {update, create}`:`new_content` 必须为非空字符串。  
   - `operation == patch`:`diff_unified` 必须为非空 unified diff 文本。  
5. 执行写入(必要时先备份):  
   - `update/create` 走整文件覆盖写盘。  
   - `patch` 走 unified diff 应用。  
   任一文件失败返回 `3002` 并停止后续写入。
6. 更新 Redis 状态。

补充说明:
- 为避免误写空内容导致文件被清空,`update/create` 模式必须校验 `new_content`。
- 为兼容 patch-first 模式,`patch` 可不提供 `new_content`,但必须提供 `diff_unified`。

#### D.1 `patch` 回写到工作区的执行细节(实现口径)

写盘入口与职责:
- 入口函数:`app/services/confirm_service.py::confirm_apply`。
- 文件写盘能力:`app/infra/runtime_support.py::apply_unified_patch`(patch)与 `apply_change`(update/create)。

执行步骤(`operation=patch`):
1. 基础校验:`diff_unified` 必须是非空字符串,否则返回 `9000/invalid diff_unified`。  
2. 沙箱校验:通过 `safe_join(workspace_root, file_path)` 保证目标路径在工作区内,防止路径逃逸。  
3. 读取原文:读取目标文件当前内容,解析 `diff_unified` 的 hunk。  
4. Strict 应用:优先按 unified diff 严格上下文应用(要求上下文与删除行精确匹配)。  
5. Fallback 应用(仅 strict 失败时):
   - 文本块替换 fallback:按 hunk 的 `-`/`+` 块做成对替换;
   - 宽松单行替换 fallback:当 LLM 产出的 diff 上下文较弱(例如仅给注解替换)时,按行做规范化匹配替换;
   - 方法改名 fallback:针对单行签名改名场景(如 `foo(` -> `foo1(`)做模式替换。
6. 全量成功才写盘:任一 fallback 未命中则整体失败,返回 `3002/patch apply failed:*`,不做部分写入。  

失败语义(常见):
- `patch_apply_failed:context_mismatch` / `remove_mismatch`:strict 阶段上下文不一致。
- `patch_apply_failed:fallback_replace_mismatch`:fallback 仍无法在目标文件找到替换锚点。
- `patch_apply_failed:fallback_no_replace_pairs`:diff 中无法提取有效替换对。

工程约束:
- `patch` 写盘以"可验证命中"为前提,不允许"猜测式"落盘。
- 当 `diff_unified` 为弱上下文(如仅 `@@` 占位)时,允许进入宽松 fallback,但仍要求每个替换对可被命中。
- 发生 `3002` 时前端应提示"补充上下文后重试",避免重复提交同一无效 diff。

#### E. `POST /api/tasks/{task_id}/cancel`

请求体:

```json
{
  "reason": "user_manual_cancel"
}
```

响应体:

```json
{
  "code": 0,
  "message": "cancelled",
  "data": {
    "task_id": "task_123",
    "status": "cancelled"
  }
}
```

接口逻辑:
1. 校验当前状态是否可取消(`running/waiting_confirm`)。
2. 标记任务为 `cancelled` 并停止后台执行。
3. 清理 Redis 流缓存与工作区锁。
4. 返回取消结果。

### 2.2 WebSocket

连接:`/ws/tasks/{task_id}/stream`

事件:
- `token`
- `status`
- `diff`
- `error`
- `done`

统一结构:

```json
{
  "event": "status",
  "task_id": "task_123",
  "timestamp": 1716370000,
  "payload": {}
}
```

事件 `payload` 约定:
- `token`:`{"text":"..."}`  
- `status`:`{"status":"running"}`  
- `diff`:`{"change_id":"chg_1","file_path":"app/core/agent.py","diff_unified":"@@ ...","risk_level":"low"}`  
- `error`:`{"code":2001,"message":"model provider timeout"}`  
- `done`:`{"status":"waiting_confirm","change_count":2}`

### 2.3 后端与 LLM 交互编排(Claude Code 风格)

本节定义统一的 LLM 交互契约与 Agent Loop。核心思想是:
- 先判定任务意图(分析/改动/待澄清)
- 再按需多轮补充上下文
- 仅在明确改动意图且信息充足时进入 diff/confirm 流程

#### 触发时机

- `POST /api/tasks` 成功后,执行器进入 `running` 并发起首轮 LLM 调用。
- `need_more_context=true` 时,执行"补充检索 -> 再次调用 LLM"。
- `need_more_context=false` 且 `requires_patch=true` 时,生成变更提案并转 `waiting_confirm`。
- `confirm` 阶段只做预检与写盘,不再调用 LLM。

#### 请求契约(输入)

```json
{
  "model": "gpt-4.1",
  "temperature": 0.2,
  "max_output_tokens": 4096,
  "stream": true,
  "messages": [
    {"role":"system","content":"Output strictly in JSON schema."},
    {"role":"developer","content":"Follow workspace safety and patch rules."},
    {
      "role":"developer",
      "content":"Use retrieved context first. {\"retrieval_context\":[{\"path\":\"...\",\"start_line\":10,\"end_line\":26,\"snippet\":\"...\"}]}"
    },
    {"role":"user","content":"...user instruction..."}
  ],
  "response_format":{"type":"json_schema","json_schema":"agent_loop_v1"}
}
```

输入约束:
- `messages` 按"系统 -> 开发规则 -> 开发上下文包 -> 用户问题"顺序组装。
- `retrieval_context` 仅传增量片段,禁止全仓全文。
- 检索执行顺序为"先路径候选(文件名)-> 再按需读取片段(文件内容)-> 再注入 LLM"。
- 每轮必须带上上一轮检索增量与预算信息(便于模型收敛)。

推荐检索管线(Claude Code 风格):
1. Query 解析:提取 `query_terms / symbol_hints / path_hints`。
2. 候选召回:优先命中路径与文件名;不足时再走内容关键词/语义召回。
3. 混合打分:综合路径、符号、内容命中得分生成候选排名。
4. 多样性重排:限制同目录/同后缀过度集中,提升上下文覆盖面。
5. 片段抽取:围绕命中点截取最小可理解代码片段(非整文件)。
6. 预算裁剪:按预算(字符/token)裁剪,保留最相关证据并注入 `retrieval_context`。

#### 响应契约(显式信号)

```json
{
  "intent_type": "analysis_only",
  "requires_patch": false,
  "intent_confidence": 0.93,
  "intent_reason": "用户在做代码分析,无修改诉求。",
  "need_more_context": false,
  "missing_context_hints": [],
  "next_search_queries": [],
  "analysis_summary": "...",
  "evidence": [{"path":"...","snippet":"..."}],
  "limitations": [],
  "patch_plan": [],
  "final_changes": []
}
```

字段语义:
- `intent_type`:`analysis_only | code_change | unclear`
- `requires_patch`:是否允许进入改动流
- `need_more_context`:是否继续检索补充
- `next_search_queries`:下一轮检索查询(当 `need_more_context=true` 必填)
- `final_changes`:最终改动集合(仅 `requires_patch=true` 且信息充足时允许非空)

`final_changes` 单条结构(关键):

```json
{
  "change_id": "chg_xxx",
  "file_path": "src/main/java/com/zoom/contactcenter/service/controller/web/UserController.java",
  "operation": "patch",
  "old_hash": "",
  "new_content": "",
  "diff_unified": "diff --git ...",
  "reason": "rename method from updateUserStatus to updateUserStatus1",
  "risk_level": "medium"
}
```

约束:
- `operation=patch`:`diff_unified` 必填,`new_content` 可为空。
- `operation in {update,create}`:`new_content` 必填且非空,`diff_unified` 可选(用于展示)。
- 为兼容存储模型,`task_changes.new_content` 在 patch 场景可存放 `diff_unified` 文本副本。

#### LLM 网关交互入参与响应(内部接口)

> 该接口是后端到模型网关的内部协议,不直接暴露给前端,但必须在设计文档明确,便于联调与错误定位。

请求体(`POST {OPENAI_BASE_URL}/chat/completions`):

```json
{
  "model": "gpt-5.4",
  "temperature": 0.2,
  "max_completion_tokens": 4096,
  "messages": [
    {"role":"system","content":"Output strictly in JSON schema."},
    {"role":"developer","content":"Return required keys only."},
    {"role":"developer","content":"{\"retrieval_context\":[{\"path\":\"app/services/task_service.py\",\"start_line\":60,\"end_line\":90,\"snippet\":\"...\"}]}"},
    {"role":"user","content":"重命名 updateUserStatus 到 updateUserStatus1"}
  ]
}
```

响应体:

```json
{
  "id": "chatcmpl_xxx",
  "choices": [
    {
      "message": {
        "content": "{\"intent_type\":\"code_change\",\"requires_patch\":true,\"need_more_context\":false,\"analysis_summary\":\"...\",\"final_changes\":[{\"change_id\":\"chg_1\",\"file_path\":\"src/main/java/com/zoom/contactcenter/service/controller/web/UserController.java\",\"operation\":\"patch\",\"old_hash\":\"\",\"new_content\":\"\",\"diff_unified\":\"diff --git ...\",\"reason\":\"...\",\"risk_level\":\"medium\"}]}"
      }
    }
  ]
}
```

解析要求:
- 从 `choices[0].message.content` 取 JSON 字符串并反序列化。
- 若返回 markdown code fence,需要先去掉 fence 再解析 JSON。
- 非契约结构触发一次"契约修复重试";仍失败则降级为 `analysis_only`。

#### 决策网关(统一路由)

1. `intent_type=unclear` 或 `intent_confidence < 0.6`  
   -> 直接结束为 `done`(返回澄清建议文本)
2. `requires_patch=false`  
   -> Analysis Pipeline(输出 `analysis_summary/evidence/limitations`,任务 `done`)
3. `requires_patch=true` 且 `need_more_context=true`  
   -> 进入补充检索轮次(`phase=retrieve_more`)
4. `requires_patch=true` 且 `need_more_context=false`  
   -> Patch Pipeline(保存 `final_changes`,发 `diff`,任务 `waiting_confirm`)

安全兜底:
- 未显式 `requires_patch=true` 时禁止进入写盘链路。
- `final_changes` 为空时禁止进入 `waiting_confirm`。
- 若模型声明 `need_more_context=true` 但未提供 `next_search_queries`,必须终止补充轮次并记录限制原因。

### 2.4 V1 异常处理边界(MVP 口径)

- V1 仅保留主链路必需校验与错误透传,不引入"自动降级成功"的兜底分支。
- 禁止因 `OPENAI_API_KEY` 未配置而自动回退本地 mock 结果;配置缺失应直接失败并暴露真实错误。
- 禁止对网关错误/网络错误做"吞异常 + 自动改写为成功态"的处理;应保留失败态用于联调定位。
- 禁止在任务主执行链路外围增加大范围 `try/except` 兜底(仅允许最小边界的资源清理场景)。
- 网关重试、离线兜底、降级策略留待 V2 再引入,V1 不作为默认实现。

#### Agent Loop(伪代码)

```python
round_idx = 0
context_budget = MAX_TOTAL_CONTEXT_TOKENS
context_delta = initial_retrieval(instruction)

while round_idx < MAX_CONTEXT_ROUNDS:
    llm_resp = call_llm(compose_messages(instruction, context_delta, context_budget))
    validate_schema(llm_resp)

    if llm_resp["intent_type"] == "unclear" or llm_resp["intent_confidence"] < 0.6:
        emit_clarification(llm_resp["intent_reason"])
        update_task_status("done")
        break

    if llm_resp["requires_patch"] is False:
        emit_analysis_answer(
            llm_resp["analysis_summary"],
            llm_resp.get("evidence", []),
            llm_resp.get("limitations", [])
        )
        update_task_status("done")
        break

    if llm_resp["need_more_context"] is False:
        changes = llm_resp["final_changes"]
        if not changes:
            fail_task(code=2002, message="empty final_changes for patch flow")
            break
        save_task_changes(changes)
        emit_status(phase="patch_planning")
        emit_diff_events(changes)
        update_task_status("waiting_confirm")
        break

    emit_status(phase="retrieve_more")
    context_delta = incremental_retrieval(llm_resp["next_search_queries"])
    context_budget -= count_tokens(context_delta)
    round_idx += 1

    if empty(context_delta) or context_budget <= 0:
        fail_task(code=2003, message="context budget exceeded")
        break
else:
    fail_task(code=2003, message="max context rounds exceeded")
```

#### 交互流程图

```mermaid
flowchart TD
    A[POST /api/tasks] --> B[Task running]
    B --> C[Initial retrieval]
    C --> D[Call LLM by schema]
    D --> E{intent clear?}
    E -->|No| F[Task done with clarification]
    E -->|Yes| G{requires_patch?}
    G -->|No| H[analysis_summary + evidence]
    H --> I[Task done]
    G -->|Yes| J{need_more_context?}
    J -->|Yes| K[incremental retrieval]
    K --> L{budget/round ok?}
    L -->|Yes| D
    L -->|No| M[Task failed code=2003]
    J -->|No| N[Persist final_changes]
    N --> O[Emit diff]
    O --> P[Task waiting_confirm]
    P --> Q[POST confirm]
    Q --> R[Precheck + apply]
    R --> S[Task done]
```

## 3. 任务状态机

- 主链路:`running -> waiting_confirm -> done`
- 失败链路:`running -> failed`
- 取消链路:`running/waiting_confirm -> cancelled`
- 分析链路:`running -> done`

约束:
- `waiting_confirm` 前必须有至少一条 `diff`。
- `confirm` 时校验文件 `old_hash` 防冲突。
- `confirm` 时按操作类型校验载荷:`update/create` 需要 `new_content`,`patch` 需要 `diff_unified`。
- `running` 允许内部多轮 `retrieve_more`,对外仅暴露关键状态。
- `done` 可由分析链路直接到达,不要求存在 `diff`。

### 3.2 设计约束分级(防止"文档有、实现无")

- `MUST`:必须落地到代码与测试(如状态机约束、写盘安全、循环退出条件)。
- `SHOULD`:默认应实现;若不实现需在评审记录中说明原因与计划。
- `MAY`:可选增强项,不作为当前验收阻塞条件。

落地检查清单(每次改动前后各检查一次):
1. 约束是否标记级别(MUST/SHOULD/MAY)。
2. MUST 是否已有代码实现。
3. MUST 是否有自动化测试覆盖。
4. 若 SHOULD 未实现,是否在评审记录中显式标注原因与计划。

### 3.3 后端落地对照表

| 设计约束 | 级别 | 测试/验证 | 评审要点 |
|---|---|---|---|
| `run_agent_loop` 支持多轮检索 loop | MUST | 单测:loop 收敛与退出条件 | 验证 `need_more_context` 驱动行为 |
| `max_context_rounds` 防无限循环 | MUST | 配置测试 + 单测 | 超限后返回 `2003` |
| `need_more_context=true` 且无 query 时终止 | MUST | 单测:缺失 query 断言 | 输出可解释限制原因 |
| `waiting_confirm` 前必须已有 diff | MUST | 集成测试:patch 流程 | 无 diff 禁止进入确认态 |
| `confirm` 校验 `old_hash` 冲突 | MUST | 集成测试:冲突写入 | 冲突返回 `3001` |
| `confirm` 双模式校验(`new_content`/`diff_unified`) | MUST | 单元/集成测试:update 与 patch 两种路径 | 按 operation 执行参数校验 |
| 前端确认按钮空选择置灰 | MUST | E2E:空选择提交 | 防止空 apply 请求 |
| Key缺失/网关/网络异常默认透传(不降级mock、不吞异常) | MUST | 集成测试:配置缺失与网关失败场景 | V1 严格失败快返,保留真实错误 |

### 3.1 `tasks` 与 `task_changes` 职责边界

- `tasks`:任务主表(一条记录代表一次用户指令执行),存放任务级元数据与总体状态,如 `instruction/status/summary`。
- `task_changes`:任务子表(一条记录代表一个文件变更提案),存放文件级改动明细,如 `file_path/operation/old_hash/new_content`(patch 模式下可存 diff 副本)。

关系说明:
- 一个 `task` 可以对应 0..N 条 `task_changes`。
- `tasks` 用于任务管理与列表查询;`task_changes` 用于 diff 展示、选择性确认和冲突校验。

## 4. 持久化设计

### 4.1 MySQL(长期)

核心表:
- `users`
- `workspaces`
- `tasks`
- `task_changes`

MySQL 8.0 建表示例(可直接执行):

```sql
CREATE TABLE IF NOT EXISTS users (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id VARCHAR(64) NOT NULL UNIQUE,
  username VARCHAR(64) NOT NULL UNIQUE,
  password_hash VARCHAR(255) NOT NULL,
  display_name VARCHAR(128) NOT NULL,
  status VARCHAR(16) NOT NULL DEFAULT 'active',
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS workspaces (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  workspace_id VARCHAR(64) NOT NULL UNIQUE,
  user_id VARCHAR(64) NOT NULL,
  workspace_path VARCHAR(1024) NOT NULL,
  readonly TINYINT(1) NOT NULL DEFAULT 0,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_workspaces_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS tasks (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  task_id VARCHAR(64) NOT NULL UNIQUE,
  user_id VARCHAR(64) NOT NULL,
  workspace_id VARCHAR(64) NOT NULL,
  instruction TEXT NOT NULL,
  status VARCHAR(32) NOT NULL,
  summary TEXT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_tasks_workspace_status (workspace_id, status),
  INDEX idx_tasks_user_created (user_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS task_changes (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  change_id VARCHAR(64) NOT NULL,
  task_id VARCHAR(64) NOT NULL,
  file_path VARCHAR(1024) NOT NULL,
  operation VARCHAR(16) NOT NULL,
  old_hash VARCHAR(128) NULL,
  new_content LONGTEXT NOT NULL,
  reason TEXT NULL,
  risk_level VARCHAR(16) NOT NULL DEFAULT 'low',
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_changes_task_id (task_id),
  INDEX idx_changes_task_change (task_id, change_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

`task_changes` 约束说明:
- `change_id` 仅作为任务内变更标识,不作为跨任务幂等键。
- 禁止对 `change_id` 建全局唯一索引,避免重复任务提交时触发 `Duplicate entry`。
- 若需要查重,按 `task_id + change_id` 维度处理,不影响不同任务复用同名变更。

状态字段约束建议:
- `users.status` 只允许:`active/disabled`
- `tasks.status` 只允许:`running/waiting_confirm/done/failed/cancelled`
- `task_changes.operation` 只允许:`create/update/delete/patch`

### 4.2 Redis(短期与会话)

Redis 详细设计(key、结构、TTL):

| Key | Type | TTL | 示例值 | 用途 |
|---|---|---:|---|---|
| `agent:task:{task_id}:status` | String | 24h | `running` | 任务实时状态 |
| `agent:task:{task_id}:stream` | List | 30min | token/event 序列 | 断线重连后回放 |
| `agent:task:{task_id}:diff_ids` | Set | 24h | `chg_1,chg_2` | 任务内变更集合(仅当前 task) |
| `agent:ws:{connection_id}` | Hash | 2h | `{"task_id":"task_123","user_id":"u_1"}` | WS 连接上下文 |
| `agent:user:{user_id}:active_task` | String | 24h | `task_123` | 用户当前活跃任务 |
| `agent:conv:{conversation_id}:messages` | List | 7d | `{"role":"user","content":"...","ts":1716370000}` | 对话消息存储(替代 MySQL) |
| `agent:conv:{conversation_id}:meta` | Hash | 7d | `{"user_id":"u_1","workspace_id":"ws_1"}` | 会话元信息 |

建议实现:
- 写 `stream` 时使用 `LPUSH + LTRIM` 限制长度(如保留最近 2000 条事件)。
- `conversation messages` 使用 `RPUSH + EXPIRE`,并通过 `LTRIM` 控制最大消息数(如 500 条)。

Redis 规范建议:
- key 前缀统一为 `agent:`,避免与其他业务冲突。
- TTL 由场景驱动:会话 7d、流缓存 30min。
- 复杂对象统一 JSON 字符串,字段使用小写下划线命名。
- 每个写操作必须定义过期时间,防止无界增长。
- Redis 不作为 `change_id` 的跨任务幂等存储;`diff_ids` 仅用于当前 `task_id` 的会话态展示与确认辅助。

## 5. 错误码

- `0`:成功
- `1001`:工作区不存在或不可访问
- `1002`:工作区越权访问
- `2001`:模型调用失败
- `2002`:模型输出格式不合法
- `2003`:上下文不足(达到补充轮次或 token 预算上限)
- `3001`:写入冲突
- `3002`:写入失败
- `9000`:未知系统异常

错误响应示例:

```json
{
  "code": 2003,
  "message": "context budget exceeded",
  "data": {
    "task_id": "task_123",
    "phase": "retrieve_more",
    "max_context_rounds": 5
  }
}
```

登录失败示例:

```json
{
  "code": 1101,
  "message": "invalid username or password",
  "data": {
    "task_id": null
  }
}
```

## 6. 配置规范(config.py)

使用环境变量,不在代码中硬编码敏感信息。至少支持:

- `APP_HOST`
- `APP_PORT`
- `APP_RELOAD`
- `OPENAI_BASE_URL`(兼容内部 LLM gateway,例如 `https://api.openai.com/v1`)
- `MODEL_NAME`
- `OPENAI_API_KEY`
- `MAX_TOTAL_CONTEXT_CHARS`(单轮注入上下文预算,默认建议 9000)
- `REDIS_HOST/PORT/PASSWORD/DB`
- `MYSQL_HOST/PORT/DB/USER/PASSWORD`

示例环境映射(本地联调):
- LLM gateway:
  - `OPENAI_BASE_URL=https://api.openai.com/v1`
  - `MODEL_NAME=gpt-5.4`
- Redis:
  - `REDIS_HOST=localhost`
  - `REDIS_PORT=6379`
  - `REDIS_PASSWORD=`(空)
- MySQL(由 JDBC URL `jdbc:mysql://localhost:3308/agent_demo?...` 拆分):
  - `MYSQL_HOST=localhost`
  - `MYSQL_PORT=3308`
  - `MYSQL_DB=agent_demo`
  - `MYSQL_USER=root`
  - `MYSQL_PASSWORD=<local_secret>`

## 7. 测试要求

- 单元测试:路径校验、diff 生成、状态机、错误码映射
- 集成测试:`select -> create -> stream -> confirm -> apply`
- 回归测试:冲突写入、取消任务、服务重启恢复

## 8. 运维与发布基线

- 启动前校验关键配置:`APP_PORT`、模型配置、Redis/MySQL 连接。
- 生产环境关闭 debug/reload,配置请求超时与并发上限。
- 对外发布前至少完成一轮端到端联调(含 `2003` 与 `3001` 异常场景)。


### 8.1 关键日志(排障基线)

建议在以下关键步骤打印 INFO/WARNING/ERROR 日志,并统一携带 `task_id/user_id/workspace_id`(如可用):
- 登录与工作区选择:`login attempt/success/fail`、`workspace select`。
- 任务生命周期:`create task`、`task started`、`task waiting_confirm`、`task cancelled`、`task failed`。
- LLM 调用:调用开始、调用完成(包含 `requires_patch` 判定)、异常堆栈。
- 检索命中:记录 `filename_hints`、`direct_hit_count`、`direct_hit_paths`(截断展示)以便定位"仅文件名检索"问题。
- Confirm/Cancel:确认入参、冲突命中(`3001`)、写入成功文件数、取消原因。
- WS 连接:连接建立与断开事件。

### 8.2 取消任务执行约束

- 前端触发 `POST /api/tasks/{task_id}/cancel` 后,后端需将任务置为 `cancelled` 并释放工作区锁。
- 任务执行器在关键阶段(LLM 调用前后、写入前)需检查任务是否已取消;若已取消,停止后续流程并避免覆盖状态。

前端

复制代码
# Code Agent 前端设计

## 1. 目标与范围

- 提供可视化交互入口:任务输入、流式输出、diff 预览、确认落盘。
- 状态展示与后端保持一致,不做业务推断。
- 支持深浅主题,优先深色工程风格。
- 支持账号登录后进入工作区与对话主界面。

## 2. 页面与交互流程

1. 登录页  
- 输入 `username/password`,调用登录接口校验身份。  
- 登录成功后进入工作区页;失败时展示错误提示。

2. 工作区选择页  
- 展示用户可访问工作区列表(支持搜索)。  
- 登录成功后若后端返回 `latest_workspace`,默认回填最近一次工作区路径与只读状态。  
- 用户确认后进入 Agent 主界面。

3. Agent 主界面  
- 左侧工作区树(窄栏)  
- 中央 Chat 主区域(主要交互区域)  
- 右侧可折叠详情区(任务状态、diff 预览、确认栏)

4. 改动确认流程  
- 当任务进入 `waiting_confirm`,展示变更文件列表与 diff。  
- 用户可选择变更后点击"确认修改"触发 apply。

5. 任务终止流程
- 在输入区提供"终止"按钮(Stop)。
- 当任务处于 `submitting/streaming/waiting_confirm` 时可点击终止。
- 前端调用 `POST /api/tasks/{task_id}/cancel`,成功后将页面状态置为 `cancelled` 并停止当前流式连接。
- 终止后建议在消息区追加系统提示(如"任务已终止"),避免用户误判为网络断开。

## 3. 布局规格(强调 Chat 主体)

- 顶部栏:56px(应用名、登录用户、当前工作区、连接状态)。
- 左侧工作区树:默认 220px,最小 180px,最大 260px(不能占用过多宽度)。
- 中央 Chat 区:占内容区至少 65% 宽度,优先保证消息阅读和输入体验。
- 右侧详情区:默认 320px,可折叠到 0;在 `waiting_confirm` 时自动展开。
- 底部输入区:固定在 Chat 区底部,包含发送、停止、清空按钮。

## 4. 视觉规范

- Primary:`#3B82F6`
- Success:`#22C55E`
- Warning:`#F59E0B`
- Error:`#EF4444`
- 代码字体:`Consolas, Menlo, monospace`
- 卡片:圆角 8px + 轻阴影

## 5. 状态模型与步骤提示

- `idle`
- `submitting`
- `streaming`
- `waiting_confirm`
- `applying`
- `done`
- `error`
- `cancelled`

交互约束:
- `submitting/streaming/applying` 时禁用发送按钮
- `submitting/streaming/waiting_confirm` 时允许终止按钮
- `waiting_confirm` 默认不全选变更
- "确认修改"按钮在 `selected_changes` 为空时置灰(至少勾选 1 条 diff 才可提交)
- `error` 态展示 `error_code + message + retry_action`
- 工作区选择页优先展示 `latest_workspace`(如存在),用户可手工覆盖后再提交。
- `streaming` 阶段展示关键状态为 `running`,无需展示细粒度 phase
- 当后端返回澄清建议时,当前任务按 `done` 结束,前端展示建议并引导用户发起新任务补充信息

步骤提示组件(建议固定在 Chat 顶部):
- 当前步骤:`retrieval -> analysis -> retrieve_more -> patch_planning -> waiting_confirm/applying`
- 每步显示状态(进行中/完成/失败)与耗时
- 当步骤停留过久(如 >30s)显示"处理中,请稍候"文案

## 6. 接口映射

### 6.1 REST

- 登录:`POST /api/auth/login`
- 选择工作区:`POST /api/workspace/select`
- 创建任务:`POST /api/tasks`
- 轮询详情:`GET /api/tasks/{task_id}`
- 确认修改:`POST /api/tasks/{task_id}/confirm`
- 取消任务:`POST /api/tasks/{task_id}/cancel`

### 6.2 WebSocket

- 连接:`/ws/tasks/{task_id}/stream`
- 事件:`token/status/diff/error/done`
- `status` 事件仅使用 `payload.status` 驱动状态展示,不由前端自行推断细粒度阶段

## 7. 组件建议

- `LoginForm`
- `WorkspaceSelector`
- `WorkspaceTree`
- `TaskInput`
- `TaskTimeline`
- `StreamOutputPanel`
- `DiffFileTree`
- `DiffViewer`
- `ConfirmBar`
- `StatusBadge`
- `PhaseStepper`

## 8. E2E 用例

- 登录链路:登录成功进入工作区;登录失败提示错误
- 选区链路:选择工作区后加载目录树与历史任务
- 正常链路:提交任务 -> 收到流式输出 -> 展示 diff -> 确认落盘
- 异常链路:模型失败 -> 错误提示 -> 重试
- 冲突链路:确认时后端返回 `3001` -> 提示重新生成
- 信息不足链路:收到 `2003` 后展示可操作建议

代码

生成的propmt

你是资深全栈工程师。请严格依据我项目中的设计文档生成"可运行代码骨架 + 核心实现"。

【文档来源】

  • design/需求设计文档.md

  • design/后端设计.md

  • design/前端设计.md

【总体要求】

  1. 先完整阅读以上3个文档,再开始实现。

  2. 实现必须与文档一致;若发现冲突,按优先级处理:

  • 后端实现细节以 design/后端设计.md 为准

  • 前端实现细节以 design/前端设计.md 为准

  • 范围与原则以 design/需求设计文档.md 为准

  1. 不要擅自增加文档未要求的复杂能力。

  2. 先生成最小可运行版本(MVP),保证主链路可跑通。

【你需要完成的内容】

A. 后端(Python/FastAPI)

  • 按文档目录创建后端骨架(当前约定的精简结构)

  • 实现接口:

  • POST /api/auth/login

  • POST /api/workspace/select

  • POST /api/tasks

  • GET /api/tasks/{task_id}

  • POST /api/tasks/{task_id}/confirm

  • POST /api/tasks/{task_id}/cancel

  • 实现 WebSocket:/ws/tasks/{task_id}/stream

  • 实现任务状态机与phase机制

  • 实现 llm_client + tool_registry 的最小可用版本

  • 实现 MySQL/Redis 基础读写

  • 提供 config(含 APP_PORT、MySQL、Redis、模型配置,环境变量读取)

B. 前端(按文档交互)

  • 登录页(username/password)

  • 工作区选择页

  • Agent 主界面(窄工作区树 + chat主区域 + 右侧可折叠详情)

  • Chat步骤提示(status.phase)

  • diff确认交互(waiting_confirm)

C. 运行与验证

  • 给出启动方式(后端/前端)

  • 给出最小初始化步骤(如 users 表初始化一条账号)

  • 跑一条主链路自检:登录 -> 选工作区 -> 发消息 -> 返回分析或diff -> 确认

【输出格式要求】

  1. 先输出"实现计划(分步骤)"。

  2. 然后逐步执行并直接修改代码。

  3. 每一步说明改了哪些文件、为什么这么改。

  4. 最后输出:

  • 变更文件清单

  • 启动命令

  • 验证步骤

  • 已知限制(如MVP暂未覆盖项)

我们订阅的cursor是按request次数收费的:这次请求总共花费231万 token,对比按token计费划算很多

下面来看下代码。

相关推荐
桦说编程5 分钟前
我让 AI 加了一个开关,结果代码走了原本不该走的分支
人工智能·代码规范
fly spider6 分钟前
AI 到底是怎么访问网页的?从爬虫、Browser Agent 到 Computer Use
人工智能·爬虫
Lee川38 分钟前
RAG 实战:从一篇掘金文章出发,拆解检索增强生成的全链路
前端·人工智能·后端
码农小旋风42 分钟前
Codex小白入门使用教程
人工智能·chatgpt·claude
Lee川1 小时前
MCP 高德地图实战:当 AI 学会使用工具,一个协议如何重塑大模型的行动边界
前端·人工智能·后端
凌杰1 小时前
AI 学习笔记:Agent 的应用演示
人工智能
程序员cxuan1 小时前
Codex 把我家烂网给优化后,我 TM 直接原地起飞了。
人工智能·后端·程序员
IT_陈寒1 小时前
Redis批量删除踩了坑,原来DEL命令不是万能的
前端·人工智能·后端
xinhuanjieyi1 小时前
gpt-sovits测试语音克隆
人工智能·gpt
星辰AI1 小时前
Transformers 架构核心原理:从注意力机制到 GPT
人工智能·ai·语言模型