一、为什么做这个

之前针对家庭日程管理智能体——日程管理怎样和智能体框架融合、怎样尽可能复用标准智能体框架、满足实现便捷性和后续扩展性——写了产品技术架构文档.

基于这套架构,结合个人日程管理的需求,先设计一个最小的 MVP 实现。核心需求:

  • 多源信息收集:通过微信等渠道直接扔对话片段、截图、语音,智能体自动解析形成日程

  • 工作日程同步:来源于如流的 ICS 订阅,统一同步后汇总

  • 大屏看板展示:桌上摆了一个添添自由屏,自动显示下一个日程、今日日程、本周日程,看板简洁清晰

  • 端侧优先:智能体跑在屏端本地,信息存储、模型调用等本地执行(目前是基于 Termux 安装的 OpenClaw)

实现效果:

二、整体架构设计

2.1 架构分层

整体架构在个人 MVP 中做了精简:

2.2 核心设计决策

Channel 只是管道,Skill 做所有业务逻辑。 这是从产品技术架构文档中继承的最重要的设计决策。Channel 适配器不关心消息内容是日程还是闲聊,它只做协议转换。语义理解全部收敛在 Skill 层。

这意味着:新增一个输入渠道(比如从飞书换成钉钉),只需要换一个适配器,日程处理逻辑完全不用动。

三层关注点分离:解析层 / 决策层 / 写入层。 每一层坏了不影响其他两层。解析器 parse 错了?决策层会根据低置信度要求人工确认。写入失败?决策层可以重试或告警。

三、5 个 Skill 的设计与实现

3.1 数据流全景

先看全貌——两条独立的数据管线,一条走对话输入,一条走定时同步:

[流程图]

5 个 Skill 各司其职:

Skill

定位

触发方式

event-parser

解析层:中文 NL → 标准日程字段 + 置信度

会话实时

calendar-board-sync

写入层:看板 API HTTP 客户端

被调用

calendar-dispatcher

决策层:置信度路由 + 协调上下游

会话实时

baidu-workflow-calendar-sync

数据源:定时拉取 ICS → 本地缓存

cron 每 6h

ics-board-mirror

同步层:diff 缓存 → 增量推送看板

cron 每 6h

底层逻辑:event-parsercalendar-board-sync 是纯功能模块,calendar-dispatcherics-board-mirror 是两个协调器,分别负责"对话入口"和"ICS 数据入口"两条管线。

3.2 event-parser:中文日程解析 Skill

设计目标:把"明天下午3点和小李在A123开会"这样的自然语言,解析成标准字段 + 逐字段置信度。

实现方式:这是一个基于大模型(MiniMax-M3)的 Skill。SKILL.md 中定义了详细的解析规则、字段提取逻辑和置信度计算公式,作为 prompt 指导模型按照确定性规则来执行解析。本质上是用 LLM 的语言理解能力来做结构化提取,但通过严格的规则约束让输出尽可能可预测。

SKILL.md 中约束的提取规则

  • 时间表达:今天/明天/下周X、X月X日、X点X分、上午/下午/晚上

  • 地点提取:在X + 场所关键词(会议室/酒店/楼/厅/室)

  • 参会人提取:和/跟/同/与 + 人名

  • 标题:剥离时间/地点/人员 token 后的剩余部分

3.3 calendar-dispatcher:置信度决策协调器

这是整个对话链路的大脑。它不自己干解析,也不自己干写入,只做一件事:根据 event-parser 的置信度输出,决定走哪条路。

一个值得说明的设计选择:calendar-dispatcher 没有独立的执行脚本(不像 event-parser 有 parse-event.mjs、calendar-board-sync 有 calendar-board.mjs)。它的 SKILL.md 本质上是一份"决策流程文档",用来约束 Agent 的推理路径——检测意图 → 调 event-parser → 看置信度 → 调 calendar-board-sync。这些步骤就是 Agent 本身的 ReAct 推理流程。

为什么不直接把这段逻辑写在 agent.md 里? 因为把它封装成独立 Skill 有几个好处:

  1. Agent 有一个明确的"入口点"——检测到日程意图就激活这个 Skill,按文档里的 Flow 走,而不是靠 agent.md 中散落的指令拼凑行为

  2. 决策逻辑有清晰的文档边界,和 event-parser、calendar-board-sync 形成可维护的三件套

  3. 可以独立迭代——修改决策阈值、增加新的判断分支,只需要改这一个 SKILL.md

本质上这是一个 "Prompt-as-Skill"——用结构化文档来编排 Agent 的推理路径,而不是用代码脚本来执行逻辑。在当前 LLM Agent 架构下,这是一种有效的模式:把复杂的多步决策流程固化为文档,让 Agent 按文档执行,而不是每次都靠 agent.md 中的零散指令来"临场发挥"。

3.4 baidu-workflow-calendar-sync:ICS 定时抓取

场景:如流有一个 ICS 日历订阅链接,里面有我所有的工作会议。我需要定时抓取、过滤、缓存到本地。

关键设计决策

  1. 三周窗口过滤 [today-7, today+14]:ICS 源里有几百个历史事件(首次跑拿到 297 个),但我只关心最近三周的。窗口过滤把 297 个裁到 29 个。

  2. 自写极简 ICS 解析器:没有用第三方 ics 库。原因是百度工作流生成的 ICS 有一些非标写法(比如 TZID=Etc/GMT),需要特殊处理。自己写的好处是出了问题能直接定位。

  3. 每 6 小时全量覆盖:不做增量追踪。每次跑都是全量拉取→过滤→覆盖本地缓存。简单暴力但可靠。

  4. 纯 Node 内置 API,零依赖:只用 fetch(Node 18+内置)和 Intl.DateTimeFormat,不引入任何第三方包。部署和运行都极简。

Cron 配置0 */6 * * *(每天 00/06/12/18 点跑一次)

3.5 ics-board-mirror:增量同步到看板

场景baidu-workflow-calendar-sync 把 ICS 数据缓存到本地 JSON 了,现在需要把变化的部分推到看板服务。

为什么不直接在上一个 Skill 里推? 关注点分离。抓取和同步是两个独立的失败域:ICS 抓取可能因为网络失败,看板推送可能因为 Token 过期。拆开后,ICS 缓存即使同步失败了还在本地,可以下次重试。

diff 逻辑

  • 读取上次同步快照 ics-mirror-state.json

  • 和最新缓存 baidu-workflow-cache.json 做 diff

  • (uid, start) 为 key 判断新增/修改/删除

  • 稳定 externalId:openclaw-bd-<uid前缀>-<hash(uid|start)>

