first commit
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
---
|
||||
name: dingtalk-event
|
||||
description: 钉钉个人 IM 与 OA 审批事件长连接监听。Use when 用户说监听消息/@我/某人/某群/全部消息、已读/撤回/reaction、群成员加入/群成员退出/群状态变化,或监听审批任务创建/完成/转交、审批实例发起/抄送/终止/完成。命令前缀:dws event。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉个人 IM 与 OA 审批事件
|
||||
|
||||
> **前置:执行 `dws` 前必须完整读取 [`dingtalk-shared`](../dingtalk-shared/SKILL.md)。**Shared references 仅按需加载。
|
||||
|
||||
本 Skill 只负责未来个人 IM/OA 实时事件;发送和历史消息走 `dingtalk-chat`,审批查询与处理走 `dingtalk-misc` 的 OA,开放平台应用事件配置走其 DevApp。子 reference 按需加载。
|
||||
|
||||
实时监听必须使用事件长连接,不写轮询脚本,不用历史消息或审批列表查询模拟事件。高频 IM 意图优先交给 `dws event +listen-im`;它在 CLI 内解析自然目标、选择 EventKey,并复用现有订阅与 bus 生命周期。OA 审批事件使用显式 `dws event consume`。
|
||||
|
||||
<!-- dws-intent: event.listen.im -->消息、reaction、已读和撤回的默认监听入口是 `dws event +listen-im`;
|
||||
只有群生命周期、Filter DSL、原始 envelope 或底层订阅控制才使用
|
||||
`event consume` fallback。
|
||||
|
||||
<!-- dws-intent: event.listen.oa -->OA 审批任务与审批实例的实时变化使用 `dws event consume`;查询或操作已有审批走 `dws oa`,不要用轮询模拟事件。
|
||||
|
||||
## Golden Route
|
||||
|
||||
| 用户意图 | 唯一推荐入口 |
|
||||
|---|---|
|
||||
| 监听 @我的消息 | `dws event +listen-im --kind at-me` |
|
||||
| 监听某人发来的消息 | `dws event +listen-im --kind sender --user-query <姓名>` |
|
||||
| 监听指定群消息 | `dws event +listen-im --kind group --chat-query <群名>` |
|
||||
| 同一人/群的消息、表情、已读或撤回 | `dws event +listen-im --kind <sender|group> --events message,reaction,read,recall ...` |
|
||||
| 监听全部单聊或全部群消息 | `dws event +listen-im --kind <all-direct|all-group>`;只有用户明确要求“全部”时使用 |
|
||||
| 群改名、成员进退、群解散 | 读取 [EventKey 索引](references/event-im-keys.md),使用精确 `event consume` EventKey |
|
||||
| OA 审批任务或实例事件 | 读取 [OA 事件参考](references/event-oa.md),使用精确 `event consume` EventKey |
|
||||
| 查看 OA 事件目录 | `dws event list --category oa` |
|
||||
| 已知 EventKey 或需要底层订阅控制 | `dws event consume`;参数与约束以 leaf Schema 为准 |
|
||||
| 查看状态 / 停止 | `dws event status` / `dws event stop <subscribe_id> --dry-run`,确认后再 `--yes` |
|
||||
|
||||
默认 `--events message`。可选事件为 `message`、`reaction`、`read`、`recall`:
|
||||
|
||||
- `at-me`、`all-direct`、`all-group` 只支持 `message`,且不接受目标。
|
||||
- `sender` 必须且只能传 `--user`、`--open-dingtalk-id` 或 `--user-query` 之一。
|
||||
- `group` 必须且只能传 `--chat-id` 或 `--chat-query` 之一。
|
||||
- `--query` 只用于纯 `message` 监听;混入 reaction/read/recall 时不得使用。
|
||||
|
||||
OA 事件不进入 `+listen-im`。七个公开 OA EventKey 都订阅当前 OAuth 用户相关的全部审批事件,使用 `ruleType=all`、`filterRule={}`;不接受 `--user`、`--open-dingtalk-id`、`--group`、`--query` 或 `--filter-json`。七项可放入同一个 consume,每项建立独立订阅并共享 bus。
|
||||
|
||||
自然姓名和群名由 CLI 内部唯一解析:零命中或多候选返回结构化失败,在创建任何订阅前停止。`--dry-run` 走同一解析链。解析、监听、状态和停止必须使用同一个 `--profile`,不得跨组织搬运 ID。
|
||||
|
||||
### 兼容 EventKey 索引
|
||||
|
||||
`+listen-im` 覆盖高频路径;只有需要精确底层控制时才直接使用以下 16 个 EventKey:
|
||||
|
||||
```text
|
||||
user_im_message_receive_at
|
||||
user_im_message_receive_o2o user_im_message_receive_user
|
||||
user_im_message_receive_group user_im_message_receive_o2o_all
|
||||
user_im_message_receive_group_all user_im_message_read_o2o
|
||||
user_im_message_read_group user_im_message_recall_o2o
|
||||
user_im_message_recall_group user_im_message_reaction_o2o
|
||||
user_im_message_reaction_group user_im_group_updated
|
||||
user_im_group_member_added user_im_group_member_exited
|
||||
user_im_group_disbanded
|
||||
```
|
||||
|
||||
七个 OA EventKey 及其输出字段见 [OA 事件参考](references/event-oa.md)。
|
||||
|
||||
用户类事件传 `--user` 或 `--open-dingtalk-id`,群类事件传 `--group`。群生命周期输出可含 `operator_open_dingtalk_id` 和 `members`;成员项使用 `open_dingtalk_id`。精确组合、兼容性和 Filter 规则见 reference。
|
||||
|
||||
## 公开层与内部统一边界
|
||||
|
||||
`+listen-im` 是意图编译层,不是第二套事件系统。它只负责:
|
||||
|
||||
```text
|
||||
kind + events + target
|
||||
→ typed resolver
|
||||
→ 确定 EventKey 集合
|
||||
→ 一次 event consume 生命周期
|
||||
```
|
||||
|
||||
订阅创建/复用、单 bus、多 consumer、ready marker、扁平 NDJSON、超时/取消、部分失败回滚和退出清理全部复用现有 Runtime。低频 EventKey、群生命周期、OA 审批、Filter DSL、原始 envelope、复用 subscribe_id 等仍由 `event consume` 承担。
|
||||
|
||||
## 运行与结果契约
|
||||
|
||||
- 正常消费固定使用当前用户 OAuth 身份、`--flatten` 和 NDJSON;stdout 只输出事件,stderr 输出订阅、ready、退出和错误状态。
|
||||
- 单事件 ready:`[event] ready event_key=<key> bus_pid=<pid> subscribe_id=<id>`。
|
||||
- 多事件先逐条输出 subscription,全部就绪后输出 `[event] ready event_count=<n> bus_pid=<pid>`。必须等待 ready,不用 `sleep` 猜测。
|
||||
- 有界任务使用 `--max-events N` 或 `--duration 10m`;无界任务需要宿主管理进程并持续读取 stdout。
|
||||
- 干净退出会取消本次新建的订阅;使用 SIGTERM、关闭符合条件的管道 stdin,或 Runtime 的 bounded exit。不要 `kill -9`。
|
||||
- 当前用户自己发送的消息会被 self-loop 过滤;自测事件应由另一用户或机器人发送。
|
||||
- 事件只负责监听;需要回复时按 [输出与 Chat 交接](references/event-im-output.md) 把真实 `conversation_id` 或 `sender_open_dingtalk_id` 交给 `dws chat +messages-send`,不要从显示名猜 ID。
|
||||
- 扁平消息/动作字段按事件类型读取:已读为 `reader_open_dingtalk_id`,撤回为 `recaller_open_dingtalk_id`,回应为 `reaction_name`、`operation_type`。媒体优先通过聊天读取命令加 `--download-resources`;已知消息 ID 的底层降级入口是 `dws chat message download-media`。
|
||||
- OA 扁平事件提供审批实例、任务和状态字段;字段差异、原始回退条件及与 OA 命令的稳定 ID 交接以 [OA 事件参考](references/event-oa.md) 为准。
|
||||
|
||||
## 安全与失败处理
|
||||
|
||||
- `event stop` 会取消订阅并影响本地 consumer:先 `--dry-run`,用户确认后再加 `--yes`。
|
||||
- 多事件属于一次原始操作;任一订阅启动失败时 Runtime 回滚本次已创建项,不拆成新命令绕过重试预算。
|
||||
- 这套 `0/2/1` 是 **Agent/host** 编排预算,适用于全部 23 个公开个人 EventKey(16 个 IM + 7 个 OA):`retryable=false` 对应 `max_additional_attempts=0`;`retryable=true` 对应 `max_additional_attempts=2`;`retryable=unknown` 对应 `max_additional_attempts=1`。它不是 CLI 持久化硬总次数上限;每次调用最多创建一次,进程内不会自动重试,CLI 也不持久化或计算跨调用的 Agent/host 尝试次数。
|
||||
- 重试必须遵守 `retry_after_seconds` / `next_retry_at`。遇到 `in_flight`、`cooldown`、`terminal_hold` 不并发或递归重启同一逻辑订阅,也不换 `subscribe_id` / `trace_id` 绕过保护。
|
||||
- 认证、profile、订阅保护状态和 bus 排障按失败类型读取 [订阅运维](references/event-im-operations.md),不要在正常路径预加载完整运维手册。
|
||||
|
||||
### 本地订阅保护契约
|
||||
|
||||
- open 版状态路径为 `~/.dws/events/open/personal_stream/<identity_hash>/personal_subscription_attempts.json`;设置 `DWS_CONFIG_DIR` 后根目录随之变化。
|
||||
- identity 目录权限为 `0700`;`personal_subscription_attempts.json` 与 `personal_subscription_attempts.lock` 权限为 `0600`。
|
||||
- 连续 `24h` 无失败后重置计数;`terminal_hold` 持续 `1h`。优先等待 `next_retry_at`,不要把删状态当常规重试。
|
||||
- 仅在确认该 identity 没有订阅创建进程的紧急恢复场景,只删除 `personal_subscription_attempts.json`,不要删除 lock 文件。该操作会清空该 identity 的全部保护记录,而非单个事件。
|
||||
|
||||
## 何时查询 Schema
|
||||
|
||||
- 已知 Golden Route 时直接执行,不先跑 `event list`。
|
||||
- 只有解析业务字段时才用 `dws event schema <event_key> --flatten`。
|
||||
- 只有参数或安全不确定时才用 `dws schema --cli-path "event +listen-im" --compact` 或对应 compact leaf。
|
||||
- `event schema` 描述事件 payload;顶层 `dws schema` 描述 CLI 命令,两者不要混用。
|
||||
|
||||
## Reference
|
||||
|
||||
| Topic | Reference | 何时读取 |
|
||||
|---|---|---|
|
||||
| 任务索引 | [event-im.md](references/event-im.md) | 还不能判断应该加载哪一个子 reference |
|
||||
| EventKey、目标规则与底层 consume | [event-im-keys.md](references/event-im-keys.md) | 群生命周期、显式 EventKey 或多事件组合 |
|
||||
| ready、bounded consume 与退出清理 | [event-im-lifecycle.md](references/event-im-lifecycle.md) | 启动/托管/关闭 consumer |
|
||||
| 扁平字段与事件到 Chat 交接 | [event-im-output.md](references/event-im-output.md) | 解析事件或自动回复 |
|
||||
| Filter、status/stop、重试与排障 | [event-im-operations.md](references/event-im-operations.md) | 订阅控制或失败恢复 |
|
||||
| OA 审批事件 | [event-oa.md](references/event-oa.md) | 选择七个 OA EventKey、组合消费或解析审批字段 |
|
||||
@@ -0,0 +1,54 @@
|
||||
# IM EventKey 与底层消费
|
||||
|
||||
高频消息、reaction、已读和撤回优先 `dws event +listen-im`。本页只用于群生命周期、
|
||||
显式 EventKey 或高级底层控制。
|
||||
|
||||
## 16 个 EventKey
|
||||
|
||||
| EventKey | 范围 | 目标参数 |
|
||||
|---|---|---|
|
||||
| `user_im_message_receive_at` | 被 @ 消息 | 无 |
|
||||
| `user_im_message_receive_o2o` | 指定单聊消息 | `--user` 或 `--open-dingtalk-id` |
|
||||
| `user_im_message_receive_group` | 指定群消息 | `--group` |
|
||||
| `user_im_message_receive_user` | 指定发送人在单聊/群聊中的消息 | `--user` 或 `--open-dingtalk-id` |
|
||||
| `user_im_message_receive_o2o_all` | 全部单聊消息 | 无 |
|
||||
| `user_im_message_receive_group_all` | 全部群消息 | 无 |
|
||||
| `user_im_message_read_o2o` | 指定单聊已读 | user 二选一 |
|
||||
| `user_im_message_read_group` | 指定群已读 | `--group` |
|
||||
| `user_im_message_recall_o2o` | 指定单聊撤回 | user 二选一 |
|
||||
| `user_im_message_recall_group` | 指定群撤回 | `--group` |
|
||||
| `user_im_message_reaction_o2o` | 指定单聊 reaction | user 二选一 |
|
||||
| `user_im_message_reaction_group` | 指定群 reaction | `--group` |
|
||||
| `user_im_group_updated` | 群标题变化 | `--group` |
|
||||
| `user_im_group_member_added` | 成员加入 | `--group` |
|
||||
| `user_im_group_member_exited` | 成员退出 | `--group` |
|
||||
| `user_im_group_disbanded` | 群解散 | `--group` |
|
||||
|
||||
`--user` 只接收 userId;明确 openDingTalkId 时用对应 flag。群目标必须是
|
||||
openConversationId。不要把两种身份混传或选择搜索第一项。
|
||||
|
||||
## 精确模板
|
||||
|
||||
```bash
|
||||
dws event consume user_im_group_member_added \
|
||||
--group <openConversationId> --flatten -f ndjson
|
||||
|
||||
dws event consume user_im_message_receive_user \
|
||||
--open-dingtalk-id <openDingTalkId> --flatten -f ndjson
|
||||
|
||||
dws event consume user_im_message_receive_group \
|
||||
user_im_message_reaction_group \
|
||||
user_im_message_recall_group \
|
||||
--group <openConversationId> --flatten -f ndjson
|
||||
```
|
||||
|
||||
多事件只能共享同一 target/filter。用户类与群类不能混在一个命令中;不同人、群或过滤条件
|
||||
启动不同 consume。只有全部 EventKey 都是接收消息时才能共享 `--query/--filter-json`。
|
||||
多事件不支持 `--subscribe-id`、`--rule`、`--event-types`、`--filter`、`--foreground`、
|
||||
`--force` 或 `--debug-raw-events`。
|
||||
|
||||
## 意图消歧
|
||||
|
||||
- “我和某人的单聊” → `receive_o2o`;“某人发给我的消息” → `receive_user`。
|
||||
- 执行撤回/添加 reaction 走 `dws chat`;监听它们才走 Event。
|
||||
- 群改名/成员进退/解散使用四个生命周期 EventKey;解散自测只能用已确认可销毁测试群。
|
||||
@@ -0,0 +1,35 @@
|
||||
# IM consume 生命周期
|
||||
|
||||
## Ready 门禁
|
||||
|
||||
单事件只有出现以下 stderr 后才读取 stdout:
|
||||
|
||||
```text
|
||||
[event] ready event_key=<key> bus_pid=<pid> subscribe_id=<id>
|
||||
```
|
||||
|
||||
多事件会先逐条输出 subscription,全部 IPC consumer 就绪后才输出:
|
||||
|
||||
```text
|
||||
[event] subscription event_key=<key> subscribe_id=<id>
|
||||
[event] subscription event_key=<key> subscribe_id=<id>
|
||||
[event] ready event_count=2 bus_pid=<pid>
|
||||
```
|
||||
|
||||
不能把 subscription 行当成整体 ready,也不要用 `sleep` 猜建联。任一订阅或 IPC 建联失败,
|
||||
Runtime 会回滚本次已创建订阅。
|
||||
|
||||
## 有界与长期任务
|
||||
|
||||
- 有界消费使用 `--max-events N` 或 `--duration 10m`。
|
||||
- 长期任务由宿主管理子进程并持续读取 stdout/stderr,避免管道背压。
|
||||
- `--output-dir`/`--route` 是明确落盘任务,不要用文件 watcher 代替 stdout 事件循环。
|
||||
- stdout 的 NDJSON 每行独立解析;单行失败不能吞掉后续事件。
|
||||
|
||||
## 干净退出
|
||||
|
||||
本次新建的订阅会在 SIGTERM、Ctrl+C、符合条件的 stdin EOF、duration 或 max-events 退出时
|
||||
自动取消。复用 `--subscribe-id` 的订阅默认保留,除非显式 `--ephemeral`。
|
||||
|
||||
多事件中停止一个 subscribe_id 只移除对应 consumer;其余继续,最后一个移除后进程退出。
|
||||
禁止 `kill -9`,它会跳过清理。外部停止流程见 [event-im-operations.md](event-im-operations.md)。
|
||||
@@ -0,0 +1,52 @@
|
||||
# IM 订阅过滤、状态与排障
|
||||
|
||||
## Filter
|
||||
|
||||
优先用订阅规则缩小范围:单聊/发送人用 user 身份,群用 `--group`。接收消息事件需要额外
|
||||
正文过滤时才用 `--query` 或 `--filter-json`;已读、撤回、reaction 和群生命周期不使用
|
||||
消息内容过滤。业务别名包括 `content`、`sender`、`conversation_id`、
|
||||
`sender_open_dingtalk_id`。
|
||||
|
||||
## Status 与 stop
|
||||
|
||||
```bash
|
||||
dws event status --event <event_key>
|
||||
dws event stop <subscribe_id> --dry-run
|
||||
dws event stop <subscribe_id> --yes
|
||||
dws event stop --all --dry-run
|
||||
dws event stop --all --yes
|
||||
```
|
||||
|
||||
`status` 同时看服务端 Subscriptions 与本地 Consumers;用 PID、EventKey、subscribe_id 和
|
||||
received/dropped 判断 consumer。裸 `event stop` 不取消任何订阅。stop 是有影响操作,先预览,
|
||||
按 Runtime gate 确认后执行。
|
||||
|
||||
## 创建失败与 `0/2/1` 编排预算
|
||||
|
||||
这些约束只治理 ready 之前的创建;ready 后断线由长连接重连:
|
||||
|
||||
- `retryable=false`:额外尝试 0 次。
|
||||
- `retryable=true`:最多额外 2 次,并遵守 `retry_after_seconds/next_retry_at`。
|
||||
- 未给 retryable:最多额外 1 次,然后停止并保留 trace。
|
||||
|
||||
这是 Agent/host 预算,不是 CLI 跨进程计数器。一个逻辑订阅由 profile/身份、EventKey、
|
||||
rule、目标和 filter 确定;换 subscribe_id、trace 或进程不能重置预算。遇到 `in_flight`、
|
||||
`cooldown`、`terminal_hold` 不并发、递归或拆分多事件绕过保护。
|
||||
|
||||
## 本地保护状态
|
||||
|
||||
open 版路径为
|
||||
`~/.dws/events/open/personal_stream/<identity_hash>/personal_subscription_attempts.json`;
|
||||
`DWS_CONFIG_DIR` 会改变根目录。identity 目录为 `0700`,JSON 与 lock 为 `0600`。
|
||||
连续 24h 无失败后重置,terminal hold 为 1h。
|
||||
|
||||
紧急恢复前确认没有创建进程,只删除 attempts JSON,不删除 lock;这会清空该 identity 的
|
||||
全部保护记录,不是常规重试方式。
|
||||
|
||||
## 最短排障
|
||||
|
||||
- 无输出:先确认正确 ready marker,再看 subscribe_id 和 received/dropped。
|
||||
- 目标错误:o2o/user 检查身份 flag,group 检查 openConversationId。
|
||||
- 判断服务端是否推到连接:临时单事件 `--debug --debug-raw-events`;它不能与 `--flatten`
|
||||
并用,排查后立即移除。
|
||||
- 长期运行:交给宿主进程管理,不写历史消息轮询脚本。
|
||||
@@ -0,0 +1,39 @@
|
||||
# IM 事件输出与 Chat 交接
|
||||
|
||||
Agent 默认使用 `--flatten -f ndjson`,顶层直接读取字段,不再 `fromjson`。消息接收常见字段:
|
||||
|
||||
| 字段 | 语义 |
|
||||
|---|---|
|
||||
| `type` / `event_id` / `timestamp` | 事件类型、去重 ID、时间 |
|
||||
| `subscribe_id` | 个人订阅与本地输出隔离键 |
|
||||
| `message_id` / `conversation_id` | 稳定消息与会话 ID |
|
||||
| `sender` / `sender_open_dingtalk_id` | 展示名与稳定发送人开放 ID |
|
||||
| `content` / `create_time` / `event_time` | 正文及时间 |
|
||||
| `quoted_message` | 可选引用原消息 |
|
||||
| `forward_messages` | 可选合并转发子消息数组 |
|
||||
|
||||
引用和转发子消息字段为 `message_id`、`conversation_id`、`sender`、
|
||||
`sender_open_dingtalk_id`、`content`、`create_time`。按结构识别转发,不匹配本地化摘要。
|
||||
|
||||
动作事件通用字段之外:已读提供 `reader_open_dingtalk_id/read_time`,撤回提供
|
||||
`recaller_open_dingtalk_id/recall_time`,reaction 提供
|
||||
`operator_open_dingtalk_id/reaction_name/reaction_text/operation_type/operation_time`。
|
||||
|
||||
成员加入/退出提供 `conversation_id`、`operator_open_dingtalk_id`、`members[]` 和
|
||||
`event_time`;成员稳定 ID 是 `members[].open_dingtalk_id`。群标题变化和群解散仅保守承诺
|
||||
基础路由字段及 `payload`,不得猜未由真实样本确认的键。
|
||||
|
||||
## 事件驱动回复的精确 ID 映射
|
||||
|
||||
<!-- DWS_EVENT_CHAT_HANDOFF_START -->
|
||||
| event field | exact chat target |
|
||||
|---|---|
|
||||
| `conversation_id` | `dws chat +messages-send --as user --group <conversation_id>` |
|
||||
| `sender_open_dingtalk_id` | `dws chat +messages-send --as user --open-dingtalk-id <sender_open_dingtalk_id>` |
|
||||
<!-- DWS_EVENT_CHAT_HANDOFF_END -->
|
||||
|
||||
在上述命令后追加真实 `--text`/`--markdown` 和必要 confirmation。禁止使用 `sender` 再做
|
||||
`--user-query`,也禁止把单聊发送人 ID 当成群 ID。交接 marker 由 policy 逐字验证。
|
||||
|
||||
媒体事件正文可能只是描述。优先按真实消息 ID/会话 ID 使用 Chat 消息读取命令加
|
||||
`--download-resources`;只有精确 lower fallback 才用 `chat message download-media`。
|
||||
@@ -0,0 +1,58 @@
|
||||
# IM 事件任务路由
|
||||
|
||||
本页是任务索引,不再混放 16 个 EventKey、输出字段和运维细节。先用上层
|
||||
[SKILL.md](../SKILL.md) 的 Golden Route;只加载当前任务对应的一份子 reference。
|
||||
|
||||
<!-- dws-intent: event.listen.im -->消息、reaction、已读和撤回默认使用 `dws event +listen-im` 长连接;
|
||||
群生命周期、显式 EventKey、Filter DSL、原始 envelope 或底层订阅控制才使用
|
||||
`event consume`。不要写轮询脚本。
|
||||
|
||||
## 选择哪一页
|
||||
|
||||
| 任务 | Reference |
|
||||
|---|---|
|
||||
| 选择 16 个 EventKey、区分 user/group/all 规则、组合底层 consume | [event-im-keys.md](event-im-keys.md) |
|
||||
| 等待 ready、多事件回滚、bounded consume、退出清理 | [event-im-lifecycle.md](event-im-lifecycle.md) |
|
||||
| 扁平字段、引用/转发、动作与群成员事件、事件驱动回复 | [event-im-output.md](event-im-output.md) |
|
||||
| Filter、status/stop、重试预算、本地保护与排障 | [event-im-operations.md](event-im-operations.md) |
|
||||
|
||||
## 共同硬规则
|
||||
|
||||
- 个人事件使用当前用户 OAuth;解析、consume、status、stop 必须是同一 `--profile`。
|
||||
- `+listen-im --user-query/--chat-query` 在 CLI 内唯一解析;零命中、多候选或分页不完整时,
|
||||
在创建订阅前停止。底层 fallback 只传真实稳定 ID。
|
||||
- 默认 `--flatten -f ndjson`;stdout 只处理事件,stderr 等待明确 ready marker。
|
||||
- 指定目标优先于 `*_all`;只有用户明确说“全部单聊/全部群消息”才订阅全量事件。
|
||||
- 当前用户自己发送的消息会被 self-loop 过滤;自测由另一用户或机器人触发。
|
||||
- 事件只负责监听。回复必须使用事件里的真实 `conversation_id` 或
|
||||
`sender_open_dingtalk_id`,禁止把展示名重新做自然查询。
|
||||
|
||||
## 跨页契约索引
|
||||
|
||||
以下索引保留跨页必须一致的机器可检验契约;解释、示例和操作步骤仍按上表按需加载:
|
||||
|
||||
- 16 个事件都使用同一 `--profile`。就绪以 `[event] ready` 为准;全量事件是
|
||||
`user_im_message_receive_o2o_all` / `user_im_message_receive_group_all`,群生命周期是
|
||||
`user_im_group_updated` / `user_im_group_member_added` /
|
||||
`user_im_group_member_exited` / `user_im_group_disbanded`。
|
||||
- 扁平动作字段包括 `reader_open_dingtalk_id`、`recaller_open_dingtalk_id`、
|
||||
`operator_open_dingtalk_id`、`reaction_name`、`operation_type` 和 `members`;媒体 lower
|
||||
fallback 是 `dws chat message download-media`,外部身份参数是 `--open-dingtalk-id`。
|
||||
- 创建失败遵循 Agent/host 的 `0/2/1` 预算:`retryable=false` 对应
|
||||
`max_additional_attempts=0`,`retryable=true` 对应 `max_additional_attempts=2`,
|
||||
`retryable=unknown` 对应 `max_additional_attempts=1`,并遵守 `retry_after_seconds` /
|
||||
`next_retry_at`。这不是 CLI 持久化硬总次数上限;进程内不会自动重试,也不持久化或计算跨调用的
|
||||
Agent/host 尝试次数。`subscribe_id` / `trace_id` 不重置预算,`in_flight` / `cooldown` /
|
||||
`terminal_hold` 不得被并发绕过。
|
||||
- open 版保护文件是
|
||||
`~/.dws/events/open/personal_stream/<identity_hash>/personal_subscription_attempts.json`;
|
||||
`DWS_CONFIG_DIR` 可改变根目录。目录权限 `0700`,`personal_subscription_attempts.json` 与
|
||||
`personal_subscription_attempts.lock` 权限 `0600`;连续 `24h` 无失败后重置,
|
||||
`terminal_hold` 为 `1h`。紧急恢复只删除 `personal_subscription_attempts.json`,
|
||||
不要删除 lock 文件;这会清空该 identity 的全部保护记录。
|
||||
|
||||
## Schema 边界
|
||||
|
||||
- 业务 payload:`dws event schema <event_key> --flatten`。
|
||||
- CLI 参数/安全:`dws schema --cli-path "event +listen-im" --compact -f json` 或精确 compact consume leaf。
|
||||
- `--flatten` 的 `jq_root_path` 为 `.`;兼容 transport envelope 才使用 `.data | fromjson`。
|
||||
@@ -0,0 +1,155 @@
|
||||
# OA 个人审批事件
|
||||
|
||||
先读事件产品入口 [SKILL.md](../SKILL.md) 的命令规则、调用流和子进程契约。本参考覆盖当前公开的七个 OA 个人事件:审批实例发起、抄送、终止和完成,以及审批任务创建、完成和转交。
|
||||
|
||||
<!-- dws-intent: event.listen.oa -->实时监听审批事件必须使用 `dws event consume` 长连接,不要轮询 OA 待办或审批实例列表来模拟事件。
|
||||
|
||||
## Prerequisite
|
||||
|
||||
OA 个人事件使用当前用户 OAuth 登录态。未登录或 token 失效时,先执行:
|
||||
|
||||
```bash
|
||||
dws auth login
|
||||
```
|
||||
|
||||
非默认组织使用全局 `--profile <corpId 或 profile 名>`。事件范围始终是该 OAuth 用户相关的全部 OA 事件,不需要也不接受审批人、发起人或审批模板选择参数。
|
||||
|
||||
## Event catalog
|
||||
|
||||
| 事件码 | 订阅规则 | 接收语义 | 必填参数 |
|
||||
|---|---|---|---|
|
||||
| `user_oa_approval_task_created` | `all` | 审批任务创建,发送给审批人 | 无 |
|
||||
| `user_oa_approval_task_finished` | `all` | 审批任务已完成 | 无 |
|
||||
| `user_oa_approval_task_redirected` | `all` | 审批任务已转交 | 无 |
|
||||
| `user_oa_approval_instance_started` | `all` | 审批实例已发起 | 无 |
|
||||
| `user_oa_approval_instance_cc` | `all` | 审批实例到达抄送节点,发送给被抄送人 | 无 |
|
||||
| `user_oa_approval_instance_terminated` | `all` | 审批实例已终止 | 无 |
|
||||
| `user_oa_approval_instance_finished` | `all` | 审批实例完成,发送给审批单发起人 | 无 |
|
||||
|
||||
只承认上表 7 个 OA 事件码。CLI 为每个事件发送 `ruleType=all`、`filterRule={}` 的独立订阅请求;不要添加 `--user`、`--open-dingtalk-id`、`--group`、`--query` 或 `--filter-json`。
|
||||
|
||||
## Intent mapping
|
||||
|
||||
| 用户说 | 下一步 |
|
||||
|---|---|
|
||||
| “监听新的待我审批任务” / “有审批任务创建时通知我” | `dws event consume user_oa_approval_task_created --flatten -f ndjson` |
|
||||
| “审批任务完成时通知我” | `dws event consume user_oa_approval_task_finished --flatten -f ndjson` |
|
||||
| “审批任务被转交时通知我” | `dws event consume user_oa_approval_task_redirected --flatten -f ndjson` |
|
||||
| “有审批单发起时通知我” | `dws event consume user_oa_approval_instance_started --flatten -f ndjson` |
|
||||
| “有审批抄送给我时通知我” | `dws event consume user_oa_approval_instance_cc --flatten -f ndjson` |
|
||||
| “有审批单终止时通知我” | `dws event consume user_oa_approval_instance_terminated --flatten -f ndjson` |
|
||||
| “监听我发起的审批何时完成” / “审批实例完成时通知我” | `dws event consume user_oa_approval_instance_finished --flatten -f ndjson` |
|
||||
| “同时监听全部已公开 OA 事件” | 一个 consume 放入七个 OA event key,不加目标或过滤参数 |
|
||||
| “查看 OA 事件目录” | `dws event list --category oa` |
|
||||
| “查看 OA 事件输出字段” | 对对应事件运行 `dws event schema <event_key> --flatten` |
|
||||
|
||||
三个审批任务事件分别表达任务已创建、已完成和已转交;四个审批实例事件分别表达实例已发起、到达抄送节点、已终止和已完成。`status` 和 `result` 保留服务端原值,不把当前样本值推断为完整枚举。
|
||||
|
||||
## Commands
|
||||
|
||||
查看稳定的扁平输出 schema:
|
||||
|
||||
```bash
|
||||
dws event schema user_oa_approval_task_created --flatten
|
||||
dws event schema user_oa_approval_task_finished --flatten
|
||||
dws event schema user_oa_approval_task_redirected --flatten
|
||||
dws event schema user_oa_approval_instance_started --flatten
|
||||
dws event schema user_oa_approval_instance_cc --flatten
|
||||
dws event schema user_oa_approval_instance_terminated --flatten
|
||||
dws event schema user_oa_approval_instance_finished --flatten
|
||||
```
|
||||
|
||||
单独监听一种事件:
|
||||
|
||||
```bash
|
||||
dws event consume user_oa_approval_task_created --flatten -f ndjson
|
||||
dws event consume user_oa_approval_task_finished --flatten -f ndjson
|
||||
dws event consume user_oa_approval_task_redirected --flatten -f ndjson
|
||||
dws event consume user_oa_approval_instance_started --flatten -f ndjson
|
||||
dws event consume user_oa_approval_instance_cc --flatten -f ndjson
|
||||
dws event consume user_oa_approval_instance_terminated --flatten -f ndjson
|
||||
dws event consume user_oa_approval_instance_finished --flatten -f ndjson
|
||||
```
|
||||
|
||||
同时监听七种事件:
|
||||
|
||||
```bash
|
||||
dws event consume \
|
||||
user_oa_approval_task_created \
|
||||
user_oa_approval_task_finished \
|
||||
user_oa_approval_task_redirected \
|
||||
user_oa_approval_instance_started \
|
||||
user_oa_approval_instance_cc \
|
||||
user_oa_approval_instance_terminated \
|
||||
user_oa_approval_instance_finished \
|
||||
--flatten \
|
||||
-f ndjson
|
||||
```
|
||||
|
||||
多事件 consume 会为七个 event key 分别创建订阅和逻辑 consumer,并共享当前组织的 personal bus、远程连接、stdout 和生命周期。不要给 OA 命令加 `--query` 或 `--filter-json`;这两个 flag 只用于兼容的 IM 消息接收事件。
|
||||
|
||||
## Output contract
|
||||
|
||||
`--flatten` 模式的所有 OA 事件都包含以下顶层字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "user_oa_approval_task_created",
|
||||
"event_id": "...",
|
||||
"timestamp": 0,
|
||||
"subscribe_id": "...",
|
||||
"process_instance_id": "...",
|
||||
"process_code": "...",
|
||||
"title": "...",
|
||||
"status": "RUNNING",
|
||||
"create_time": 0,
|
||||
"event_time": 0
|
||||
}
|
||||
```
|
||||
|
||||
- `type` 是当前 event key;`event_id` 可用于去重;`timestamp` 是 transport 事件发生时间;`subscribe_id` 标识对应的独立订阅。
|
||||
- `process_instance_id` 是审批实例 ID,可传给 OA 审批命令的 `--instance-id`;`process_code` 是审批流程模板编码。
|
||||
- `create_time`、`finish_time` 和 `event_time` 都是毫秒时间戳。`event_time` 是审批业务事件时间,`timestamp` 是 transport 事件时间。
|
||||
- 七类事件的额外字段如下;具体事件始终以 `dws event schema <event_key> --flatten` 为准。
|
||||
|
||||
| 事件 | 额外顶层字段 |
|
||||
|---|---|
|
||||
| `user_oa_approval_task_created` | `task_id` |
|
||||
| `user_oa_approval_task_finished` | `task_id`、`result`、`finish_time` |
|
||||
| `user_oa_approval_task_redirected` | `task_id`、`result`、`finish_time` |
|
||||
| `user_oa_approval_instance_started` | 无 |
|
||||
| `user_oa_approval_instance_cc` | 无 |
|
||||
| `user_oa_approval_instance_terminated` | `finish_time` |
|
||||
| `user_oa_approval_instance_finished` | `result`、`finish_time` |
|
||||
|
||||
任务完成事件示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "user_oa_approval_task_finished",
|
||||
"event_id": "...",
|
||||
"timestamp": 0,
|
||||
"subscribe_id": "...",
|
||||
"process_instance_id": "...",
|
||||
"process_code": "...",
|
||||
"task_id": "...",
|
||||
"title": "测试审批",
|
||||
"status": "FINISHED",
|
||||
"result": "agree",
|
||||
"create_time": 0,
|
||||
"finish_time": 0,
|
||||
"event_time": 0
|
||||
}
|
||||
```
|
||||
|
||||
- `task_id` 是当前审批任务 ID,可传给接受任务 ID 的 OA 审批命令。
|
||||
- `status` 和 `result` 是服务端字符串;不要只根据当前样本把 `RUNNING/FINISHED/TERMINATED` 或 `agree/redirect` 写成封闭枚举。
|
||||
- payload 缺失、为空、缺少对应事件的稳定 ID 或无法解析时,consume 会在 stderr 记录 warning,并把原始 transport envelope 写到 stdout,保证事件不被静默丢弃。
|
||||
- 不传 `--flatten` 时保持兼容 transport envelope,业务 payload 位于 `.data | fromjson`。需要联调完整原始协议时使用不带 `--flatten` 的 `-f raw` 或 `--debug-raw-events`。
|
||||
|
||||
## Lifecycle
|
||||
|
||||
- 单事件等待 `[event] ready event_key=<key> bus_pid=<pid> subscribe_id=<id>`。
|
||||
- 七事件先保存七条 `[event] subscription event_key=<key> subscribe_id=<id>`,再等待 `[event] ready event_count=7 bus_pid=<pid>`。
|
||||
- 临时验证使用 `--max-events 1` 或 `--duration 10m`;任务完成后优雅结束 consume,本次新建的订阅会自动取消。
|
||||
- 外部停止已有订阅时先运行 `dws event stop <subscribe_id> --dry-run`,确认后再加 `--yes`。不要 `kill -9`,否则会跳过自动退订。
|
||||
Reference in New Issue
Block a user