STARDUSTLC666/dsh-calendar

DeepSeek Harness日历插件:calendar_list/create/update/delete/search五个工具,支持CalDAV协议,兼容Google/iCloud/Nextcloud/自定义端点,RRULE重复事件自动展开,插件级proxyUrl代理,配置缺失不崩溃启动;纯Node全平台。· 适用于DeepSeek Harness代理的CalDAV日历工具。

Project Overview项目介绍

dsh-calendar is a DSH plugin that enables models to read and write calendar events via CalDAV, exposing five tools: list, create, update, delete, and search. It supports Google, iCloud, Nextcloud, and any CalDAV-compatible server, automatically expanding recurring events into individual instances. Use it when an agent needs to schedule, query, or modify calendar entries conversationally. Configuration lives entirely in cordis.patch.yml using Basic auth (app-specific passwords), with no web settings UI; Google and iCloud require a proxyUrl.

dsh-calendar 是 DSH 社区插件,通过 CalDAV 让模型读写日历事件,提供 list、create、update、delete、search 五个工具,支持 Google、iCloud、Nextcloud 及任意 CalDAV 服务器,重复日程自动展开为独立实例。适用于让智能体在对话中排期、查日程、修改或删除事件。配置全部在 cordis.patch.yml,需 Basic 认证(应用专用密码),无 Web 设置页;Google 与 iCloud 需配置 proxyUrl。

Or use CLI install (for developers)或使用命令行安装(适合开发者)

CLI Install命令行安装

dsh plugin --profile web add dsh-calendar

STARDUSTLC666/dsh-calendar 加入你的 DSH 配置(web profile)即可启用。

READMEREADME

English

dsh-calendar

agent 从此会排期:CalDAV 读写日历,重复日程自动展开。

npm version npm downloads license stars

Awesome DSH Plugin

DSH 社区插件:通过 CalDAV 读写日历事件。提供 5 个日历操作工具(calendar_list / calendar_create / calendar_update / calendar_delete / calendar_search)和 calendar_health 配置自检。Google 使用 OAuth 2.0;iCloud / Nextcloud / 自定义服务器默认保留 Basic 认证。不含设置页 UI,配置全部走 profile 的 cordis.patch.yml。

兼容性

已在官方 @deepseek-ai/dsh@0.1.5-rc.1、Node 24.16.0 上验证(2026-09-11):18 个组件与 Modlens 同载,工具 schema、技能注册及离线只读调用检查通过。采用 cordis.patch.yml + dsh.bundle.patch 组合包模型。Node 要求与该版本 Harness 一致:22.19 及以上的 22.x,或 24 及以上。外部服务的实际业务操作需按各组件配置单独验证。

2026-09-10,npm dsh-calendar@0.5.2 已通过该 Harness 的官方 CLI 安装和 6 个工具注册;经宿主执行 calendar_list,真实 Google 令牌刷新返回 200、CalDAV REPORT 返回 207,并生成模型可读结果。验证仅含 Google 读取,未执行写入;本次补丁不修改运行时代码。