错峰设计:Cron 是 5 */6 * * *(比 baidu-workflow-calendar-sync 晚 5 分钟),确保跑的时候本地缓存已经是最新的。

3.6 calendar-board-sync:看板 API 客户端

这是最"薄"的一个 Skill——纯 HTTP 客户端,封装了看板服务的所有 API 调用。

支持的操作:upsertsync(批量)、listgetpatchdeletedelete-by-external-id

幂等性保证:所有写操作基于 source + externalId 做 upsert。同一个 externalId 重复推送只会更新,不会创建重复记录。

四、Agent 调度设计

4.1 agent.md 中的 Calendar Skills 配置

为了让智能体知道什么时候该触发日程技能,在 agent.md 中明确配置了触发规则:

触发关键词

  • 日程动词:开会、见面、聚餐、约、打球、记得、提醒我、加个日程、安排、预约

  • 时间表达:今天/明天/后天、下周X、X月X日、X点X分、上午/下午/晚上

  • 日程关键词:日程、会议、提醒、预约、calendar、schedule

核心规则:检测到日程意图时,直接激活 calendar-dispatcher,不要问用户"要不要加日程?" 这是主动服务的体现——用户已经在说"明天3点开会"了,还问一句"要帮你加吗?"是多余的交互摩擦。

对图片/语音的处理:先用多模态能力(image tool / ASR)转成文本,再走 dispatcher 流程。渠道无关,统一入口。

4.2 对话流程示例

[流程图]

五、日程看板服务的实现

5.1 开发方法:Vibe Coding

看板部分的开发完全基于 Claude Code Vibe Coding 模式:

  1. 先写需求文档:通过对话和 AI 一起完善需求,产出完整的设计需求文档(包含布局、API、数据模型、安全设计等)

  2. AI 生成技术方案:基于需求文档,让 AI 出技术方案,指定 Vercel 部署方案(低成本)

  3. AI 编码实现:分四个里程碑推进——骨架 → 数据库+API → 前端 → 部署

  4. AI 生成 Skill 对接文档:开发完成后,AI 自动生成 Skill 对接文档,拷贝给龙虾(OpenClaw)去建立技能

一个实用技巧:前端 UI 调整时,先让 AI 生成测试数据,在一个独立的 preview 页面上调整布局,调好了再同步到主页面。避免每次改 UI 都需要真实数据和完整链路。

# 个人大屏日历看板设计需求

## 1. 项目背景

设计一个面向个人使用的日历大屏看板服务,用于在全屏设备上清晰展示个人日程状态。

系统包含:

- 前端日历看板页面:用于全屏展示今日日程、本周日程、下一个日程。
- 后端日程服务:用于存储、查询和处理日程数据。
- OpenClaw Skill 对接能力:OpenClaw 可以通过 Skill 向本服务写入、更新、删除、读取日程。

本项目优先实现 MVP 版本:单用户、Token 鉴权、看板密码访问保护、前端只读展示、后端提供稳定 API,方便 OpenClaw Skill 对接。

相关文档:

- [技术方案](技术方案.md):技术栈、架构、数据库、Vercel 部署方案。
- [Skill 对接文档](Skill对接文档.md):OpenClaw Skill 调用接口、鉴权、请求和响应示例。

---

## 2. 使用场景

### 2.1 主要场景

用户在个人大屏、显示器、平板、电视或浏览器全屏模式下查看日历看板,快速了解:

- 今天有哪些日程。
- 本周近期有哪些安排。
- 下一件马上要发生的日程是什么。

该看板主要面向个人使用,不面向多人协作场景。

### 2.2 数据来源

日程数据主要由 OpenClaw Skill 同步到本服务。

OpenClaw Skill 负责:

- 创建日程。
- 更新日程。
- 删除日程。
- 查询日程。
- 处理重复日程逻辑。

本服务不负责重复日程展开和重复规则计算。重复日程由 OpenClaw 侧提前处理后,以普通日程形式写入本服务。

---

## 3. 目标与非目标

### 3.1 目标

- 提供一个简洁清晰的个人日历大屏看板。
- 支持横屏 16:9 和竖屏 9:16 的全屏展示。
- 页面整体不滚动,具体模块内容过多时模块内部滚动。
- 展示今日日程、本周日程、下一个日程三个核心模块。
- 支持 OpenClaw Skill 对日程进行增删改查。
- 支持基于 Token 的接口鉴权。
- 支持前端看板首次访问密码验证,验证通过后在同一浏览器中保持登录状态,避免个人日程信息泄露。
- 开发完成后可直接部署到 Vercel。
- 使用 Neon Postgres 持久化存储日程数据,避免 Vercel Serverless 环境中本地文件不可持久化的问题。
- 支持按 `source + externalId` 进行幂等写入,避免重复同步产生重复日程。

### 3.2 非目标

MVP 阶段暂不实现:

- 多用户账号体系。
- OAuth 登录。
- 第三方日历平台直连。
- 重复日程规则计算。
- 复杂权限模型。
- 前端手动新增、编辑、删除日程。
- 移动端复杂交互。
- 日程提醒、推送通知。

---

## 4. 系统角色

### 4.1 用户

日历看板的使用者,主要通过前端页面查看日程。

### 4.2 OpenClaw Skill

外部自动化 Skill,负责向后端写入、读取、更新、删除日程。

### 4.3 日历服务后端

负责:

- 使用 Neon Postgres 持久化存储日程数据。
- 提供查询接口。
- 提供创建、更新、删除接口。
- 提供批量同步接口。
- 校验 Token。

### 4.4 日历服务前端

负责:

- 首次打开看板时引导用户输入访问密码。
- 密码验证通过后,在同一浏览器中保持登录状态,后续打开无需重复输入。
- 从后端读取日程。
- 计算并展示今天、本周、下一个日程。
- 根据屏幕方向自动调整布局。

---

## 5. 功能需求

## 5.1 后端能力需求

### 5.1.1 日程创建

OpenClaw Skill 可以创建新的日程。

要求:

- 支持通过 `source + externalId` 标识外部日程。
- 如果相同 `source + externalId` 已存在,创建请求应按覆盖逻辑更新已有日程。
- 如果没有传 `externalId`,后端生成内部 `id`,但不保证外部幂等。

### 5.1.2 日程更新

OpenClaw Skill 可以更新已有日程。

