feat(channels): add DingTalk channel via Stream Mode

Implement DingTalk messaging channel using the official Stream Mode
WebSocket protocol with per-message session webhook replies.

- Add DingTalkChannel with send/listen/health_check support
- Add DingTalkConfig (client_id, client_secret, allowed_users)
- Integrate with onboard wizard, integrations registry, and channel
  list/doctor commands
- Include unit tests for user allowlist rules and config serialization
This commit is contained in:
elonf 2026-02-17 00:02:05 +08:00
parent c11c569ddd
commit 9463bf08a4
5 changed files with 449 additions and 5 deletions

View file

@ -1,4 +1,5 @@
pub mod cli;
pub mod dingtalk;
pub mod discord;
pub mod email_channel;
pub mod imessage;
@ -11,6 +12,7 @@ pub mod traits;
pub mod whatsapp;
pub use cli::CliChannel;
pub use dingtalk::DingTalkChannel;
pub use discord::DiscordChannel;
pub use email_channel::EmailChannel;
pub use imessage::IMessageChannel;
@ -555,6 +557,7 @@ pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Resul
("Email", config.channels_config.email.is_some()),
("IRC", config.channels_config.irc.is_some()),
("Lark", config.channels_config.lark.is_some()),
("DingTalk", config.channels_config.dingtalk.is_some()),
] {
println!(" {} {name}", if configured { "" } else { "" });
}
@ -697,6 +700,17 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
));
}
if let Some(ref dt) = config.channels_config.dingtalk {
channels.push((
"DingTalk",
Arc::new(DingTalkChannel::new(
dt.client_id.clone(),
dt.client_secret.clone(),
dt.allowed_users.clone(),
)),
));
}
if channels.is_empty() {
println!("No real-time channels configured. Run `zeroclaw onboard` first.");
return Ok(());
@ -958,6 +972,14 @@ pub async fn start_channels(config: Config) -> Result<()> {
)));
}
if let Some(ref dt) = config.channels_config.dingtalk {
channels.push(Arc::new(DingTalkChannel::new(
dt.client_id.clone(),
dt.client_secret.clone(),
dt.allowed_users.clone(),
)));
}
if channels.is_empty() {
println!("No channels configured. Run `zeroclaw onboard` to set up channels.");
return Ok(());