namespace Dpz.Core.Infrastructure;
/// <summary>
/// AI 代码分析进度阶段
/// </summary>
public static class CodeAnalyzeStage
{
/// <summary>
/// 开始分析
/// </summary>
public const int Started = 0;
/// <summary>
/// 工具轮次/阶段进度行
/// </summary>
public const int Tool = 1;
/// <summary>
/// 流式内容增量
/// </summary>
public const int Content = 2;
/// <summary>
/// 分析完成
/// </summary>
public const int Completed = 3;
/// <summary>
/// 分析失败或中止
/// </summary>
public const int Failed = 4;
}
/// <summary>
/// AI 代码分析实时进度消息(Jobs → Web hub → 浏览器)
/// </summary>
public sealed record CodeAnalyzeProgressMessage
{
/// <summary>
/// 文件相对路径(含文件名,如 dir/Foo.cs),与代码浏览页面路由一致,用于浏览器按页过滤
/// </summary>
public string FileKey { get; set; } = "";
/// <summary>
/// 阶段,取值见 <see cref="CodeAnalyzeStage"/>
/// </summary>
public int Stage { get; set; }
/// <summary>
/// 阶段文本(阶段 0/1/3/4 时使用)
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 内容增量(阶段 2 时使用,客户端拼接后实时渲染)
/// </summary>
public string? Content { get; set; }
}
该文件位于 Dpz.Core.Infrastructure 项目(系统公共基础设施组件库)根目录下,是一个纯粹的数据契约定义文件:它不包含任何业务逻辑或执行流程,仅声明了 AI 代码分析功能在前后端之间传递的"进度消息协议"。整个文件由两个类型组成。
1. CodeAnalyzeStage —— 进度阶段常量
一个 public static class,用 const int 定义了 AI 分析生命周期的 5 个阶段,作为消息协议中 Stage 字段的取值约定:
| 常量 | 值 | 含义 | 对应的消息内容 |
|---|---|---|---|
Started | 0 | 开始分析 | Message 文本 |
Tool | 1 | MCP 工具轮次/阶段进度行 | Message 文本 |
Content | 2 | 流式内容增量 | Content 增量片段 |
Completed | 3 | 分析完成 | Message 文本 |
Failed | 4 | 失败或中止 | Message 文本 |
阶段 0/1/3/4 携带文本状态,阶段 2 携带需要客户端拼接后实时渲染的内容增量。
2. CodeAnalyzeProgressMessage —— 进度消息载体
一个 sealed record,作为跨进程、跨端传输的 DTO:
FileKey:文件相对路径(含文件名,如dir/Foo.cs)。设计上刻意与代码浏览页面的路由保持一致,作用是让浏览器端只处理与"当前正在浏览的文件"相关的推送,避免不同文件的分析进度互相干扰。Stage:阶段编号,取值与CodeAnalyzeStage对应。Message:阶段说明文本。Content:流式 Markdown 内容增量,仅阶段 2 使用。
与相关文件的协作关系(已通过工具确认)
该消息被夹在"Jobs 后端处理进程 → Web 服务 SignalR Hub → 浏览器"的三段推送链路中,链路如下:
flowchart LR
A[AnalyzeCodeHandler.cs<br/>Web.Jobs 消息处理器] -->|构造 CodeAnalyzeProgressMessage| B[PushMessage.cs<br/>Jobs→Hub 的 SignalR Client]
B -->|Invoke 方法 PushCodeAnalyzeProgress| C[Notification.cs<br/>Web 端 Hub]
C -->|广播事件 codeAnalyzeProgress| D[CodeAiLive.ts<br/>浏览器]
D -->|按 FileKey 过滤| E[渲染实时进度/流式 Markdown]
各协作点详述:
生产端 AnalyzeCodeHandler.cs(
Dpz.Core.Web.Jobs中的后台任务处理器):在调用 OpenAI 流式接口时,通过私有方法PushProgressStageAsync(阶段消息,stage 取CodeAnalyzeStage.Started/Tool/Completed/Failed)和PushContentDeltaAsync/FlushContentAsync(流式增量,stage 取CodeAnalyzeStage.Content,约 100ms 节流合并后批量推送)构造消息。其中PushToolCallAsync会把 MCP 工具调用翻译成中文进度说明再以 Tool 阶段发出。这些方法都通过IPushMessage注入的pushMessage转发。中转端 PushMessage.cs:Jobs 进程内维护到 Web 端
/notificationHub 的 SignalR 长连接,PushCodeAnalyzeProgressAsync调用远程 Hub 方法PushCodeAnalyzeProgress把整条消息原样转发。Web 端 Hub Notification.cs:
PushCodeAnalyzeProgress方法通过Clients.All.SendCoreAsync("codeAnalyzeProgress", [message])向所有浏览器广播。消费端 CodeAiLive.ts:订阅事件后,用本地常量
STAGE_STARTED/TOOL/CONTENT/COMPLETED/FAILED(与后端CodeAnalyzeStage逐一对齐)做switch分发;先比对region.dataset.fileKey === payload.fileKey决定是否处理,再按阶段驱动日志行追加、Markdown 增量缓冲渲染(约 120ms 节流)以及完成/失败时的清理与静态结果恢复。
值得注意的是,TS 侧的阶段常量是在 CodeAiLive.ts 中手工复刻的(注释标明"与后端 CodeAnalyzeStage 对应"),本 C# 文件并未通过序列化等方式直接暴露给前端;两端约定完全依赖"数值一致"这一默契。
小结
这是一个职责单一、零依赖的跨进程消息协议定义:CodeAnalyzeStage 是协议取值词典,CodeAnalyzeProgressMessage 是协议报文。它本身不参与任何处理逻辑,作用是在 Jobs 的 AI 分析处理器与 Web 端浏览器之间,为"代码浏览页面上实时展示 AI 分析进度与流式结果"这一功能建立统一的传输格式,由同一项目下的 MessageQueue/Hub/前端脚本共同消费。