要求:

- 支持按内部 `id` 更新。
- 支持按 `source + externalId` 覆盖更新。
- 冲突规则统一采用覆盖逻辑:后写入的数据覆盖已有数据。

### 5.1.3 日程删除

OpenClaw Skill 可以删除日程。

要求:

- 支持按内部 `id` 删除。
- 支持按 `source + externalId` 删除。
- 删除采用硬删除即可,MVP 阶段不要求软删除。

### 5.1.4 日程查询

OpenClaw Skill 和前端都可以读取日程。

要求:

- 支持按时间范围查询。
- 支持查询未来日程。
- 支持查询单个日程详情。
- 支持按来源过滤。

### 5.1.5 批量同步

为方便 OpenClaw Skill 对接,后端提供批量同步接口。

要求:

- 支持一次请求中批量 upsert 日程。
- 支持一次请求中批量删除日程。
- upsert 使用覆盖逻辑。
- 删除优先使用 `source + externalId`。
- 返回每条记录的处理结果,方便 OpenClaw 侧排查问题。

---

## 5.2 看板访问保护需求

### 5.2.1 首次访问密码验证

前端看板页面涉及个人日程信息,需要在首次打开时进行密码验证。

规则:

- 用户首次打开看板页面时,不能直接看到日程内容。
- 页面展示密码输入界面。
- 密码固定为 6 位数字。
- 密码输入界面使用页面自带的触摸数字键盘,不调用系统键盘。
- 用户通过自带键盘逐位输入密码,输入满 6 位后可以自动验证。
- 用户输入正确密码后,进入日历看板页面。
- 密码错误时展示错误提示,不展示任何日程内容。
- 访问密码只用于保护个人看板页面,不用于 OpenClaw Skill API 调用。

### 5.2.2 保持登录状态

密码验证通过后,需要在同一浏览器中保持登录状态,避免每次打开都重新输入密码。

规则:

- 验证通过后,后端下发安全会话 Cookie 或等效登录凭证。
- 用户后续在同一浏览器打开看板页面时,如果会话仍有效,应直接进入看板。
- 登录状态应至少支持长期保持,适合个人大屏固定设备使用。
- 用户清除浏览器数据、更换浏览器、更换设备或会话失效后,需要重新输入密码。
- MVP 阶段可以不提供显式退出登录按钮,但后续可作为增强功能。

### 5.2.3 数据保护范围

访问保护需要覆盖:

- 前端看板页面。
- 前端看板页面依赖的看板数据接口。

访问保护不影响:

- OpenClaw Skill 使用 Bearer Token 调用的日程同步接口。
- OpenClaw Skill 使用 Bearer Token 调用的日程查询接口。

---

## 5.3 前端展示需求

### 5.3.1 页面整体要求

- 页面用于全屏展示。
- 支持横屏 16:9。
- 支持竖屏 9:16。
- 页面整体不可滚动。
- 页面内具体功能模块如果内容超出,可以在模块内部滚动。
- 模块内部保留滚动能力,但默认不展示显眼滚动条,避免静止展示时影响大屏观感。
- 页面布局简约、清晰、稳定。
- 横屏和竖屏下都不能出现格式混乱、元素溢出、内容重叠。
- UI 调整优先在 `preview/dashboard-preview.html` 中预览确认,确认后再同步到主程序并部署。

### 5.3.2 展示模块

前端包含三个核心模块:

1. 今日日程。
2. 本周日程。
3. 下一个日程。

### 5.3.3 今日日程模块

用于展示当天全部日程。

规则:

- 展示今天 00:00 到 23:59:59 内的全部日程。
- 按开始时间升序排序。
- 已结束日程可以弱化展示,例如降低透明度或标记为“已结束”。
- 正在进行中的日程需要突出显示。
- 今日无日程时展示空状态,例如“今天暂无日程”。
- 如果当天日程过多,模块内部支持纵向滚动。

### 5.3.4 本周日程模块

用于展示近期日程,帮助用户看到接下来几天的安排。

规则:

- 标题展示为“本周日程”。
- 优先展示本周内的日程,也可以为了滚动上下文包含近期前后日期。
- 如果本周日程过多,至少展示明天及未来两天的日程。
- 按日期分组展示。
- 每个日期内按开始时间升序排序。
- 如果模块展示不下,模块内部可以滚动。
- 今日已在“今日日程”中完整展示,本周模块默认滚动到明天分组,从当前时间第二天的第一个日期分组开始显示,避免和今日日程重复。

### 5.3.5 下一个日程模块

用于突出显示距离当前时间最近的下一个未结束日程。

规则:

- 从当前时间之后的日程中选择开始时间最近的一条。
- 如果当前存在正在进行中的日程,可以优先展示正在进行中的日程,并标记为“进行中”。
- 展示内容包括标题、时间、地点、非普通优先级、距离开始还有多久。
- 时间信息前展示时钟图标,地点信息前展示位置图标,增强可读性。
- 右侧倒计时区域需要保持足够宽度和字号,不能被压缩得过小或显得局促。
- 如果没有未来日程,展示空状态,例如“暂无即将开始的日程”。

---

## 6. 页面布局要求

## 6.1 横屏布局 16:9

适用于显示器、电视、浏览器横向全屏。

建议布局:

- 左上区域:下一个日程。
- 左下区域:今日日程。
- 右侧整列:本周日程。

示意:

