log-center/docs/project-management-repair-plan.md
zyc 625e53dc44
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 2m16s
feat(project-mgmt): 项目管理 + 失败原因追踪 + 前端展示
- 新增 Project 模型(repo_url, local_path, name, description)
- 项目 CRUD API(GET/PUT /api/v1/projects)
- 日志上报自动 upsert Project 记录
- ErrorLog 增加 failure_reason 字段
- update_task_status / create_repair_report 写入失败原因
- Repair Agent 优先从 API 获取项目配置,回退 .env
- 新增 Web 端「项目管理」页面(表格 + 行内编辑)
- BugList/BugDetail/RepairList 展示失败原因
- 更新接入指南文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 11:18:27 +08:00

10 KiB
Raw Permalink Blame History

Log Center 改进方案:项目管理 + 修复失败追踪

背景

Log Center 当前存在三个核心问题:

  1. Repair Agent 无法识别项目仓库和本地路径 — 仓库地址(repo_url)和本地项目路径(local_path)都硬编码在 repair_agent/.env,需手动配置,且当前全部为空。应在接入日志收集时自动注册项目信息,并可在 Web 端统一管理。
  2. 修复失败原因未上报ErrorLog 表没有 failure_reason 字段;update_task_status API 接收了 message 参数但直接丢弃(main.py:113upload_report 失败时原因静默丢失。
  3. 前端未展示失败原因 — BugList / BugDetail 页面无法看到修复失败的具体原因,用户必须逐一查看 RepairTask 记录才能找到。

第一部分:项目管理(仓库地址 + 本地路径 + Web 管理页)

1.1 新增 Project 数据模型

文件: app/models.py

class Project(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    project_id: str = Field(unique=True, index=True)    # "rtc_backend"
    name: Optional[str] = Field(default=None)            # 显示名称
    repo_url: Optional[str] = Field(default=None)        # GitHub/Gitea 仓库地址
    local_path: Optional[str] = Field(default=None)      # 本地项目路径Agent 修复时使用)
    description: Optional[str] = Field(default=None)     # 项目描述
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

新增 ProjectUpdate schema 用于编辑:

class ProjectUpdate(SQLModel):
    name: Optional[str] = None
    repo_url: Optional[str] = None
    local_path: Optional[str] = None
    description: Optional[str] = None

1.2 日志上报自动注册项目

文件: app/models.pyErrorLogCreate 增加字段

class ErrorLogCreate(SQLModel):
    # ... 现有字段 ...
    repo_url: Optional[str] = None  # 可选:上报时附带仓库地址

文件: app/main.pyreport_log() 增加 upsert 逻辑

收到日志上报时:

  1. 根据 project_id 查找 Project 记录
  2. 不存在 → 自动创建(project_id + repo_url
  3. 已存在且 repo_url 不为空 → 更新 repo_url

向后兼容:不传 repo_url 时仍正常创建 Project 记录(repo_url 为空),后续可在 Web 端手动补充。

1.3 项目管理 API

文件: app/main.py

端点 方法 用途
GET /api/v1/projects GET 项目列表(改造现有端点,从 Project 表查询,返回完整信息)
GET /api/v1/projects/{project_id} GET 获取单个项目详情(含 repo_url、local_path
PUT /api/v1/projects/{project_id} PUT 编辑项目信息repo_url、local_path、name、description

GET /api/v1/projects 响应示例

{
  "projects": [
    {
      "id": 1,
      "project_id": "rtc_backend",
      "name": "RTC 后端",
      "repo_url": "https://gitea.example.com/team/rtc_backend.git",
      "local_path": "/Users/maidong/Desktop/zyc/qy_gitlab/rtc_backend",
      "description": "Django 后端服务",
      "created_at": "2026-01-15T08:00:00",
      "updated_at": "2026-02-20T10:30:00"
    }
  ]
}

PUT /api/v1/projects/{project_id} 请求示例

{
  "name": "RTC 后端",
  "repo_url": "https://gitea.example.com/team/rtc_backend.git",
  "local_path": "/Users/maidong/Desktop/zyc/qy_gitlab/rtc_backend",
  "description": "Django 后端服务"
}

1.4 Repair Agent 适配

task_manager.py — 新增 get_project_info()

def get_project_info(self, project_id: str) -> Optional[dict]:
    """从 Log Center API 获取项目配置repo_url + local_path"""
    response = self.client.get(f"{self.base_url}/api/v1/projects/{project_id}")
    return response.json()  # { repo_url, local_path, ... }

core.py — 修改 fix_project()fix_single_bug()

优先级链:

  • local_pathAPI 返回值 → settings.get_project_path() (.env) → 报错退出
  • repo_urlAPI 返回值 → settings.get_github_repo() (.env) → 跳过 Git 操作
# 获取项目配置API 优先)
project_info = self.task_manager.get_project_info(project_id)

project_path = (project_info and project_info.get("local_path")) or settings.get_project_path(project_id)
github_repo = (project_info and project_info.get("repo_url")) or settings.get_github_repo(project_id)

1.5 Web 端项目管理页面

新增文件: web/src/pages/ProjectList.tsx

功能:

  • 表格展示所有项目project_id、名称、仓库地址、本地路径、描述、更新时间
  • 行内编辑:点击「编辑」按钮进入编辑模式,可修改所有可编辑字段
  • 状态指示:repo_url / local_path 为空时标红显示「未配置」
  • 移动端适配:卡片式布局

修改文件: web/src/App.tsx

  • 侧边栏新增「项目管理」入口(使用 FolderGit2 图标)
  • 路由新增 /projectsProjectList

修改文件: web/src/api.ts

export interface Project {
    id: number;
    project_id: string;
    name: string | null;
    repo_url: string | null;
    local_path: string | null;
    description: string | null;
    created_at: string;
    updated_at: string;
}

export const getProjectList = () =>
    api.get<{ projects: Project[] }>('/api/v1/projects');

export const getProjectDetail = (projectId: string) =>
    api.get<Project>(`/api/v1/projects/${projectId}`);

export const updateProject = (projectId: string, data: Partial<Project>) =>
    api.put(`/api/v1/projects/${projectId}`, data);

1.6 数据库变更

-- 新建 Project 表
CREATE TABLE project (
    id SERIAL PRIMARY KEY,
    project_id VARCHAR UNIQUE NOT NULL,
    name VARCHAR,
    repo_url VARCHAR,
    local_path VARCHAR,
    description VARCHAR,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);
CREATE UNIQUE INDEX ix_project_project_id ON project (project_id);

第二部分:修复失败原因录入数据库

2.1 ErrorLog 增加 failure_reason 字段

文件: app/models.py

class ErrorLog(SQLModel, table=True):
    # ... 现有字段 ...
    failure_reason: Optional[str] = Field(default=None, sa_column=Column(Text, nullable=True))

2.2 update_task_status API 存储 message

文件: app/main.pyupdate_task_status()

当前代码(第 113 行):

task.status = status_update.status
# We could log the message to a history table if needed  ← message 被丢弃了

修改为:

task.status = status_update.status
if status_update.message and status_update.status == LogStatus.FIX_FAILED:
    task.failure_reason = status_update.message

2.3 create_repair_report API 同步更新 ErrorLog

文件: app/main.pycreate_repair_report()

当前仅在 FIXED / FIX_FAILED 时更新 ErrorLog 的 status。增加逻辑

if error_log:
    error_log.status = report.status
    if report.failure_reason and report.status == LogStatus.FIX_FAILED:
        error_log.failure_reason = report.failure_reason
    session.add(error_log)

2.4 数据库变更

ALTER TABLE errorlog ADD COLUMN failure_reason TEXT;

第三部分:前端展示失败原因

3.1 TypeScript 类型更新

文件: web/src/api.ts

export interface ErrorLog {
    // ... 现有字段 ...
    failure_reason: string | null;
}

3.2 BugList 页面

文件: web/src/pages/BugList.tsx

当 bug 状态为 FIX_FAILED 时,在状态列旁或下方显示 failure_reason 摘要(超长截断)。

3.3 BugDetail 页面

文件: web/src/pages/BugDetail.tsx

当状态为 FIX_FAILEDfailure_reason 不为空时,增加醒目的失败原因卡片:

{bug.failure_reason && (
    <div className="card" style={{ borderLeft: '3px solid var(--error)' }}>
        <h2><AlertTriangle size={16} /> 修复失败原因</h2>
        <pre className="code-block error">{bug.failure_reason}</pre>
    </div>
)}

3.4 RepairList 页面

文件: web/src/pages/RepairList.tsx

表格新增「失败原因」列,显示截断文本(text-overflow: ellipsis)。


文件变更清单

后端

文件 操作 说明
app/models.py 修改 新增 Project + ProjectUpdateErrorLog 增加 failure_reason
app/main.py 修改 项目 CRUD API修改 report_log / update_task_status / create_repair_report
app/database.py 修改 追加迁移 SQLProject 表 + failure_reason 列)
repair_agent/agent/task_manager.py 修改 新增 get_project_info()
repair_agent/agent/core.py 修改 fix_project / fix_single_bug 优先使用 API 配置

前端

文件 操作 说明
web/src/api.ts 修改 Project 类型 + API 函数ErrorLog 增加 failure_reason
web/src/App.tsx 修改 路由 + 侧边栏增加「项目管理」
web/src/pages/ProjectList.tsx 新增 项目列表 + 行内编辑
web/src/pages/BugList.tsx 修改 展示 failure_reason
web/src/pages/BugDetail.tsx 修改 突出展示 failure_reason
web/src/pages/RepairList.tsx 修改 增加失败原因列

实施顺序

  1. 后端模型 — 新增 Project 模型 + ErrorLog 增加 failure_reason + 数据库迁移
  2. 后端 API — 项目 CRUD + 修改 report_log / update_task_status / create_repair_report
  3. Repair Agent — task_manager 获取项目配置 + core.py 优先使用 API 配置
  4. 前端 API 层 — api.ts 类型和函数更新
  5. 前端页面 — ProjectList 新页面 + BugList / BugDetail / RepairList 展示 failure_reason
  6. 路由 / 侧边栏 — App.tsx 接入项目管理入口

验证方式

  1. 调用 POST /api/v1/logs/reportrepo_url → 检查 Project 表自动创建
  2. Web 端「项目管理」页 → 编辑 repo_url / local_path → 验证保存成功
  3. Repair Agent status 命令 → 验证读取到 API 配置的 repo_url + local_path
  4. 触发一次修复失败 → 检查 ErrorLog.failure_reason 已写入
  5. Web 端 BugList / BugDetail / RepairList → 确认失败原因正确展示