贰 · 推送
钉钉推送
ctx.dingtalk
通过钉钉 dws CLI 发送文本 / Markdown 消息,支持 user / bot / webhook 身份、群聊 / 单聊 / 多群、@ 人、幂等键和 dryRun。
接口
const r = await ctx.dingtalk.send({
markdown: '## 标题\n正文', // 或 text: '纯文本',二选一
title: '标题',
target: { chatId: 'cid...' }, // 或 { userId } / { openDingtalkId } / { chatIds: [...] }(仅 bot)
at: { userIds: ['...'], all: false }, // 另有 openDingtalkIds(user / bot)、mobiles(仅 webhook)
idempotencyKey: 'evt_...',
traceId: 'evt_...',
signal, // 可选,中止时终止 dws 子进程
})
// r.results: Array<{ target, ok, messageId?, error? }>本 Service 通过子进程调用 dws chat +messages-send:
- 不经过 shell,参数统一写成
--key=value形式,以-开头的正文也不会被当成选项。 - 固定附加
--yes --format=json,常驻进程不会卡在交互确认上。 - 子进程只继承环境变量白名单,本包的其他密钥不会传给 dws。
- 超时或卸载时先发 SIGTERM,宽限
killGraceMs后发 SIGKILL,连同孙进程一起回收(Windows 上用taskkill /T /F)。
目标与身份
target 省略时使用配置的 defaultTarget;单次调用的 target 会覆盖它,多个业务包共用本包时互不影响。目标、@ 列表与幂等键在拼装参数前做格式校验,以 - 开头的值会被拒绝(invalid_target)。
| 身份 | chatId | chatIds | userId | openDingtalkId | @ 参数 | 幂等键 |
|---|---|---|---|---|---|---|
user | 支持 | 不支持 | 支持 | 支持 | openDingtalkIds、all | 支持 |
bot | 支持 | 支持,最多 100 个 | 支持 | 支持 | userIds、openDingtalkIds、all | 忽略 |
webhook | 不传 target,目标由 token 所在群决定 | userIds、mobiles、all | 忽略 |
bot 身份统一走批量参数,dws 返回逐目标结果。批量发送的部分失败甚至全部失败都不抛错,体现在 results 中。
重试
只有在 user 身份且给出 idempotencyKey 时,才会对可重试的失败(超时,或 dws 错误类别为 network / timeout / rate_limit / server / unavailable)最多重试 retry.maxAttempts 次,间隔从 500ms 起指数增长。其他情况不自动重试,避免重复发送。
登录状态与登录
const st = await ctx.dingtalk.status()
// { channel: 'dingtalk', identity: 'bot', online: true, account?: '张三', detail, checkedAt }
const s = await ctx.dingtalk.login() // { channel, verificationUrl, userCode?, expiresAt, completed, cancel() }
await postToOps(s.verificationUrl) // 由业务包决定怎么把链接交给要登录的人
const after = await s.completed // 授权完成后的状态
await ctx.dingtalk.logout() // 返回退出后的状态status():执行dws auth status实时检查。dryRun时只报告,不改变health();非dryRun时结果同时更新health()。login({ signal? }):运行dws auth login --device --no-browser,从输出中取到授权链接就返回,dws 在后台等待授权。对方授权后completed以新的状态 resolve;链接过期(15 分钟,dws 给出有效期时以它为准)、被拒绝、cancel()或signal中止时同样 resolve,online为false。登录进行中再次调用返回同一个会话。dws 在给出链接前就退出时抛出login_failed。logout():运行dws auth logout,返回退出后的状态。webhook身份没有登录:status()总是online: true,login()/logout()抛出unsupported。
登录态检查与 dryRun
- 启动时以及每隔
preflightIntervalMs执行dws auth status检查登录态。失效时health()返回failed,并触发agent-kit/service-failed事件。 dryRun: true时附加--dry-run,只做参数解析与日志、不真实发送,适合本地开发与测试;此时不检查登录态。webhook身份不检查登录态。
dwsPath 与 Windows
dwsPath 必须是绝对路径;省略时启动时从 PATH 解析。Windows 上 npm 全局安装的是 dws.cmd,本包会自动定位到它背后的 dws.js 并用 node 运行。手动配置 dwsPath 时,请指向可执行文件、.exe 或 .js,不要指向 .cmd / .bat。
配置
在 Profile 的 cordis.patch.yml 中按 id agent-kit-dingtalk 启用并给出配置。按 id 修改 config 时整段替换,未给出的字段使用默认值。下表由本包源码中的配置 schema 生成。
- id: agent-kit-dingtalk
disabled: false
config:
# 只写需要改的字段,其余使用下表的默认值 | 字段 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|
identity 必填 | — | user | bot | webhook | 发送身份;服务器环境推荐 bot |
defaultTarget | — | 见说明 | 省略 target 时使用 |
robotCode | — | — | bot 身份必填 |
webhookTokenEnv | — | 匹配 /^[A-Za-z_][A-Za-z0-9_]*$/ | webhook 身份必填:保存 token 的环境变量名 |
dwsPath | — | — | dws 可执行文件的绝对路径;默认从 PATH 解析。需指向可执行文件、.exe 或 .js(不支持 Windows 的 .cmd/.bat,因为不经过 shell 启动子进程) |
timeoutMs | 15000 | [1000, 120000] | 单次 dws 调用的超时时间。 |
killGraceMs | 5000 | ≥ 0 | 超时或卸载时,SIGTERM 之后等待多久再发 SIGKILL。 |
retry.maxAttempts | 2 | [0, 5] | user 身份且给出幂等键时,可重试失败的最多重试次数。 |
preflightIntervalMs | 3600000 | ≥ 0 | 检查 dws 登录态的间隔,0 表示只在启动时检查 |
dryRun | false | — | 附加 --dry-run,只解析参数、不真实发送;同时跳过登录态检查。 |
约束与说明
- bot 身份必须填写 robotCode;webhook 身份必须填写 webhookTokenEnv,且对应环境变量已设置。
- webhook 身份不能设置 defaultTarget:目标由 token 所在群决定。
- webhook 身份只能把 token 作为命令行参数传给 dws(会出现在 ps 中),不推荐使用。
- 自动重试只在 user 身份且给出 idempotencyKey 时进行,避免重复发送。
- status() 实时检查登录态;login() 发起设备流登录,拿到授权链接即返回,由业务包决定怎么交给要登录的人;logout() 退出登录。webhook 身份的 login() / logout() 报 unsupported。
- dws 的登录态是本机共享的,同一系统用户下的其他 dws 程序也会看到登录与退出;logout() 只退出当前账号(--profile=<corpId>:<userId>)。
错误码
所有错误都是 KitError:用 isKitError(e) 判断,按 code 与 retryable 决定是否重试。
| code | 可重试 | 含义 |
|---|---|---|
timeout | 是 | dws 超时,子进程按「先 SIGTERM、宽限后 SIGKILL」回收。 |
exit_nonzero | 视情况 | dws 非零退出;按 dws 错误类别(network / timeout / rate_limit / server / unavailable)判断是否可重试。 |
bad_output | 否 | dws 输出无法解析。 |
invalid_target | 否 | 目标、@ 列表或幂等键格式非法,或与身份不匹配。 |
send_failed | 否 | dws 报告发送失败(批量发送时体现在逐目标结果中)。 |
aborted | 否 | 调用方 signal 中止或 Service 卸载。 |
spawn_failed | 否 | 无法启动 dws 子进程。 |
unsupported | 否 | webhook 身份调用 login() / logout():该身份没有登录。 |
login_failed | 否 | dws auth login 在给出授权链接之前就结束了。 |
invalid_config | 否 | 配置或环境变量非法,Service 启动失败。 |