# OpenClaw Daily Report 方案

## 1. 目标

为 OpenClaw 增加一个“每日自动汇总上报”能力：

- 每天自动整理当天的对话与工作情况
- 通过文档中定义的 `POST /openclaw-daily-report` 接口上报云端
- 不影响现有聊天、心跳、配置同步等主流程
- 方案适合测试阶段快速验证，也适合正式环境长期运行

## 2. 对接的云端 API

使用 `docs/云端API接入文档.txt` 中定义的接口：

- `POST /openclaw-daily-report`

### 请求字段

- `api_key`
- `summary_date`
- `total_conversations`
- `total_messages`
- `total_tokens`
- `total_errors`
- `highlights`
- `issues`
- `raw_summary_text`
- `active_channels`

### 返回字段

- `ok`
- `summary_id`
- `employee_id`
- `summary_date`

## 3. 数据来源

日报内容从现有桌面端数据里生成，主要来源如下：

- `packages/gateway-client/src/index.ts`
  - 读取会话列表
  - 读取会话消息
- `apps/desktop/src/main/ipc.ts`
  - 现有聊天、会话、配置的主进程入口
- `apps/desktop/src/main/services/runtime-cloud-supervisor.ts`
  - 现有主进程定时器、云端状态、运行时 telemetry 的管理模式
- `apps/desktop/src/main/services/cloud-api.ts`
  - 云端请求封装与 `api_key` 读取方式
- `apps/desktop/src/main/services/diagnostics.ts`
  - 结构化报告的组织方式，可参考其输出风格

## 4. 总体设计

### 4.1 单独做成定时任务

日报能力不挂到聊天发送链路，也不挂到心跳或配置同步链路里，而是单独做成一个主进程侧服务，例如：

- `DailyReportService`

这个服务只做三件事：

1. 到点检查是否需要发送日报
2. 生成日报 payload
3. 调用 `/openclaw-daily-report`

### 4.2 为什么要独立出来

这样可以保证：

- 日报失败不会影响聊天
- 日报失败不会影响心跳
- 日报失败不会影响配置同步
- 日报逻辑更容易测试和维护

## 5. 报表内容设计

建议日报保持“简洁 + 有要点”，避免发送过长原文。

### 5.1 建议 payload 结构

```ts
interface OpenClawDailyReportPayload {
  api_key: string;
  summary_date: string;
  total_conversations: number;
  total_messages: number;
  total_tokens: number;
  total_errors: number;
  highlights: string[];
  issues: string[];
  raw_summary_text: string;
  active_channels: Array<{
    type: string;
    name: string;
  }>;
}
```

### 5.2 内容建议

- `summary_date`
  - 使用本地日期，格式 `YYYY-MM-DD`
- `total_conversations`
  - 当天会话数
- `total_messages`
  - 当天消息总数
- `total_tokens`
  - 如果当前链路能拿到 token，就统计累计值
- `total_errors`
  - 当天错误数
- `highlights`
  - 3~5 条关键摘要
- `issues`
  - 异常、失败、恢复情况
- `raw_summary_text`
  - 一段简短的人类可读总结
- `active_channels`
  - 当天活跃的渠道列表

## 6. 调度策略

### 6.1 独立调度器

建议在主进程里单独维护一个定时器：

- 采用 `setInterval`
- 每分钟检查一次当前时间
- 如果当前时间已经到设定时间，且今天还没发过，就发送一次

### 6.2 时间配置

时间做成可配置项，便于测试和正式环境切换。

建议使用环境变量：

- `DAILY_REPORT_HOUR`

规则：

- 正式环境默认 `20`，即晚上 8 点
- 测试阶段可以改成当前小时或附近小时，方便快速触发
- 更改配置后，在下次启动时生效

### 6.3 去重机制

为了避免重复发送：

- 记录 `lastSummaryDate`
- 如果今天已经发过，就跳过
- 重启后也能继续判断，避免重复补发

## 7. 预期改动文件

### 7.1 核心文件

- `apps/desktop/src/main/services/cloud-api.ts`
  - 增加 `POST /openclaw-daily-report` 的请求方法
- `apps/desktop/src/main/services/runtime-cloud-supervisor.ts`
  - 增加日报生成与调度逻辑，或抽出一个新的主进程服务
- `apps/desktop/src/main/index.ts`
  - 在应用启动时拉起日报服务
- `packages/shared-types/src/index.ts`
  - 如有需要，补充日报请求/响应类型

### 7.2 可选文件

- `apps/desktop/src/main/ipc.ts`
  - 如果需要手动触发测试，可增加一个 IPC 入口

## 8. 实现步骤

### Step 1：接入日报 API

在 `apps/desktop/src/main/services/cloud-api.ts` 中增加一个专门请求 `POST /openclaw-daily-report` 的方法。

要求：

- 复用现有 HTTP 请求封装
- 复用现有 `api_key` 获取方式
- 返回值结构化处理

### Step 2：生成日报内容

在主进程里读取当天会话数据，计算：

- 会话数
- 消息数
- token 数
- 错误数
- 亮点
- 问题
- 简短文本总结
- 活跃渠道

### Step 3：增加独立定时任务

新增一个主进程服务，例如 `DailyReportService`：

- 启动时检查是否需要补发前一天的日报
- 每分钟检查一次时间
- 到点后发送日报
- 发送成功后记录 `lastSummaryDate`

### Step 4：保持主流程隔离

日报失败时：

- 只记录日志
- 不抛到聊天逻辑
- 不影响心跳和配置同步

## 9. 测试计划

### 9.1 代码级检查

```bash
corepack pnpm typecheck
corepack pnpm build
```

### 9.2 单元级检查

验证以下内容：

- 日报 payload 组装正确
- `summary_date` 格式正确
- 统计字段计算正确
- `lastSummaryDate` 能防止重复发送
- 请求失败不会影响聊天或 heartbeat

### 9.3 集成检查

1. 启动桌面端
2. 绑定 employee `api_key`
3. 设置 `DAILY_REPORT_HOUR` 为测试阶段可快速触发的时间
4. 创建几条会话和消息
5. 等定时器触发或手动触发日报
6. 确认 `/openclaw-daily-report` 收到正确 payload
7. 确认返回里有 `ok`、`summary_id`、`employee_id`、`summary_date`

### 9.4 回归检查

- 心跳是否仍正常执行
- 配置同步是否仍正常执行
- 聊天发送是否仍正常执行
- 重启后是否不会对同一天重复上报

### 9.5 失败路径检查

- 模拟接口返回 4xx / 5xx
- 确认不会影响主业务
- 确认日志里能看到失败原因
- 确认没有活动时的策略符合产品预期（跳过或发最小摘要）

## 10. 约定和注意事项

- 请求字段名必须严格按文档来，不要改成事件式字段名
- `raw_summary_text` 要简洁，不要过长
- `summary_date` 使用本地日期字符串 `YYYY-MM-DD`
- 日报功能应保持独立，不能影响现有聊天链路
- 文档后续若要补充细节，可直接在这里扩展
