dsh-calendar:给 DSH 接入 CalDAV 日历工具

前言

在 DSH 智能体场景里,模型经常需要查询“今天有哪些日程”“明天上午是否有空”,或者把一条待办落成日历事件。如果每次都要人工导出日历文本、截图或手写同步脚本,模型就很难直接参与排期。

dsh-calendar 是一个 DSH 社区插件,通过 CalDAV 读写日历事件,支持 Google、iCloud、Nextcloud 及任意自定义 CalDAV 服务器。DSH 生态强调“一切皆插件”;这里介绍的是社区插件,不是官方应用商店内置能力。

插件概览

dsh-calendar 解决的问题很明确:把日历事件能力封装成 DSH 可以调用的模型工具。

它提供五个面向模型的工具:

  • calendar_list:列出某时间段内的事件
  • calendar_create:新建事件
  • calendar_update:按 uid 更新事件
  • calendar_delete:按 uid 删除事件
  • calendar_search:按关键词搜索事件

几个关键事实如下:

  • GitHub 仓库:https://github.com/STARDUSTLC666/dsh-calendar
  • 许可证:MIT
  • 运行要求:Node >=22
  • 认证方式:Basic 认证,使用应用专用密码
  • 不支持 Google / iCloud OAuth 登录流程
  • 无设置页 UI,配置走 profile 的 cordis.patch.yml
  • 事件稳定标识 uid 使用 CalDAV href

安装与启用

先在目标 profile 中安装插件:

dsh plugin --profile web add dsh-calendar

安装后重启 dsh

默认配置通常没有填写任何凭证,此时插件可以正常加载,但工具在调用时会返回中文指引错误,提示补全配置。配置位置是当前 profile 的 cordis.patch.yml,按 id 覆盖 calendar 行的 config

一个最小示例:

- id: calendar
  config:
    provider: custom
    caldavUrl: https://dav.example.com/calendars/me/work/
    username: me
    password: 你的应用专用密码

如果不想把密码写进 YAML,可以使用环境变量 DSH_CALENDAR_PASSWORD

卸载命令如下:

dsh plugin --profile web remove dsh-calendar

卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile cordis.patch.yml 中的对应插件行。

配置字段

所有配置都在 cordis.patch.ymlcalendar 行里。常用字段如下:

  • providergoogleicloudnextcloudcustom
  • caldavUrl:完整日历集合 URL。customicloud 必填;google / nextcloud 也可以手动填写以覆盖预设
  • username:CalDAV 账号。Google / iCloud 一般填账号邮箱
  • password:密码。Google / iCloud 请使用应用专用密码
  • proxyUrl:本机代理地址。中国大陆访问 Google / iCloud 的 CalDAV 端点时可能需要
  • calendarId:Google 专用,日历 ID,通常可以是你的邮箱
  • host:Nextcloud 专用,例如 https://cloud.example.com
  • user:Nextcloud 专用,CalDAV 用户
  • calendar:Nextcloud 专用,日历名

典型用法

Google 日历

Google 示例如下:

- id: calendar
  config:
    provider: google
    username: you@gmail.com
    calendarId: you@gmail.com
    # 也可以改用 DSH_CALENDAR_PASSWORD
    password: 你的应用专用密码

Google 的 CalDAV 集合 URL 由插件拼成:

https://apidata.googleusercontent.com/caldav/v2/<calendarId>/events

Google 需要使用应用专用密码,不能使用 Google 登录密码。

iCloud 日历

iCloud 示例如下:

- id: calendar
  config:
    provider: icloud
    username: you@icloud.com
    caldavUrl: https://caldav.icloud.com/123456789/calendars/<日历ID>/
    # 也可以改用 DSH_CALENDAR_PASSWORD
    password: 你的应用专用密码

iCloud 需要手动填写完整日历集合 URL,包含用户 ID 和日历 ID。插件不做 principal 自动发现,也不做多日历选择。

iCloud 同样需要使用应用专用密码,不能使用 Apple ID 登录密码。

Nextcloud 日历

Nextcloud 示例如下:

- id: calendar
  config:
    provider: nextcloud
    username: alice
    host: https://cloud.example.com
    user: alice
    calendar: personal
    # 也可以改用 DSH_CALENDAR_PASSWORD
    password: 你的应用专用密码

插件会拼成类似:

https://cloud.example.com/remote.php/dav/calendars/alice/personal/

自定义 CalDAV

自定义 CalDAV 示例如下:

