first commit

This commit is contained in:
2026-09-02 11:44:52 +08:00
commit 0c8fa2653e
309 changed files with 57278 additions and 0 deletions
@@ -0,0 +1,70 @@
# IM 稳定契约与能力边界
本页只记录需要跨命令复用的 Runtime 契约。下面四个 marker 区块由
`check-multi-im-skill-chain.sh` 对照 Go typed descriptor 逐字校验;修改能力时先改 Runtime、
测试与 descriptor,再同步本页。命令参数仍以精确 leaf Schema 为准。
## 消息结果 `im.message-list.v1`
`+chat-messages``+search-msg``+messages-mget` 及相关消息读取使用同一兼容版本。
字段可能为空,但不能换名猜测;全量任务必须结合完整性 ledger 判断。
<!-- DWS_MESSAGE_RESULT_CONTRACT_START -->
- `version`: `im.message-list.v1`
- `message_fields`: `messageId`, `conversationId`, `threadId`, `sender`, `senderId`, `senderType`, `messageType`, `text`, `createTime`, `updateTime`, `reactions`, `quotedMessage`, `forwarded`, `resourceRefs`
- `envelope_fields`: `contractVersion`, `messages`, `count`, `resolvedFilters`, `queryRange`, `pagesFetched`, `paginationKnown`, `complete`, `hasMore`, `nextPage`, `stopReason`, `truncated`, `truncatedByPageLimit`, `truncatedByResultLimit`, `failedCount`, `failures`, `partial`, `scope`, `resourceDownloads`
<!-- DWS_MESSAGE_RESULT_CONTRACT_END -->
`complete=false` 时不能称为全量成功。`nextPage` 只能来自真实 lower boundary
`failedCount/failures``partial`、总 `truncated` 和两个原因字段必须原样保留。
当 Runtime 解析并应用自然发送者条件时,`resolvedFilters.senders[]` 保留原查询及选中的
`userId/openDingTalkId`。消息展示名可以与通讯录姓名不同;只能用稳定 `senderId` 与解析结果关联,
不得重新做姓名字符串比较。
当查询声明时间范围或顺序时,`queryRange` 保留规范化的 `startTime``endTime``order`
`semantics=[start,end)`。排序只覆盖本次实际取得的 `messages``complete=false` 时不得把它描述为完整范围的全局排序。
## `+messages-send` 身份矩阵
<!-- DWS_IDENTITY_CAPABILITY_CONTRACT_START -->
| identity | targets | content types | natural targets | mention targets | idempotency keys | batch ledger |
|---|---|---|---|---|---:|---:|
| `user` | `group`<br>`direct-user`<br>`direct-open-dingtalk-id` | `text`<br>`markdown`<br>`image-media-id`<br>`file`<br>`audio-as-file`<br>`video-as-file` | `chat-query`<br>`user-query` | `open-dingtalk-id`<br>`all` | `true` | `false` |
| `bot` | `group`<br>`groups`<br>`direct-users`<br>`direct-open-dingtalk-ids` | `text`<br>`markdown` | — | `user-id`<br>`open-dingtalk-id`<br>`all` | `false` | `true` |
| `webhook` | `token-owned-group` | `text`<br>`markdown` | — | `user-id`<br>`mobile`<br>`all` | `false` | `false` |
<!-- DWS_IDENTITY_CAPABILITY_CONTRACT_END -->
Bot 多群用 `--groups``--groups-file`Runtime 去重后输出
`im.batch-write.v1` 逐目标 ledger。Bot/Webhook 不支持的内容类型会在写前失败,不能降级为
另一身份或偷偷改成纯文本。
## 流式卡片
<!-- DWS_CARD_WORKFLOW_CONTRACT_START -->
- `version`: `im.streaming-card.v1`
- `targets`: `group`, `direct-user`, `direct-open-dingtalk-id`
- `content_types`: `streaming-text`
- `flow_statuses`: `1=processing`, `2=typing`, `3=completed`, `4=executing`, `5=error`
- `callback_supported`: `false`
<!-- DWS_CARD_WORKFLOW_CONTRACT_END -->
发送目标与状态范围由 Runtime 校验。当前不是 Lark Card JSON 编译器,也不消费按钮 callback;
具体创建和更新流程见 `card/` 下的精确 reference。
## 正向能力与负向边界
<!-- DWS_CAPABILITY_BOUNDARY_CONTRACT_START -->
| capability | supported | current route / boundary |
|---|---:|---|
| `thread-write` | `false` | quote reply with +messages-reply; thread reading with +thread-replies |
| `bot-rich-media` | `false` | bot text/markdown, or current-user file/image send |
| `card-action-callback` | `false` | streaming text card create/update only |
| `resource-resume` | `false` | atomic whole-file download with explicit retry |
| `group-member-full-pagination` | `true` | +chat-members-list or +group-members |
| `group-owner-selection` | `true` | +chat-create owner flags |
<!-- DWS_CAPABILITY_BOUNDARY_CONTRACT_END -->
`supported=false` 是执行门禁,不是待猜测字段。只有 lower interface、Runtime、测试、Schema 和
此页同时升级后,才能改变对外承诺。
话题圈会话仍禁止引用消息回复;向 Thread 追加回复使用 `chat thread reply --conversation-id <openConvThreadId>`