遵循官方插件打包与安装要求:ESM 入口、预构建 lib/dsh.bundle.patchcordis.patch.yml 配置层;显式注入 tools,提供 JSON Schema 参数、规范化输出和渲染函数,运行时不 import @deepseek-ai/* 内部模块。使用 Node 22.19 及以上的 22.x 或 Node 24 及以上版本;Harness 仍在快速迭代,上述版本是实测基线。

安装

dsh plugin --profile web add dsh-calendar

安装后重启 dsh。插件会向 profile 插入一行 id 为 calendar 的配置行(见本包的 cordis.patch.yml)。默认 provider 为 custom 且未填任何凭证,此时插件照常加载,但工具在调用时会抛出中文指引错误,提示你补全配置。

配置

所有配置都在你的 profile 的 cordis.patch.yml 里,按 id 覆盖 calendar 行(覆盖整行的 config)。通用字段:

  • provider:google | icloud | nextcloud | custom
  • caldavUrl:完整日历集合 URL(custom / icloud 必填;google / nextcloud 也可手填覆盖预设)
  • authMethodbasic | oauth;Google 默认且必须为 oauth,其他 provider 默认 basic。其他 OAuth 服务器需显式设置 oauth,不会因环境中存在 Google 凭据而自动切换。
  • username / password:仅 Basic 认证必需。iCloud 请用应用专用密码;密码推荐用环境变量 DSH_CALENDAR_PASSWORDGoogle CalDAV 不接受任何 Basic 密码,包括应用专用密码。
  • clientId / clientSecret / refreshToken:OAuth 必需;分别支持 DSH_CALENDAR_CLIENT_ID / DSH_CALENDAR_CLIENT_SECRET / DSH_CALENDAR_REFRESH_TOKEN。非空配置值优先于环境变量。请勿把密钥或令牌提交到 Git。
  • tokenUrl:可用 DSH_CALENDAR_TOKEN_URL;Google 默认 https://oauth2.googleapis.com/token,其他 OAuth 服务必填。OAuth 的 tokenUrl 与 caldavUrl 必须为不含内嵌账号密码、查询参数或片段的 HTTPS 地址。
  • proxyUrl:可选 HTTP 代理地址(如 http://127.0.0.1:7890);令牌刷新和 CalDAV 请求共用该代理。可直连时无需填写。
  • calendarId:google 专用,日历 ID(通常是你的邮箱)
  • host / user / calendar:nextcloud 专用

卸载

dsh plugin --profile web remove dsh-calendar

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

中国用户:特殊代理配置(Google / iCloud)

若本机网络无法直连 Google / iCloud,插件内置的 proxyUrl 可把 OAuth 令牌请求和 CalDAV 请求路由到你本机 HTTP 代理客户端的端口,不影响其他插件,也无需改任何系统设置。

- id: calendar
  config:
    provider: google
    calendarId: you@gmail.com
    # OAuth 凭据通过下文三个环境变量提供
    proxyUrl: http://127.0.0.1:7890   # 改成你代理客户端的本地端口

常见代理客户端本地端口

客户端 本地端口
Clash / Clash Verge(HTTP) 7890 / 7897
v2rayN(HTTP / SOCKS) 10808 / 10809
Shadowsocks 1080

在客户端界面确认你的实际端口,填进 proxyUrl 即可。国内可直连的 CalDAV 服务(如自建 Nextcloud)则无需填写。

Google 示例

- id: calendar
  name: dsh-calendar
  config:
    provider: google
    calendarId: you@gmail.com
    # authMethod: oauth  # Google 默认即为 oauth
    # clientId / clientSecret / refreshToken 推荐用环境变量

Google 的 CalDAV 集合 URL 由插件拼成:https://apidata.googleusercontent.com/caldav/v2/<calendarId>/events

在启动源码版 pnpm dsh 或普通 dsh 的同一个终端中设置(以下均为占位值):

export DSH_CALENDAR_CLIENT_ID='你的 OAuth 客户端 ID'
export DSH_CALENDAR_CLIENT_SECRET='你的 OAuth 客户端密钥'
export DSH_CALENDAR_REFRESH_TOKEN='你授权后取得的 refresh token'

凭据必须来自你自己的 Google Cloud OAuth 客户端和一次用户授权,而不是邮箱应用专用密码。按 Google CalDAV 官方设置说明 启用 API、配置 OAuth;申请日历读写范围 https://www.googleapis.com/auth/calendar,并请求离线访问(access_type=offline)以取得刷新令牌,参见 Google 离线授权说明。尚未提供浏览器一键登录或独立登录 CLI;已有 OAuth 配置的用户可直接填入刷新令牌。

Google CalDAV 范围实测(2026-09-08):同一账号与日历使用 calendar.readonly 时,令牌刷新返回 200、集合探测 PROPFIND 返回 207,但读取日程 REPORT 返回 403;改为上述 calendar 范围后,REPORT 返回 207,重启验证进程后再次刷新和读取也通过。因此,请按这里的 CalDAV 配置申请范围,并用 calendar_list 验证真实读取,不能只凭令牌获取成功或集合探测成功判断日程可读。本次真实测试仅执行读取,没有验证 Google 的写入操作。

calendar 范围允许查看、修改、分享及删除可访问的日历,申请前请确认接受该权限范围,详见 Google 权限定义。外部 OAuth 应用处于 Testing 状态时,包含日历权限的刷新令牌会在 7 天后过期;长期使用需处理重新授权或按 Google 要求配置生产状态,详见 刷新令牌到期规则

插件在内存中缓存访问令牌,并在每次 DAV 请求前检查有效期、提前刷新;令牌请求与 DAV 请求都会透传调用的取消信号。401 会使缓存失效,下一次调用重新刷新,不会自动重放写请求。OAuth 请求不跟随重定向、不向其它源的对象 href 发送 Bearer token,请填写最终日历集合地址。运行时令牌不会写入配置或日志;若其他 OAuth 提供方轮换 refresh token,重启时需要重新提供有效凭据。

iCloud 示例

- id: calendar
  name: dsh-calendar
  config:
    provider: icloud
    username: you@icloud.com
    caldavUrl: https://caldav.icloud.com/123456789/calendars/<日历ID>/
    # password 推荐用环境变量 DSH_CALENDAR_PASSWORD

iCloud 需要完整日历集合 URL(含你的用户 ID 与日历 ID),在 icloud.com 的日历 CalDAV 设置里可找到具体日历地址。

Nextcloud 示例

- id: calendar
  name: dsh-calendar
  config:
    provider: nextcloud
    username: alice
    host: https://cloud.example.com
    user: alice
    calendar: personal
    # password 推荐用环境变量 DSH_CALENDAR_PASSWORD

插件会拼成:https://cloud.example.com/remote.php/dav/calendars/alice/personal/

自定义 CalDAV 示例

- id: calendar
  name: dsh-calendar
  config:
    provider: custom
    caldavUrl: https://dav.example.com/calendars/me/work/
    username: me
    # password 推荐用环境变量 DSH_CALENDAR_PASSWORD

认证失败排查

Google:仅支持 OAuth 2.0。401/403 时检查 OAuth 授权、日历范围与日历访问权限;如果令牌刷新和 PROPFIND 成功而 REPORT 返回 403,核对实际授予的范围是否为上述 calendar,不要将 calendar.readonly 的集合探测成功当作日程读取成功。令牌刷新失败时核对 clientId/clientSecret/refreshToken,授权被撤销或过期时重新授权,并检查是否仍处于 Testing 的 7 天期限内。重新生成应用专用密码不能解决 Google CalDAV 认证失败。

iCloud:登录 appleid.apple.com → 登录与安全 → App 专用密码,生成后填到 passwordDSH_CALENDAR_PASSWORD。不能用你的 Apple ID 密码。

Nextcloud / 自定义 Basic 服务:检查账号、密码或服务要求的应用令牌及日历权限。calendar_health 只检查配置完整性,不联网、不证明授权成功;请再用 calendar_list 验证真实连接。

工具清单

  • calendar_health:离线检查服务商、日历集合地址与 Basic/OAuth 凭据完整性,不回显密钥、不发起网络连接。
  • calendar_list:列出某时间段事件(start/end,ISO 8601,缺省未来 7 天)。默认展开重复事件(expand 默认 true,maxOccurrences 默认 30、clamp 1-200):每个实例独立成行,带 isOccurrence: trueseriesStart;非重复事件保持 isOccurrence: falseexpand=false 时重复事件按原始单条返回并带 rrule。结果按开始时间稳定排序
  • calendar_create:新建事件(summary/start/end 必填,description/location/allDay/rrule 可选)。严格校验真实日历日期与 end >= start
  • calendar_update:按 uid 改事件(summary/start/end/description/location/allDay/rrule 可选,未提供保留原值,重复规则不再丢失)
  • calendar_delete:按 uid 删事件
  • calendar_search:按关键词搜事件(客户端过滤标题/描述/地点/UID,不区分大小写;limit 默认 50、clamp 1-200,结果按开始时间排序)

事件稳定标识 uid 为 CalDAV href(完整对象 URL),calendar_update / calendar_delete 使用它。

时间与时区

输入输出统一 ISO 8601。定时事件输出为 UTC(如 2025-01-15T01:00:00Z),全天事件输出 YYYY-MM-DD。输入可带时区偏移(如 2025-01-15T09:00:00+08:00),插件内部转 UTC 存储。

版本记录

  • 0.5.3(2026-09-11):复验官方 Harness 0.1.5-rc.1,更新整套同载与真实服务验证记录;运行时代码未变。
  • 0.5.2(2026-09-08):补充官方 Harness 0.1.3-alpha.2 的安装、加载与真实 Google 工具调用验证,更新兼容性和 Node 版本要求;运行时代码与 0.5.0 相同。
  • 0.5.1(2026-09-08):补充真实 Google OAuth/CalDAV 读取验证、calendar.readonlycalendar 范围对比及 Testing 刷新令牌到期说明;运行时代码与 0.5.0 相同。
  • 0.5.0(2026-09-07):修复 Google CalDAV #2:新增 OAuth 凭据与环境变量配置、请求时刷新、取消与代理透传;健康检查区分 Basic/OAuth,修正误导的应用专用密码说明。保留其他服务的 Basic 认证。
  • 0.4.0:新增 calendar_health 自检(离线检查 CalDAV 端点与凭据配置,不验证连接)。
  • 0.3.2
    • 修复 calendar_update 更新其他字段时丢失 rrule 的问题。
    • 更新与新建都会校验 end >= start,并拒绝 2025-02-30 这类不存在的日期。
    • calendar_list / calendar_search 输出按开始时间稳定排序;搜索 limit clamp 到 1-200。
    • CalDAV 客户端创建失败后清空缓存,下一次调用可自动重试,不再永久复用 rejected promise。

已知限制

  • 网络可达性:若无法直连,可用 proxyUrl 指定本机 HTTP 代理,或改用可直连的 CalDAV 端点。

  • 重复事件展开:calendar_list 默认用 ICAL.RecurExpansion 展开 RRULE(expand=true),受 maxOccurrences 封顶;calendar_search 仍返回原始系列(不展开)。

  • 不支持单次实例的改/删:calendar_update / calendar_delete 针对整个重复系列(按 uid 操作),无法只修改或删除某一次发生(不支持 RECURRENCE-ID 实例级操作)。

  • OAuth 凭据需要事先取得:支持刷新令牌认证,但不提供浏览器登录 UI / 登录 CLI,也不把运行时令牌写回配置文件。

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

  • 无设置页 UI:本轮为 node 半身,配置只走 cordis.patch.yml,不提供 Web 设置页。

  • 日历发现:iCloud 需手动填完整日历集合 URL;不做 principal 自动发现与多日历选择。

  • 取消/超时:工具使用 timeoutMs(60 秒),并向令牌刷新与 DAV 网络请求透传宿主 AbortSignal;并发调用独立取消。

开发

pnpm install
pnpm test   # 构建 + node --test

构建产物在 lib/,测试在 test/*.test.mjs(不依赖真实账号)。

相关插件

上一个 Prev dsh-crw 下一个 Next dsh-omv