Commit graph

10 commits

Author SHA1 Message Date
chinesepowered
b6e8f89687
fix(dingtalk): only suffix '(cont.)' on continuation chunks, not first (#2977) 2026-04-18 08:11:46 +08:00
易良
0ca2d23103
fix(channels/dingtalk): prioritize senderStaffId over senderId for allowedUsers matching (#3294)
DingTalk provides two user identifiers: `senderId` (an internal platform ID
like `$:LWCP_v1:xxx`) and `senderStaffId` (the human-readable staff/employee
ID). The current code uses `senderId` first when constructing the Envelope,
which means `allowedUsers` configuration cannot match against the staff ID
that users actually know and configure.

Swap the priority so `senderStaffId` is preferred when available, falling back
to `senderId` only when `senderStaffId` is absent.

Made-with: Cursor
2026-04-15 22:34:08 +08:00
tanzhenxin
7bbd5e6471 fix(channels): address PR review — security, bugs, and reliability
- fix: sanitize remote filenames with basename() and isolate uploads
  in UUID subdirs to prevent path traversal and collision (#2-4, #27)
- fix: use crypto.randomInt() for pairing codes instead of Math.random() (#5)
- fix: pass config.sessionScope instead of hardcoded 'user' (#6);
  add per-channel scope overrides via setChannelScope() for startAll (#7)
- fix: removeSession now returns removed session IDs and persists
  when chatId is provided (#8)
- fix: /clear only removes the cleared session from instructedSessions,
  not all sessions (#9)
- fix: DingTalk @mention stripping now removes only the first mention
  instead of all mentions (#10)
- fix: remove dead TELEGRAF_COMMANDS Set and its guard (#13)
- fix: WeChat cursor saved after message processing, not before (#14)
- fix: crash recovery uses time-window counting instead of resettable
  counter to prevent infinite restart loops (#17)
- fix: call channel.disconnect() before exit on crash exhaustion (#18)
2026-03-31 00:57:59 +00:00
tanzhenxin
7251da0152 feat(channels): add dispatch modes and prompt lifecycle hooks
Add three dispatch modes for handling concurrent messages:
- steer (default): cancel current prompt and start new one
- collect: buffer messages and coalesce into follow-up prompt
- followup: queue messages for sequential processing

Introduce onPromptStart/onPromptEnd lifecycle hooks for working
indicators. These fire only when a prompt actually begins processing,
not for buffered (collect mode) or gated/blocked messages.

Refactor Telegram, WeChat, and DingTalk adapters to use the new hooks
instead of overriding handleInbound, simplifying the working indicator
pattern and ensuring correct behavior with dispatch modes.

This enables better UX for async workflows and prevents indicator
leaks when messages are buffered or cancelled.
2026-03-28 06:19:02 +00:00
tanzhenxin
3e0f213ea3 feat(channels): add structured attachment support for file handling
- Add Attachment interface with type, data, filePath, mimeType, fileName
- Resolve attachments in ChannelBase before prompting bridge
- Update DingTalk, Telegram, Weixin adapters to use structured attachments
- Clean up placeholder text when files are received
- Export Attachment type from base package index

This enables proper handling of images and files across all channels,
separating attachment metadata from message text.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-27 14:50:24 +00:00
tanzhenxin
9f4dd53198 feat(channels): add DingTalk reply/quote message context support
- Add interfaces for DingTalkRepliedMsg and DingTalkRichTextPart types
- Support both newer text.repliedMsg and legacy quoteMessage formats
- Extract quoted message context with isReplyToBot detection
- Summarize replied content (text, richText, media placeholders)

This enables the bot to understand when users are replying to specific
messages and provides context about what message is being referenced.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 09:08:36 +00:00
tanzhenxin
a61189b232 feat(channels): add DingTalk media download support
- Handle richText, picture, file, audio, video message types
- Download media via DingTalk API two-step flow
- Attach images as base64, save other files to temp dir
- Add DingTalkMessageData interface for richer payloads

This enables the DingTalk channel to process media attachments
in incoming messages.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 08:49:56 +00:00
tanzhenxin
6c6057cf9c feat(channels): add DingTalk markdown normalization
- Convert tables to pipe-separated plain text (DingTalk doesn't render tables)
- Split long messages into chunks respecting ~3800 char limit
- Handle code fences across chunk boundaries
- Extract title from first markdown line for webhook payload

This ensures markdown content renders correctly in DingTalk's limited renderer.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 08:34:34 +00:00
tanzhenxin
217964b849 feat(channels): add reaction feedback and webhook caching for DingTalk
- Cache sessionWebhook by conversationId for reliable message routing
- Show 👀 reaction while processing messages, then recall it
- Use conversationId as chatId instead of webhook URL
- Fix rawData parsing for already-parsed message data

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 08:29:27 +00:00
tanzhenxin
92c54ff309 feat(channels): add DingTalk channel adapter
- Add @qwen-code/channel-dingtalk package with stream-based bot integration
- Support clientId/clientSecret authentication for DingTalk
- Add message deduplication and group chat mention handling
- Update ChannelConfig type to include dingtalk channel type

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 08:03:43 +00:00