- id: calendar
  config:
    provider: custom
    caldavUrl: https://dav.example.com/calendars/me/work/
    username: me
    # 也可以改用 DSH_CALENDAR_PASSWORD
    password: 你的应用专用密码

这种方式适合自建 Radicale、Nextcloud 或其他提供标准 CalDAV 的服务器。

工具行为

calendar_list

calendar_list 用于列出某时间段内的事件。

支持参数:

  • start / end:ISO 8601 时间
  • expand:是否展开重复事件,默认 true
  • maxOccurrences:重复事件展开数量上限,默认 30,范围 1-200

默认情况下,calendar_list 会展开重复事件。展开后的实例会带:

  • isOccurrence: true
  • seriesStart

非重复事件会保持:

  • isOccurrence: false

如果设置 expand=false,重复事件会按原始单条返回,并带 rrule

结果按开始时间稳定排序。

calendar_create

calendar_create 用于新建事件。

必填字段:

  • summary
  • start
  • end

可选字段:

  • description
  • location
  • allDay
  • rrule

插件会校验真实日历日期,并要求 end >= start。例如 2025-02-30 这类不存在的日期会被拒绝。

calendar_update

calendar_updateuid 更新事件。

可更新字段包括:

  • summary
  • start
  • end
  • description
  • location
  • allDay
  • rrule

未提供的字段保留原值。重复规则不会因为更新其他字段而丢失。

calendar_delete

calendar_deleteuid 删除事件。

calendar_search 用于按关键词搜索事件。

它会对标题、描述、地点、UID 做客户端过滤,不区分大小写。

支持参数:

  • 关键词
  • limit:默认 50,范围 1-200

结果按开始时间排序。

需要注意:calendar_search 返回原始系列,不展开重复事件。

重复事件限制

calendar_updatecalendar_deleteuid 操作整个重复系列。

这意味着它们适合修改或删除整个重复日程,但不支持只修改或删除某一次发生。换句话说,不支持 RECURRENCE-ID 实例级修改或删除。

如果你需要“只取消周三那一次”,这个插件目前不能直接做到。

时区与时间格式

输入输出统一使用 ISO 8601。

  • 定时事件输出为 UTC,例如:
2025-01-15T01:00:00Z
  • 全天事件输出为日期格式:
2025-01-15

输入可以带时区偏移,例如:

2025-01-15T09:00:00+08:00

插件内部会转成 UTC 存储。

TZID 命名时区的事件输出会转成 UTC。全天边界、夏令时等复杂时区规则不做精细化处理。

代理与网络限制

中国大陆访问 Google 与 iCloud 的 CalDAV 端点不可直连。可以使用 proxyUrl 配置本机代理。

示例:

- id: calendar
  config:
    provider: google
    username: you@gmail.com
    calendarId: you@gmail.com
    password: 你的应用专用密码
    proxyUrl: http://127.0.0.1:7890

这里的 proxyUrl 填你本机代理客户端实际暴露的 HTTP 端口。国内可直连的 CalDAV 服务,例如自建 Nextcloud 或其他私有 CalDAV,通常不需要配置代理。

工具整体超时为 60 秒。插件不在单次网络请求上透传 AbortSignal

适用场景

dsh-calendar 比较适合这类场景:

  • 你使用 DSH 做智能体或助手,希望模型能直接查询日历
  • 你需要模型创建、更新、删除或搜索日程
  • 你已有 Google、iCloud、Nextcloud 或其他 CalDAV 服务
  • 你可以通过 cordis.patch.yml 维护插件配置
  • 你接受当前版本没有 Web 设置页,配置直接写在 YAML 中

注意事项

使用前建议注意以下几点:

  1. 插件会以当前 dsh 进程权限运行,安装前建议检查源码与许可证。
  2. 只支持 Basic 认证,不支持 Google / iCloud OAuth。
  3. Google / iCloud 必须使用应用专用密码,不能用登录密码。
  4. calendar_updatecalendar_delete 针对整个重复系列,不支持单次实例级操作。
  5. calendar_search 不展开重复事件。
  6. iCloud 需要手动填写完整日历集合 URL。
  7. 没有设置页 UI,所有配置走 cordis.patch.yml
  8. 如果调用返回 401 / 403,优先检查是否误用了登录密码。

结尾

dsh-calendar 的价值在于把 CalDAV 日历能力封装成五个稳定的模型工具,让 DSH 智能体可以直接完成查日程、建日程、改日程、删日程和搜日程这些动作。

GitHub 仓库:

https://github.com/STARDUSTLC666/dsh-calendar
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