- Bump channel package versions to 0.13.0
- Add publish steps for @qwen-code/channel-base and @qwen-code/channel-plugin-example
- Update version script to convert file: references to semver for published packages
This enables proper npm publishing of channel packages during the release process.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Update channel-base to use built dist/ output with proper exports
- Add README with quick start guide and usage instructions
- Add qwen-extension.json manifest for extension discovery
- Add start-server CLI for running the mock WebSocket server
- Update dependencies from local file: to npm version
This enables the plugin-example package to be published and installed
as a standalone extension for testing the channel plugin system.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add comprehensive developer guide for building channel plugins
- Add user-facing docs for installing/configuring custom channel plugins
- Replace custom-channels.md with new plugins.md
- Rename @qwen-code/channel-mock to @qwen-code/channel-plugin-example
- Add messageId field to Envelope type for response correlation
This provides clear documentation for developers building custom channel
adapters and renames the mock package to better reflect its purpose as
a reference implementation example.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add @qwen-code/channel-mock package with MockPluginChannel
- Add createMockServer for programmatic test control via WebSocket
- Refactor integration test to use real WebSocket E2E flow
This enables testing the full channel pipeline (WebSocket → ChannelBase → AcpBridge → agent)
instead of the previous in-process loopback approach.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add ExtensionChannelConfig interface for declaring channels in extension manifests
- Add loadChannelsFromExtensions() to discover and register channel plugins from active extensions
- Integrate extension channel loading into channel start commands
This enables extensions to contribute new channel types (e.g., Telegram, Slack) without modifying core code.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Refactor channel system to use a formal plugin interface:
- Add ChannelPlugin interface to @qwen-code/channel-base (channelType,
displayName, requiredConfigFields, createChannel factory)
- Each built-in adapter (Telegram, WeChat, DingTalk) exports a plugin object
- Replace hardcoded if/else factory with a Map-based channel registry
- Config validation now uses plugin's requiredConfigFields dynamically
- ChannelType changed from fixed union to string for extensibility
- Multi-channel mode now picks model from first channel config
This is the foundation for external plugin support — built-in channels
go through the exact same code path that third-party plugins will use.
Two bugs caused cross-talk between DM and group conversations:
1. Session routing key only used senderId, so the same user in DM and
group shared one ACP session (and conversation context). Now includes
chatId: `channelName:senderId:chatId`.
2. Concurrent messages on the same session caused textChunk listener
pollution in AcpBridge.prompt(), leaking response text across chats.
Added per-session promise queue in ChannelBase to serialize prompts.
- 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>
- 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>
- 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>
- 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>
- 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>
- Add referencedText field to Envelope for quoted/replied-to messages
- TelegramAdapter extracts text from reply_to_message
- WeixinAdapter extracts text from ref_msg field
- ChannelBase prepends referenced text to agent prompt
This allows the agent to see what message a user is replying to,
providing better context for conversations in both Telegram and WeChat.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add /help, /clear (aliases: /reset, /new), /status commands to ChannelBase
- Commands are handled locally without agent round-trip
- TelegramAdapter skips "Working..." indicator for local commands
- Update docs to reflect new command structure
This provides a consistent command interface across all channel types
(Telegram, WeChat, etc.) with platform-specific extensibility.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add `qwen channel status` to check running service info
- Add `qwen channel stop` to gracefully stop the service
- Add PID file tracking to prevent duplicate service instances
- Update documentation with new commands and usage
This enables users to manage the channel service from another terminal
without needing to use Ctrl+C on the foreground process.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add session persistence to SessionRouter for crash recovery
- Add loadSession method to AcpBridge for restoring sessions
- Add ChannelBaseOptions to support external router injection
- Refactor start.ts to support both standalone and gateway modes
- Extract config utilities into separate module
This enables channels to recover sessions after bridge crashes and
supports running multiple channels under a gateway process.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add photo message handling in Telegram adapter with base64 encoding
- Add document/file message handling with temp directory storage
- Extend WeChat adapter to support file downloads from CDN
- Refactor envelope building into reusable buildEnvelope method
- Rename ImageCdnRef to CdnRef for generic media handling
This enables users to send images and files through both Telegram and WeChat channels, with files saved to a temp directory for agent access.
- Add model configuration option for channel-specific model selection
- Support base64-encoded images in prompts via AcpBridge
- Add media utilities for WeChat/Weixin channel
- Update settings schema for model configuration
Enables channels to process images and use custom models.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add GroupGate class for group access control with three policies:
disabled (default), allowlist, and open
- Implement mention gating: bot only responds when @mentioned or replied to
in groups (configurable per-group)
- Extend Envelope type with isGroup, isMentioned, isReplyToBot fields
- Update TelegramAdapter to detect group context and mentions
- Add comprehensive documentation for group chat setup and troubleshooting
This enables using Qwen Code bots in Telegram groups with fine-grained
access control and mention-based activation to prevent noise.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
The trust/isTrustedFolder logic was accidentally dropped during the
permission system refactor in feat/support-permission (PR #2283).
Previously, shouldConfirmExecute() returned false (no confirmation) when
both conditions were met:
- MCP server config has trust: true
- The workspace folder is trusted (isTrustedFolder())
The refactor replaced shouldConfirmExecute() with getDefaultPermission() but
left out the trust check entirely, adding a comment claiming 'trust logic is
now handled by PM rules' — however no PM rules were ever generated from the
trust setting, making trust: true completely non-functional.
This fix restores the original behavior: MCP tools from a trusted server
(trust: true) auto-approve only when the workspace is also trusted, preserving
the security gate that prevents trust settings from bypassing confirmation in
untrusted folders.
- Add buildHumanReadableRuleLabel() to convert raw permission rules into
natural-language descriptions for the 'Always Allow' UI options
- Add PermissionManager.findMatchingDenyRule() to surface which deny rule
caused a tool to be blocked, improving error messages in coreToolScheduler
- Update ToolConfirmationMessage to use friendly labels with i18n support
- Add comprehensive tests for new permission features and multi-directory
search in glob, grep, and ripGrep tools
- Fix integration test for tool-control allowedTools configuration
- Add PairingStore for managing pending requests and approved users
- Update SenderGate to support pairing policy with code generation
- Add CLI commands: `qwen channel pairing list/approve`
- Document pairing flow with rules and usage examples
This allows unknown senders to request access via a pairing code
that the bot operator approves through the CLI.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>