```text
┌──────────────────────────────┬──────────────────────┐
│          下一个日程           │                      │
├──────────────────────────────┤      本周日程         │
│                              │                      │
│          今日日程             │                      │
│                              │                      │
└──────────────────────────────┴──────────────────────┘

横屏要求

  • 下一个日程放在左上,保证快速看到最近安排。

  • 今日日程放在左下,展示当天完整列表。

  • 本周日程占据右侧整列,作为近期安排总览。

  • 所有模块高度固定在视口内,不能撑开页面。

  • 所有模块标题、核心信息和操作状态需要完整显示,不能被裁切。

  • 日程列表超出时只能在模块内部滚动,页面整体不能滚动。

6.2 竖屏布局 9:16

适用于竖向屏幕、平板竖屏或浏览器竖向全屏。

建议布局:

  • 顶部:下一个日程。

  • 中部:今日日程。

  • 底部:本周日程。

示意:

┌──────────────────────────────┐
│          下一个日程           │
├──────────────────────────────┤
│                              │
│          今日日程             │
│                              │
├──────────────────────────────┤
│          本周日程             │
└──────────────────────────────┘

竖屏要求

  • 下一个日程放在顶部,保证快速看到最近安排。

  • 今日日程放在中部,展示当天完整列表。

  • 本周日程放在底部,展示近期摘要。

  • 竖屏下本周日程区域需要占据页面约一半高度,避免近期安排显示过少。

  • 各模块内部独立滚动。

  • 所有模块标题、核心信息和操作状态需要完整显示,不能被裁切。

  • 页面整体不能滚动。


7. 日程数据模型

7.1 Event 对象

字段

类型

必填

说明

id

string

后端生成的内部 ID

externalId

string

外部系统日程 ID,由 OpenClaw 提供

source

string

日程来源,例如 openclawmanualcalendar_skill

title

string

日程标题

startTime

string

开始时间,ISO 8601 格式

endTime

string

结束时间,ISO 8601 格式

location

string

地点

description

string

描述

priority

string

优先级:lownormalhighurgent

createdAt

string

创建时间,后端生成

updatedAt

string

更新时间,后端生成

7.2 字段规则

title

  • 不能为空。

  • 建议长度不超过 100 个字符。

startTime / endTime

  • 使用 ISO 8601 格式。

  • 推荐包含时区,例如 2026-06-16T09:30:00+08:00

  • endTime 必须大于或等于 startTime

  • MVP 阶段不单独处理全天日程,如需要全天日程,由 OpenClaw 转换成当天 00:00 到 23:59 的普通日程。

source

  • 标识数据来源。

  • OpenClaw Skill 默认使用 openclaw

externalId

  • 外部系统中的日程唯一标识。

  • 推荐 OpenClaw 每条日程都传入该字段。

  • 后端使用 source + externalId 判断是否为同一条外部日程。

priority

允许值:

  • low:低优先级。

  • normal:普通优先级。

  • high:高优先级。

  • urgent:紧急。

默认值:normal

展示规则:

  • 未传 priority 时按 normal 处理。

  • normal 为普通日程,不显示优先级标签。

  • 只有 lowhighurgent 需要在页面上显示优先级标签。


8. 冲突与覆盖规则

MVP 阶段统一采用覆盖逻辑。

8.1 覆盖判断

如果请求中包含 sourceexternalId,后端查找是否存在相同 source + externalId 的日程:

  • 存在:覆盖已有日程。

  • 不存在:创建新日程。

8.2 字段覆盖

覆盖时,以本次请求传入的字段为准。

建议规则:

  • 完整更新:完整覆盖。

  • 部分更新:只更新传入字段。

  • 批量同步:按传入 event 对象覆盖,未传字段使用默认值或保留后端生成字段。

8.3 删除冲突

删除不存在的日程时,接口可以返回成功,并标记结果为 not_found,保证同步接口幂等。


9. 展示刷新策略

  • MVP 阶段使用版本轮询,不实现实时推送。

  • 前端首次进入看板时请求 /api/dashboard 获取完整数据。

  • 看板进入 ready 状态后,每 30 秒请求一次 /api/version 获取日历数据版本号。

  • 如果版本号未变化,不重新请求看板数据,减少数据库查询和页面重渲染。

  • 如果版本号发生变化,前端重新请求 /api/dashboard 刷新今日日程、本周日程和下一个日程。

  • /api/version 只读取版本号,不更新版本号。

  • 后端写操作完成后才更新版本号,包括新增、更新、删除事件,以及有实际变更的批量同步。

  • 一次写操作只更新一次版本号,避免单次操作触发多次无意义刷新。

  • 如果后续需要更强实时性,可以增加 Server-Sent Events 或 WebSocket。


10. 验收标准

10.1 后端验收

  • Token 错误时接口返回 401。

  • OpenClaw 可以创建日程。

  • OpenClaw 可以更新日程。

  • OpenClaw 可以删除日程。

  • OpenClaw 可以查询日程。

  • 批量同步接口支持 upsert 和 delete。

  • 相同 source + externalId 多次同步不会生成重复日程。

  • 冲突时后写入的数据覆盖旧数据。

  • 日程数据写入 Neon Postgres,重新部署后数据仍可读取。

  • Vercel 线上环境通过 DATABASE_URLOPENCLAW_API_TOKENDASHBOARD_PASSWORDSESSION_SECRET 环境变量运行。

10.2 前端验收

  • 首次打开看板时显示密码输入界面,不展示日程内容。

  • 密码输入界面只接受 6 位数字。

  • 密码输入界面使用自带触摸数字键盘,不调用系统键盘。

  • 密码错误时展示错误提示。

  • 密码正确后进入日历看板页面。

  • 同一浏览器第二次打开无需重新输入密码。

  • 横屏 16:9 下页面布局清晰,无整体滚动条。

  • 竖屏 9:16 下页面布局清晰,无整体滚动条,且本周日程区域约占页面一半高度。

  • 今日日程展示当天全部日程。

  • 今日日程过多时模块内部可滚动,但默认不显示显眼滚动条。

  • 本周日程展示近期安排,默认从明天分组开始显示,避免和今日日程重复。

  • 下一个日程能正确展示最近的未结束日程,倒计时区域显示清晰、不局促。

  • 时间前显示时钟图标,地点前显示位置图标。

  • 普通优先级不展示标签,只有非普通优先级显示标签。

  • 无日程时展示友好的空状态。

10.3 OpenClaw 对接验收

  • OpenClaw Skill 可以通过 Token 调用接口。

  • OpenClaw Skill 可以用批量同步接口同步日程。

  • OpenClaw Skill 可以读取日程。

  • 接口返回结构稳定,便于 Skill 解析。


11. 后续可选增强

  • 支持显式退出登录按钮。

  • 支持暗色主题或固定大屏主题。

  • 为不同优先级配置不同颜色。

  • 展示农历、节假日、天气等辅助信息。

  • 增加手动编辑日程能力。

  • 增加实时推送能力。





### 5.2 技术选型
|**层级**|**选择**|**理由**|
|-|-|-|
|框架|Next.js App Router|前后端一体,部署简单|
|样式|Tailwind CSS|快速实现响应式全屏布局|
|数据库|Neon Postgres|Serverless Postgres,Vercel 原生适配|
|ORM|Drizzle|轻量、类型安全、serverless 友好|
|校验|Zod|请求/响应结构化校验|
|部署|Vercel|零运维,推送即部署|

为什么选 Neon 而不是 SQLite?因为 Vercel Serverless 环境不支持持久化本地文件——每次函数冷启动都是全新容器。必须用外部数据库。Neon 提供免费的 Serverless Postgres,和 Vercel 天然集成。

个人大屏日历看板技术方案

1. 技术目标

本项目需要在开发完成后可以直接部署到 Vercel,同时满足:

  • 前端大屏看板和后端 API 同项目部署。

  • OpenClaw Skill 可以通过公网 HTTPS 接口访问后端 API。

  • 日程数据具备持久化存储能力。

  • 支持按时间范围查询、排序、增删改查和幂等同步。

  • Token、数据库连接等敏感配置不写入代码仓库。


2. 推荐技术栈

模块

推荐方案

说明

前端框架

Next.js App Router + React + TypeScript

前后端同仓库,天然适配 Vercel 部署

样式方案

Tailwind CSS

适合快速实现大屏响应式布局

后端接口

Next.js Route Handlers

使用 app/api/**/route.ts 实现 REST API

数据库

Neon Postgres

Serverless Postgres,适合 Vercel 部署和结构化日程数据

ORM

Drizzle ORM

轻量、类型友好,适合 serverless 场景

参数校验

Zod

校验接口请求体、query 参数和响应结构

时间处理

原生 Intl.DateTimeFormatdate-fns

用于日期分组、格式化和相对时间展示

部署平台

Vercel

承载前端页面和后端 Serverless API


3. 方案选择理由

3.1 为什么使用 Next.js

  • 前端页面和后端 API 可以放在同一个项目中。

  • App Router 适合构建页面、布局和 API Route Handler。

  • Vercel 对 Next.js 支持最好,部署流程简单。

  • Route Handlers 支持 GETPOSTPUTPATCHDELETE,可以直接实现本项目 REST API。

3.2 为什么使用 Neon Postgres

日程是结构化数据,需要:

  • 按时间范围查询。

  • 按开始时间排序。

  • 按来源过滤。

  • 使用 source + externalId 做唯一约束。

  • 支持更新和删除。

Postgres 比 KV、Blob、本地 JSON 更适合此类数据。

3.3 为什么不使用本地文件或 SQLite 作为线上存储

Vercel Functions 是无服务器运行环境,运行时文件系统不适合保存持久化业务数据。

因此:

  • 本地 JSON 文件只适合开发调试,不适合线上使用。

  • SQLite 文件不适合作为 Vercel 线上持久化数据库。

  • 线上应使用 Neon Postgres 等外部托管数据库。

3.4 为什么不使用 Vercel Blob / Edge Config

  • Vercel Blob 更适合图片、视频、附件等大文件存储。

  • Edge Config 更适合低频变更的配置、功能开关和全局低延迟读取。

  • 日程数据存在频繁增删改查,不适合作为 Blob 或 Edge Config 数据。


4. 系统架构

OpenClaw Skill
   │ Authorization: Bearer <OPENCLAW_API_TOKEN>
   ▼
Vercel / Next.js Route Handlers
   │
   ▼
Neon Postgres
   ▲
   │ Server-side query / dashboard API
Next.js Calendar Dashboard

4.1 请求流

  1. OpenClaw Skill 使用 Bearer Token 调用后端 API。

  2. Next.js Route Handler 校验 Token。

  3. Route Handler 使用 Zod 校验请求参数。

  4. 业务逻辑层处理创建、更新、删除、查询或批量同步。

  5. Drizzle ORM 访问 Neon Postgres。

  6. API 返回稳定 JSON 响应。

  7. 前端看板定时请求看板数据接口,刷新页面展示。


5. 推荐项目结构

calendar-board/
├── app/
│   ├── page.tsx
│   ├── layout.tsx
│   ├── globals.css
│   └── api/
│       ├── events/
│       │   ├── route.ts
│       │   ├── [id]/route.ts
│       │   └── by-external-id/route.ts
│       ├── sync/route.ts
│       ├── dashboard/route.ts
│       └── dashboard-auth/route.ts
├── components/
│   ├── PasswordGate.tsx
│   ├── TouchNumberPad.tsx
│   ├── TodayEvents.tsx
│   ├── WeekEvents.tsx
│   └── NextEvent.tsx
├── db/
│   ├── schema.ts
│   ├── client.ts
│   └── migrations/
├── lib/
│   ├── auth.ts
│   ├── events.ts
│   ├── validation.ts
│   ├── dashboard.ts
│   └── time.ts
├── drizzle.config.ts
├── next.config.ts
├── package.json
└── .env.local.example

6. 后端设计

6.1 Route Handlers

推荐接口文件:

文件

接口

app/api/events/route.ts

GET /api/eventsPOST /api/events

app/api/events/[id]/route.ts

GET /api/events/{id}PUT /api/events/{id}PATCH /api/events/{id}DELETE /api/events/{id}

app/api/events/by-external-id/route.ts

DELETE /api/events/by-external-id

app/api/sync/route.ts

POST /api/sync

app/api/dashboard/route.ts

GET /api/dashboard

app/api/dashboard-auth/route.ts

POST /api/dashboard-auth,验证 6 位数字密码并下发会话 Cookie

建议所有 API Route Handler 明确使用 Node.js runtime:

export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'

原因:

  • 数据库 SDK 在 Node.js runtime 下兼容性更稳定。

  • API 数据需要动态读取,不能被静态缓存。

6.2 数据库连接策略

数据库连接通过 db/client.ts 中的 getDb() 懒加载创建。

原因:

  • Vercel 构建阶段会导入 API Route 文件进行静态分析。

  • 如果在模块顶层直接读取 DATABASE_URL 并初始化数据库客户端,构建阶段可能因为环境变量未注入而失败。

  • 使用懒加载后,只有 API 请求真正执行时才读取 DATABASE_URL 并连接 Neon。

6.3 业务层划分

建议将业务逻辑从 Route Handler 中抽离:

  • lib/auth.ts:Token 校验。

  • lib/validation.ts:Zod schema。

  • lib/events.ts:日程增删改查逻辑。

  • lib/dashboard.ts:今日、本周、下一个日程聚合逻辑。

  • lib/time.ts:时间范围、日期分组、格式化逻辑。

这样 Route Handler 只负责:

  1. 解析请求。

  2. 校验鉴权。

  3. 调用业务层。

  4. 返回响应。


7. 数据库设计

7.1 events 表

字段

类型

说明

id

uuid / text

内部 ID,主键

external_id

text

外部日程 ID

source

text

日程来源

title

text

标题

start_time

timestamptz

开始时间

end_time

timestamptz

结束时间

location

text

地点

description

text

描述

priority

text

优先级

created_at

timestamptz

创建时间

updated_at

timestamptz

更新时间

7.2 索引建议

  • primary key(id):内部 ID 查询。

  • unique(source, external_id):保证外部同步幂等。

  • index(start_time):优化按时间范围查询和排序。

  • index(end_time):优化进行中日程和时间范围重叠查询。

  • index(source):优化按来源过滤。

7.3 注意事项

  • external_id 允许为空,但推荐 OpenClaw 始终传入。

  • 如果 external_id 为空,则不能依赖 source + external_id 做幂等。

  • priority 建议限制为 lownormalhighurgent

  • 时间字段建议使用 timestamptz,接口层统一接收 ISO 8601 字符串。


8. 鉴权与环境变量

8.1 Token 与密码设计

系统使用两套独立的凭证:

凭证

用途

类型

是否暴露到浏览器

OPENCLAW_API_TOKEN

OpenClaw Skill 调用后端 API 的读写 Token

Bearer Token

DASHBOARD_PASSWORD

保护看板页面首次访问的 6 位数字密码

用户手动输入

两者边界:

  • OPENCLAW_API_TOKEN:只用于 API 层鉴权,放在请求头,不进入浏览器界面。

  • DASHBOARD_PASSWORD:只用于看板页面访问控制,用户在浏览器中手动输入,密码本身不传到前端,只在后端对比。

OpenClaw API 请求头:

Authorization: Bearer <OPENCLAW_API_TOKEN>

8.2 看板访问保护实现

看板访问保护的推荐实现方式:

  1. 前端首次打开看板页面时,展示密码输入界面。

  2. 用户输入 6 位数字密码后,前端调用后端验证接口。

  3. 后端将用户输入的密码与 DASHBOARD_PASSWORD 环境变量对比。

  4. 密码正确,后端通过 Set-Cookie 下发 HttpOnly 会话 Cookie。

  5. 前端后续请求看板数据接口时,自动携带 Cookie,后端校验 Cookie 有效性。

  6. 密码错误,返回 401,前端展示错误提示,不展示任何日程内容。

Cookie 建议配置:

  • HttpOnly: true:防止 JavaScript 读取。

  • SameSite: Strict:防止 CSRF。

  • Secure: true:仅在 HTTPS 下传输(Vercel 线上自动 HTTPS)。

  • Max-AgeExpires:设置长过期时间,适合个人大屏固定设备。

8.3 密码输入界面

密码输入界面要求:

  • 使用自带的键盘触摸输入,不调用系统键盘。

  • 显示 6 个占位格,用户逐位输入,输入满 6 位后自动提交。

  • 输入时以圆点或掩码展示,不明文显示密码。

  • 密码长度固定为 6 位数字。

  • 密码错误时展示错误提示,清空已输入内容。

8.4 本地环境变量

.env.local 示例:

DATABASE_URL=postgresql://...
OPENCLAW_API_TOKEN=replace-with-openclaw-token
DASHBOARD_PASSWORD=123456
SESSION_SECRET=replace-with-session-secret

注意:不要使用 NEXT_PUBLIC_ 前缀保存敏感配置,否则会被暴露给浏览器端代码。

8.5 Vercel 环境变量

Vercel 项目中至少需要配置:

DATABASE_URL=postgresql://...
OPENCLAW_API_TOKEN=replace-with-openclaw-token
DASHBOARD_PASSWORD=replace-with-6-digit-password
SESSION_SECRET=replace-with-session-secret

其中:

  • DATABASE_URL:Neon Postgres 数据库连接字符串。

  • OPENCLAW_API_TOKEN:OpenClaw Skill 调用 API 的 Bearer Token。

  • DASHBOARD_PASSWORD:看板访问密码,6 位数字。

  • SESSION_SECRET:用于签名会话 Cookie,建议使用随机长字符串。


9. 前端实现方案

9.1 布局策略

  • 页面根节点固定 100vw100vh

  • 页面整体设置 overflow: hidden

  • 每个功能模块内部设置 overflow: auto

  • 使用 CSS Grid 或 Flex 实现模块布局。

  • 使用媒体查询或容器宽高比判断横屏/竖屏。

  • UI 频繁调整阶段可以先使用 preview/dashboard-preview.html 独立预览页面调试视觉效果,该文件内置测试数据,不依赖 Next.js、数据库或 API。

9.2 密码输入界面

密码输入界面实现要点:

  • 使用自绘数字键盘组件,不触发系统键盘弹出。

  • 渲染 0-9 共 10 个数字键和一个删除键。

  • 上方展示 6 个圆形占位格,已输入位用实心圆点表示。

  • 输入满 6 位后自动调用后端验证接口,无需确认按钮。

  • 验证失败后清空所有输入,展示错误提示文字。

  • 不使用 HTML input 元素,避免触发系统键盘。

9.3 横屏布局

横屏 16:9:

  • 左侧大区域:今日日程。

  • 右上区域:下一个日程。

  • 右下区域:本周日程。

9.4 竖屏布局

竖屏 9:16:

  • 顶部:下一个日程。

  • 中部:今日日程。

  • 底部:本周日程。

9.5 数据刷新

前端使用版本轮询机制,而非直接轮询 dashboard 数据,以减少不必要的数据库查询。

流程:

  1. 页面首次加载时请求一次 /api/dashboard 获取完整数据,进入 ready 状态。

  2. 进入 ready 状态后,启动每 30 秒执行一次的定时器。

  3. 每次定时器触发时:

    • 更新当前时间(用于倒计时展示)。

    • 请求 /api/version,获取日历数据的最新版本号(时间戳)。

    • 与上一次保存的版本号对比:版本相同则不做任何请求;版本不同则重新请求 /api/dashboard 刷新数据。

版本号的更新时机:

后端所有写操作完成后会调用 touchCalendarVersion() 将版本号更新为当前时间。触发场景:

  • POST /api/events:新增事件

  • PUT /api/events/{id}PATCH /api/events/{id}:更新事件

  • DELETE /api/events/{id}DELETE /api/events/by-external-id:删除事件

  • POST /api/sync:批量同步(仅当有实际变更时才更新版本)

一次操作只调用一次 touchCalendarVersion(),不会重复写入。GET /api/version 只读不写,不会触发版本更新。

不使用 WebSocket 或 Server-Sent Events。


10. Vercel 部署方案

10.1 部署目标

项目部署到 Vercel 后同时提供:

  • 前端大屏看板页面。

  • OpenClaw Skill 调用的后端 API。

  • 与 Neon Postgres 连接的持久化日程存储。

10.2 部署流程

  1. 创建 Next.js 项目并完成日历看板和 API 开发。

  2. 在 Neon 创建 Postgres 数据库,复制连接字符串作为 DATABASE_URL

  3. 在本地 .env.local 中配置 DATABASE_URLOPENCLAW_API_TOKENDASHBOARD_PASSWORDSESSION_SECRET

  4. 执行 npm run db:generate 生成 Drizzle 迁移文件。

  5. 加载本地环境变量后执行 npm run db:migrate,在 Neon 中创建 events 表和索引。

  6. 在 Vercel Project Settings 或 Vercel CLI 中配置 Production 环境变量,必须包含:DATABASE_URLOPENCLAW_API_TOKENDASHBOARD_PASSWORDSESSION_SECRET

  7. 使用 vercel env ls 确认四个变量都存在,且 environments 列包含 Production

  8. 执行 vercel deploy --prod 部署生产环境。注意:新增或修改 Vercel 环境变量后必须重新部署,新的 Serverless Function 才会读取到最新值。

  9. 使用部署后的域名配置 OpenClaw Skill 的 API Base URL。

  10. 打开看板页面,验证 6 位密码输入界面。

  11. 输入正确密码,验证进入看板页面。

  12. 使用 OpenClaw Skill 调用 POST /api/syncPOST /api/events 验证写入。

  13. 验证大屏展示和数据刷新。

10.3 当前线上部署信息

当前生产环境:

  • 看板地址:https://calendar-board.vercel.app

  • API Base URL:https://calendar-board.vercel.app/api

  • 数据库:Neon Postgres

  • 看板访问密码:6 位数字,通过 DASHBOARD_PASSWORD 环境变量配置

  • OpenClaw API Token:通过 OPENCLAW_API_TOKEN 环境变量配置,不写入文档正文

10.4 Vercel 环境变量配置

生产环境必须在 Vercel 中配置以下四个环境变量,且作用环境必须包含 Production

环境变量

用途

缺失后表现

DATABASE_URL

Neon Postgres 数据库连接字符串

API 访问数据库时报错,日程无法读取或写入

OPENCLAW_API_TOKEN

OpenClaw Skill 调用 API 的 Bearer Token

OpenClaw 调用事件接口返回 500 或鉴权失败

DASHBOARD_PASSWORD

看板 6 位数字访问密码

看板密码验证接口失败,前端可能显示“密码错误”

SESSION_SECRET

签名看板登录 Cookie 的密钥

密码正确也无法签发会话,/api/dashboard-auth 返回 500

推荐使用 Vercel CLI 添加生产环境变量:

printf '%s\n' '<DATABASE_URL>' | vercel env add DATABASE_URL production
printf '%s\n' '<OPENCLAW_API_TOKEN>' | vercel env add OPENCLAW_API_TOKEN production
printf '%s\n' '<DASHBOARD_PASSWORD>' | vercel env add DASHBOARD_PASSWORD production
printf '%s\n' '<SESSION_SECRET>' | vercel env add SESSION_SECRET production

添加完成后必须确认变量列表:

vercel env ls

确认输出中至少包含:

DATABASE_URL          Encrypted    Production
OPENCLAW_API_TOKEN    Encrypted    Production
DASHBOARD_PASSWORD    Encrypted    Production
SESSION_SECRET        Encrypted    Production

环境变量新增或修改后,必须重新部署生产环境:

vercel deploy --prod

部署完成后建议做两项验收:

  1. 使用 6 位看板密码访问生产看板,确认能进入页面。

  2. 使用 OpenClaw Skill 或接口工具调用 POST /api/sync / POST /api/events,确认 Bearer Token 和数据库写入正常。

10.5 部署注意事项

  • 不使用本地 JSON 文件作为线上持久化存储。

  • 不将 OPENCLAW_API_TOKENDASHBOARD_PASSWORDDATABASE_URLSESSION_SECRET 暴露给浏览器端代码。

  • 文档和代码仓库中只记录环境变量名和占位符,不记录真实密钥值。

  • API Route Handler 中需要关闭静态缓存或明确使用动态处理。

  • 数据库区域建议选择接近 Vercel Function 的区域,降低查询延迟。

  • 会话 Cookie 设置 HttpOnlySecureSameSite: Strict,防止被 JavaScript 读取或跨站请求伪造。


11. 开发里程碑建议

11.1 Milestone 1:项目骨架

  • 初始化 Next.js + TypeScript 项目。

  • 接入 Tailwind CSS。

  • 配置 .env.local.example

  • 建立基础页面和 API 目录结构。

11.2 Milestone 2:数据库与后端 API

  • 接入 Neon Postgres。

  • 配置 Drizzle ORM。

  • 创建 events 表和索引。

  • 实现 Token 鉴权。

  • 实现日程 CRUD API。

  • 实现批量同步 API。

11.3 Milestone 3:前端看板

  • 实现 6 位数字密码输入界面。

  • 实现自带触摸数字键盘,不调用系统键盘。

  • 实现横屏布局。

  • 实现竖屏布局。

  • 实现今日日程、本周日程、下一个日程模块。

  • 实现模块内部滚动和空状态。

  • 实现定时刷新。

11.4 Milestone 4:部署与联调

  • 部署到 Vercel。

  • 配置 Neon 和环境变量。

  • 使用 OpenClaw Skill 联调 POST /api/sync

  • 验证大屏展示和数据刷新。


12. 技术风险与规避

风险

影响

规避方式

Token 暴露到前端

造成 API 被未授权写入

Token 只保存在服务端环境变量,不使用 NEXT_PUBLIC_

密码泄露

看板被未授权访问

密码只存服务端环境变量,接口只做后端比对,不回传到前端

会话 Cookie 被劫持

伪造登录状态

Cookie 设置 HttpOnly + Secure + SameSite

API 被缓存

看板显示旧数据

Route Handler 使用动态处理,必要时设置 no-store

数据库延迟

页面刷新慢

选择接近 Vercel Function 的数据库区域

externalId 缺失

无法幂等同步

OpenClaw Skill 尽量始终传入 externalId

日期时区混乱

今日/本周计算错误

接口统一使用 ISO 8601,展示层明确本地时区

### 5.3 数据模型设计
核心就一张 `events` 表,关键设计是 `source + external_id`** 唯一索引**:

```sql
CREATE TABLE events (
  id            SERIAL PRIMARY KEY,
  external_id   VARCHAR(255),
  source        VARCHAR(100) NOT NULL,
  title         VARCHAR(255) NOT NULL,
  start_time    TIMESTAMPTZ NOT NULL,
  end_time      TIMESTAMPTZ NOT NULL,
  location      TEXT,
  description   TEXT,
  priority      VARCHAR(20) DEFAULT 'normal',
  created_at    TIMESTAMPTZ DEFAULT NOW(),
  updated_at    TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(source, external_id)
);

这个唯一索引是整个系统幂等性的基石。同一个来源的同一个事件,不管推送多少次,数据库里永远只有一条记录,后写覆盖先写。

5.4 API 设计

POST   /api/events           — 创建(支持 upsert)
GET    /api/events           — 列表查询(支持时间范围、来源过滤)
GET    /api/events/{id}      — 单条查询
PUT    /api/events/{id}      — 全量更新
PATCH  /api/events/{id}      — 部分更新
DELETE /api/events/{id}      — 删除
POST   /api/sync             — 批量同步(upsert + delete)
GET    /api/dashboard        — 看板聚合数据
GET    /api/version          — 数据版本号
POST   /api/dashboard-auth   — 看板密码验证

安全分层

  • Skill API 调用 → Bearer Token 认证(OPENCLAW_API_TOKEN

  • 看板页面 → 6 位数字密码 + HttpOnly Cookie 会话

5.5 看板刷新策略:版本轮询

这里没有用 WebSocket 或 SSE,而是用了一个极轻量的版本轮询方案:

  1. 前端每 30 秒请求 /api/version(返回一个版本号,极轻量)

  2. 版本号没变 → 什么都不做

  3. 版本号变了 → 重新请求 /api/dashboard 刷新数据

好处:大部分时间数据不变(日程不会每分钟都在改),轮询版本号几乎零开销;数据变化时又能在 30 秒内响应。比定时全量拉取省太多了。

5.6 大屏适配设计

看板需要同时适配横屏(16:9)和竖屏(9:16)两种全屏布局

关键 UX 决策

  • 页面整体不可滚动,各模块内部可滚动——适合挂墙常亮展示

  • 自定义数字键盘组件输入密码,不触发系统键盘——适配大屏/平板触屏

  • 已结束日程降低透明度,进行中日程高亮,下一个日程展示倒计时

六、与产品技术架构的对应关系

这次个人 MVP 实际上是产品技术架构文档中"阶段一:基础日程闭环"的一个子集验证。对应关系如下:

产品架构中的设计

个人 MVP 中的落地

多渠道输入 → Channel 适配器

微信/飞书/语音/截图 → OpenClaw Channel

Ingest Skill(格式预处理)

图片 → 多模态模型 OCR;语音 → ASR 转文字

schedule.operate(日程 CRUD)

calendar-dispatcher + event-parser + calendar-board-sync 三者组合

schedule.sync.ics(ICS 同步)

baidu-workflow-calendar-sync + ics-board-mirror

置信度管理(≥90% 自动 / 60-90% 确认 / <60% 追问)

dispatcher 中用 0.85/0.60 阈值三路分发

Heartbeat Cron 定时任务

cron 每 6h 拉 ICS + 同步看板

端侧优先、本地存储

OpenClaw 本地运行,memory 文件本地存储

结构化日程数据库

Neon Postgres(看板服务端)

产品架构中"家庭成员管理"、"冲突检测引擎"、"多端同步"、"路程计算提醒"等能力在个人 MVP 中暂未实现,留待后续扩展。

七、落地经验总结

7.1 架构设计层面

  1. 先定幂等契约再写逻辑source + externalId 的幂等设计是整个系统最重要的基础设施。它让上游可以放心重试,让同步可以全量覆盖,让 Skill 不需要记住"上次写过没有"。

  2. Skill 拆分粒度:一个 Skill 只做一件事:event-parser 只做解析不做决策,calendar-board-sync 只做写入不做判断,dispatcher 只做协调不做解析。拆开之后任何一个 Skill 坏了都不影响全局,而且每个 Skill 可以独立测试。

  3. 两条管线互不依赖:对话管线和 ICS 管线共享底层写入模块(calendar-board-sync),但上游完全独立。ICS 服务挂了不影响用户对话日程,用户不说话时 ICS 照常同步。

  4. 置信度是产品决策,不只是技术指标:置信度的阈值直接决定了用户体验——太严则用户觉得"怎么老问我",太松则出现误写。0.85 这个数字是调出来的,不是拍出来的。

7.2 开发方式层面

  1. Vibe Coding 适合这类项目:需求明确、技术栈确定、前后端一体——这种项目让 AI 来写代码效率极高。关键是先把需求文档写清楚,AI 写代码的质量直接和需求描述的清晰度正相关。

  2. preview 页面是好实践:前端 UI 不应该在完整链路上调试。独立的 preview 页面 + 测试数据,能让 UI 迭代速度快 5 倍以上。

  3. AI 生成对接文档 → 另一个 AI 去对接:看板开发完成后,让 Claude 生成 Skill 对接文档,再把文档给 OpenClaw(龙虾)去自己建技能。两个 AI 通过文档协作,人只需要做审核。

7.3 工程实践层面

  1. Token 文件不进版本控制:所有凭据走 .openclaw-token.local + 环境变量,gitignore 兜底。即使是个人项目也不能在安全上偷懒。

  2. Cron 错峰 5 分钟:两个定时任务有依赖关系时,后者错峰几分钟比"检测前者是否完成"简单可靠得多。

  3. 版本轮询优于定时全量刷新:绝大多数时间数据不变,轮询一个 int 版本号的开销是请求完整 dashboard 数据的 1/100。

八、后续演进方向

参考产品技术架构文档中的三阶段规划,下一步的重点:

  1. 扩展到家庭场景:引入家庭成员 Profile、人员归属识别、可见性控制

  2. 冲突检测:当新日程和已有日程时间重叠时主动告警

  3. 主动提醒:基于 Heartbeat 机制做晨间日程摘要和出门时间提醒

  4. 更多数据源:Google Calendar CalDAV 双向同步、邮件日程解析

  5. 向内部智能体平台迁移:当前基于 OpenClaw 标准接口开发,后续可迁移到内部平台,Skill 逻辑无需重写