Skip to content

feat(channels): add DingTalk Workspace channel - #9049

Closed
qqqys wants to merge 18 commits into
QwenLM:mainfrom
qqqys:feat/dws-channel-unified
Closed

qqqys wants to merge 18 commits into
QwenLM:mainfrom
qqqys:feat/dws-channel-unified

Conversation

@qqqys

@qqqys qqqys commented Aug 13, 2026 •

Copy link
Copy Markdown
Collaborator

What this PR does

Adds a built-in DingTalk Workspace channel that uses an existing authenticated DWS CLI profile. It supports direct messages, @mentions and configured ambient groups, DingTalk document-mention notifications, native todo changes, source-scoped sessions, final replies to the originating message, document comment, or todo, and a temporary 暗中观察 reaction while accepted message tasks run.

The channel reuses the shared sender and group policy model, defaults managed instances to pairing, pins one DWS profile for the channel lifetime, filters the DWS subprocess environment, persists delivery targets, processed-message cursors, and todo fingerprints, suppresses outbound echoes and duplicate pairing notifications, and exposes the channel through CLI, daemon/Web Shell management, build, release, and documentation paths. Native todo watching is opt-in, baselines existing pending todos, polls executor assignments every 30 seconds, and writes the final response back as a todo comment without reacting to its own comment metadata.

Why it's needed

The existing DingTalk channel is intentionally a dedicated application-bot adapter. Users who already authenticate DWS need a separate account-backed channel, analogous to the GitHub channel, so Qwen Code can receive workspace events and respond using the existing DWS login without requiring a bot application.

Reviewer Test Plan

How to verify

  1. Install DWS CLI 1.0.57 or newer, authenticate one profile, configure a type: "dws" channel with pairing policies, and start it with qwen channel start <name>.
  2. Send a direct message from another DingTalk account. Confirm one pairing notification is produced, approve it, then confirm subsequent messages receive 暗中观察 while the task runs and get one final reply.
  3. Send ordinary messages from an unapproved automated account. Confirm they are rejected without repeated pairing notifications or agent execution.
  4. In a DingTalk document, add a comment that @mentions the authenticated account and enable the notification option. Confirm the channel reads the referenced document and posts the final answer under the original comment; disabling the notification should not create a task.
  5. Configure a concrete group or "*" with requireMention: false and verify ordinary group messages obey both group and sender policy gates.
  6. Set watchTodos: true, start the channel once to establish a baseline, then assign a new native todo to the authenticated account. Confirm it runs once and the final response appears as a todo comment; changing only comments or modification timestamps must not start another task.

Evidence (Before & After)

Before: Qwen Code had no built-in channel for an existing DWS login; only the dedicated DingTalk bot adapter was available.

After: A locally authenticated DWS profile can start the channel, receive direct/group/document notifications, poll opted-in native todo changes, show a working reaction for messages, and route the final response back to the originating surface. Live validation also confirmed that repeated automated messages produce one pairing notification per pending request instead of an outbound loop.

Tested on

OS Status
🍏 macOS ✅
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

macOS, Node.js 22+, DWS CLI 1.0.57, local TypeScript development checkout.

Risk & Scope

  • Main risk or tradeoff: Document mentions currently depend on the DWS direct-message notification card; the five-second incremental history fallback covers cards omitted by the real-time stream. DWS 1.0.57 does not expose native todo events, so todo assignments and actionable changes are polled every 30 seconds.
  • Not validated / out of scope: Windows and Linux live DWS authentication, DingTalk bot behavior, document comments that do not generate an account notification, and todo comment-only changes or completion events.
  • Breaking changes / migration notes: None. The existing dingtalk channel remains separate and unchanged.

Linked Issues

N/A

中文说明

本 PR 做了什么

新增内置钉钉工作空间 Channel,复用已经登录的 DWS CLI profile。它支持单聊、@ 消息、按配置接收的普通群消息、钉钉文档 @ 通知、原生待办变化、按来源隔离会话,并把最终回复写回原始消息、文档评论或待办;消息任务执行期间还会添加 暗中观察 表情。

该 Channel 复用统一的发送者和群聊策略,管理界面中新建实例默认使用 pairing;启动时固定唯一 DWS profile;限制 DWS 子进程可继承的环境变量;持久化投递目标、已处理游标和待办指纹;抑制自身回显和重复配对通知;并完成 CLI、daemon/Web Shell、构建、发布和文档接线。原生待办监听默认关闭;开启后会先为已有未完成待办建立基线,每 30 秒轮询一次执行者待办,并把最终回复写入待办评论,同时忽略自身评论产生的元数据变化。

为什么需要

现有钉钉 Channel 专门服务于独立应用机器人。已经使用 DWS 登录的用户需要一个独立的账号型 Channel,像 GitHub Channel 一样,让 Qwen Code 无需新建机器人应用即可接收工作空间事件,并通过现有 DWS 登录回复。

Reviewer 测试计划

