# 任务：Realtime Logs 数据流优化 (缓冲与回放) [已完成]

## 目标
解决前端 `Realtime Logs` 面板在页面刷新、重新连接或初始加载延迟时丢失日志的问题。
目标是确保 "First-hand" 服务端日志能够可靠地流向前端，不依赖 NATS 的临时性。

## 实施方案

### 1. 后端：增强 `SyncStateCommand` (Orchestrator)
我们需要修改 `handle_sync_state` 逻辑，使其在发送状态快照的同时，**也能读取当前的临时日志文件**，并将历史日志作为事件发送给前端。

*   **修改 `workflow.rs` -> `handle_sync_state`**:
    *   调用 `log_manager.read_current_logs(req_id)` (需要新增此方法，非破坏性读取)。
    *   读取到的日志内容可能是巨大的字符串。为了不阻塞 NATS 消息，可以分块发送，或者作为 `WorkflowStateSnapshot` 的一部分发送（如果大小允许）。
    *   **方案选择**: 发送一个新的事件类型 `WorkflowLogHistory` 或者复用 `TaskLog`（批量发送）。
    *   鉴于前端 `handleEvent` 处理 `TaskLog` 是追加式的，我们可以循环发送 `TaskLog` 事件。
    *   **更优方案**: 在 `WorkflowStateSnapshot` 结构体中增加 `logs: Vec<String>` 字段。这样前端在恢复快照时一次性填入。

### 2. 定义数据结构变更
*   **`common-contracts/src/messages.rs`**:
    *   修改 `WorkflowStateSnapshot`，增加 `logs: Vec<String>`。

### 3. 完善 `LogBufferManager`
*   **`logging.rs`**:
    *   新增 `read_current_logs(&self, request_id: &str) -> Result<Vec<String>>`。
    *   读取文件，按行分割，返回 `Vec<String>`。

### 4. 前端适配
*   **`useWorkflowStore.ts`**:
    *   在 `handleEvent` -> `WorkflowStateSnapshot` 分支中，处理 `event.payload.logs`。
    *   将这些日志合并到 `state.logs` (Global Logs) 或者解析后分发到 `state.tasks` (如果日志格式包含 Task ID)。
    *   目前日志格式为 `[ISO Time] [Level] Message`，不一定包含 Task ID，所以主要作为 Global Logs 展示。

### 5. 流程梳理
1.  **前端启动/刷新**: 
    *   调用 `SSE /events/{id}`。
    *   API Gateway 收到连接，订阅 NATS，并发送 `SyncStateCommand` 给 Orchestrator。
2.  **Orchestrator**:
    *   收到 `SyncStateCommand`。
    *   生成 DAG 快照。
    *   **读取 `temp_logs/{id}.log`**。
    *   构建 `WorkflowStateSnapshot` (包含 logs)。
    *   发布到 NATS。
3.  **前端接收**:
    *   收到 Snapshot。
    *   恢复 DAG 状态。
    *   恢复 Logs 面板内容。
4.  **后续实时日志**:
    *   Orchestrator 继续运行，Tracing Layer 写入文件。
    *   **关键点**: 我们之前删除了 `publish_log`。现在需要恢复**实时推送**能力，但不是手动调用。
    *   **方案**: `FileRequestLogLayer` 除了写文件，还应该有一个机制将日志推送到 NATS 吗？
    *   **回答**: 是的。之前的重构把推送删了，导致前端**收不到实时更新**了。
    *   **修正**: `FileRequestLogLayer` 应该同时负责：
        1.  写文件 (持久化缓冲)。
        2.  推送到 NATS (实时展示)。
    *   **技术难点**: Layer 是同步的，NATS 是异步的。
    *   **解决**: 使用 `tokio::sync::broadcast` 或 `mpsc` 通道。Layer 将日志发送到通道，有一个后台 Task 负责接收通道消息并推送到 NATS。

## 修正后的后端任务列表

1.  **恢复实时推送通道**:
    *   在 `AppState` 中增加一个 `log_broadcast_tx` (sender)。
    *   `FileRequestLogLayer` 持有这个 sender。
    *   在 `main.rs` 启动一个后台任务，监听 receiver，将日志封装为 `WorkflowEvent::TaskLog` 并推送到 NATS。
2.  **实现历史回放 (Snapshot)**:
    *   修改 `WorkflowStateSnapshot` 增加 `logs` 字段。
    *   `LogBufferManager` 增加读取方法。
    *   `handle_sync_state` 填充 logs。

## 前端任务列表
1.  更新 `WorkflowStateSnapshot` 类型定义。
2.  在 Store 中处理 Snapshot 携带的日志。

这个方案兼顾了实时性和可靠性（断线重连）。

