Commit Graph

13 Commits

Author SHA1 Message Date
6vision
dec31dfd75 fix(wecom_bot): shrink callback inline images so finish packets aren't rejected
In callback mode the image is base64-embedded in the stream finish reply and
the whole response is AES-encrypted and returned on every poll. A multi-MB
body is rejected/times out on WeCom's side, leaving the "···" bubble spinning
and the image never shown.

- Compress callback images to <=512KB (JPEG, resize if needed) instead of the
  10MB the protocol nominally allows
- Fall back to the original image if compression fails, and log the final
  base64 payload size for diagnosis

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 18:26:38 +08:00
6vision
18ce17d21a fix(wecom_bot): finalize stream on cancel; never force-finish on a timer
The streaming "···" bubble should only stop when the task actually completes
or the user cancels — not on an arbitrary timeout that would also steal the
response_url fallback's chance to deliver a late answer.

- On agent_cancelled, finalize the stream (finish=true, "🛑 已中止" if empty)
  and schedule the response_url fallback so the bubble clears immediately when
  a run is cancelled, even past the poll window
- Do not force-finish a still-running stream on a timer; let it keep spinning
  until completion or cancel. Answers that finish after WeCom's ~6min poll
  window are delivered via response_url instead

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 17:26:06 +08:00
6vision
561631baba fix(wecom_bot): rescue late replies via response_url + fix degrade notice
Handle agent replies that finish after WeCom stops polling the passive
stream (the poll window is ~6min from the user's message).

- Capture response_url from the message callback and, when a reply is
  finalized but no poll picks it up within a short grace period, push it as
  a one-shot active markdown reply (valid 1h, single use)
- Guard against double delivery via delivered/url_sent flags
- Embed public image URLs in the active markdown; note when a local image
  can't be delivered post-timeout
- Append (instead of discarding) the unsupported-type notice for
  file/voice/video replies so streamed text is preserved
- Quiet the per-poll debug log and log stream completion with content size

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 18:24:33 +08:00
6vision
5c43c2f519 feat(wecom_bot): add callback (webhook) mode alongside long connection
Support receiving WeCom smart-bot messages via encrypted HTTP callback in
addition to the existing WebSocket long connection. Disabled by default
(wecom_bot_callback=false).

- Add wecom_bot_callback / wecom_bot_token / wecom_bot_encoding_aes_key /
  wecom_bot_port config keys
- Add WXBizJsonMsgCrypt-based crypto module for URL verification, callback
  decryption and passive-reply encryption (receive_id empty for internal bots)
- Reply asynchronously via the official stream-refresh polling: register a
  stream id on first reply, accumulate agent output into per-stream state, and
  serve the latest content (text + image) on each poll until finish
- Fall back to EncodingAESKey for media decryption when callback bodies carry
  no per-message aeskey
- Degrade unsupported passive replies (file/voice/video) to a text notice
- Expose the new fields in the Web console channel config

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 16:26:54 +08:00
zhayujie
8d67177a1b feat(agent): support user-initiated cancel for in-flight agent runs 2026-05-26 23:36:09 +08:00
zhayujie
bca97a1d14 feat(voice): enable TTS on Weixin / DingTalk / WeCom Bot with text-then-voice delivery
- Clear NOT_SUPPORT_REPLYTYPE on weixin, wecom_bot, dingtalk so TTS replies
  are actually synthesized for these channels.
- Wire desire_rtype=VOICE in weixin and wecom_bot _compose_context so the
  always_reply_voice / voice_reply_voice toggles take effect.
- DingTalk: send native sampleAudio (mediaId + duration). The media API
  only accepts ogg/amr, so convert TTS mp3/wav to amr on the fly.
- WeCom Bot: send native voice msgtype via ws (respond + active push),
  converting TTS audio to amr before upload.
- Weixin (ilink): no outbound voice item, deliver TTS as a file attachment.
- chat_channel: when a TEXT reply is converted to VOICE, stash original
  text in context["voice_reply_text"] and send a text bubble before the
  voice reply. Skipped for feishu_streamed and wechatcom_app, which
  already render text alongside the voice.
2026-05-21 17:29:26 +08:00
Zhao Ke Ke
249ea40ae3 fix(wecom_bot): Invalid control character 2026-05-12 18:45:03 +08:00
zhayujie
66b71c50e9 feat(wecom_bot): add Wecom Bot QR code scan auth 2026-03-31 21:27:50 +08:00
zhayujie
13c020eb61 fix(cli): cli output in wecom_bot 2026-03-28 19:26:59 +08:00
zhayujie
bc7f627253 fix(wecom_bot): compat with old websocket-client 2026-03-21 14:03:17 +08:00
zhayujie
8b45d6c750 docs: wecom_bot integration docs 2026-03-16 19:03:18 +08:00
zhayujie
a42f31fe52 feat: support wecom_bot stream card 2026-03-16 17:46:05 +08:00
zhayujie
d4480b695e feat(channel): add wecom_bot channel 2026-03-16 14:39:15 +08:00