如何验证

  1. 安装 DWS CLI 1.0.57 或更高版本,登录一个 profile,配置 type: "dws" 且策略为 pairing,然后运行 qwen channel start <name>。
  2. 从另一个钉钉账号发送单聊,确认只产生一次配对提示;批准后再次发消息,确认任务执行期间出现 暗中观察,并只收到一次最终回复。
  3. 从未批准的自动账号连续发送普通消息,确认消息被拒绝,但不会重复发送配对提示,也不会触发 Agent。
  4. 在钉钉文档评论中 @ 已登录账号并勾选通知,确认 Channel 读取关联文档并在原评论下回复;关闭通知时不应创建任务。
  5. 为具体群或 "*" 配置 requireMention: false,确认普通群消息同时遵守群策略和发送者策略。
  6. 设置 watchTodos: true,首次启动建立基线后,再把一个新的原生待办指派给已登录账号。确认待办只执行一次,最终回复出现在待办评论中;仅评论或更新时间变化时不应再次触发。

前后对比证据

Before:Qwen Code 没有复用现有 DWS 登录的内置 Channel,只支持独立钉钉机器人适配器。

After:本机已登录的 DWS profile 可以启动 Channel,接收单聊、群聊和文档通知,按配置轮询原生待办变化,为消息任务显示接手表情,并把最终回复路由回原始入口。现场验证还确认,自动账号连续发消息时,每个待批准请求只发送一次配对提示,不再形成出站回环。

验证平台

OS 状态
🍏 macOS ✅
🪟 Windows ⚠️
🐧 Linux ⚠️

环境

macOS、Node.js 22+、DWS CLI 1.0.57、本地 TypeScript 开发工作区。

风险与范围

  • 主要风险或取舍:文档 @ 当前依赖 DWS 单聊通知卡片;实时事件流遗漏卡片时,由五秒增量历史查询兜底。DWS 1.0.57 尚未提供原生待办事件,因此待办指派和关键字段变化采用每 30 秒轮询。
  • 未验证或不在范围内:Windows 和 Linux 上的真实 DWS 登录、现有钉钉机器人行为、未生成账号通知的文档评论,以及仅评论变化或完成事件的待办触发。
  • 破坏性变更或迁移说明:无。现有 dingtalk Channel 保持独立且不变。

关联 Issue

无

@qqqys

qqqys commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

E2E test report

Environment: macOS, Node.js 22+, DWS CLI 1.0.57, local npm run dev -- channel start dws-local.

  • Confirmed the channel starts with the existing authenticated DWS profile and receives real direct-message events.
  • Confirmed accepted tasks add the 暗中观察 reaction while running and remove it on completion.
  • Confirmed document @ notification cards are recognized and routed to the originating document comment.
  • Reproduced an automated-account pairing loop before the fix. After the fix, 9 distinct automated inbound messages produced only 2 outbound pairing notifications (one per pending sender); the later 7 messages were rejected without additional sends or agent execution.
  • Confirmed self-message learning suppresses later account echoes without relying on user_id metadata.

Automated checks on the rebased commit: DWS 81/81, CLI registry 44/44, Web Shell 2/2, full build, typecheck, lint, Prettier, bundle, and npm pack dry-run.

@qqqys
qqqys marked this pull request as ready for review August 13, 2026 08:37
@qqqys
qqqys dismissed a stale review August 13, 2026 13:16

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 14, 2026 07:23

已被后续 commit 849fcbc 取代,当前 head 需重新 review。

@qqqys
qqqys dismissed a stale review August 14, 2026 18:21

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 14, 2026 20:56

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 14, 2026 23:16

已被后续 commit 取代,当前 head 需重新 review。

@qqqys
qqqys dismissed a stale review August 15, 2026 03:31

Superseded by a later commit; current head requires re-review.

@qqqys
qqqys dismissed a stale review August 15, 2026 06:30

已被后续 commit 取代,当前 head 需重新 review。

@qqqys
qqqys dismissed a stale review August 15, 2026 09:35

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 15, 2026 12:32

已被后续 commit 取代,当前 head 需重新 review。

@qqqys
qqqys dismissed a stale review August 15, 2026 15:40

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 15, 2026 18:20

已被后续 commit 取代,当前 head 需重新 review

@qqqys
qqqys dismissed a stale review August 17, 2026 13:39

已被后续 commit 取代,当前 head 需重新 review

wenshao and others added 2 commits August 18, 2026 02:20
The DWS channel was already added to `PUBLISHED_PACKAGES` and to the
release.yml publish allowlist, but the test that pins the full set was
not updated, so it asserted 10 packages against the 11 now shipped and
failed the Test job.

Co-Authored-By: Claude Opus 5 <[email protected]>
@qqqys

qqqys commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /review

@github-actions

Copy link
Copy Markdown
Contributor

Qwen Code review request accepted. Review is queued in workflow run.

@qqqys

qqqys commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #9394.

Rebased onto current main and squashed into a single commit — the 17-commit history (2 merges + 15 "address review blockers" fix-ups) and the 171 stale bot review threads made this PR hard to read.

The rebuild also fixes one real gap this PR carried: @qwen-code/channel-dws was added to PUBLISHED_PACKAGES and to the release.yml publish allowlist, but the pin test in scripts/tests/get-release-version.test.js that guards that list was never updated, so it failed. Verified with npm run typecheck, the DWS suite (167), the CLI channel-registry suite (342), the web-shell channel suite (101) and the scripts/tests suite.

本 PR 已由 #9394 取代:基于最新 main 重建并压缩为单个提交,同时补上了漏改的 get-release-version 发布包清单 pin 测试。

@qqqys qqqys closed this Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants