* feat: supports weixin personal account
* feat(weixin): update documentation for personal WeChat integration and add QR code image
* feat(weixin): refactor send method to streamline message handling
* fix(weixin): correct AES key encoding in media payload construction
* feat(weixin): update weixin_oc_base_url description for clarity in config metadata
* feat(weixin): enhance WeChat integration with QR code support and configuration updates
* feat(weixin): implement WeixinOCClient for improved media handling and API requests
* feat(platform): update platform status refresh interval to 5 seconds
* fix(lark): defer streaming card creation and renew card on tool call break
- Defer CardKit streaming card creation until the first text token
arrives, preventing an empty card from rendering before content.
- Handle `type="break"` signal in send_streaming: close the current
card and lazily create a new one for post-tool-call text, so the
new card appears below the tool status message in correct order.
- Only emit "break" signal when show_tool_use is enabled; when tool
output is hidden, the AI response continues on the same card.
* style: format ruff
* fix: cr bug
* fix: cr
Fixes#6294
QQ official bot receives emoji/sticker messages as raw XML-like tags:
`<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">`
This made the LLM unable to understand the emoji content.
Changes:
- Added `_parse_face_message()` method to parse face message format
- Decode base64 `ext` field to get emoji description text
- Replace face tags with `[表情:描述]` format for readability
Example:
- Input: `<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">`
- Output: `[表情:[满头问号]]`
Co-authored-by: ccsang <ccsang@users.noreply.github.com>
* fix(qqofficial): fix streaming message delivery for C2C
* fix(qqofficial): rewrite send_streaming for C2C vs non-C2C split
* fix(qqofficial): add _extract_response_message_id for safe id extraction
* fix(qqofficial): flush stream segment on tool-call break signal
* fix(qqofficial): downgrade rich-media to non-stream send in C2C
* fix(qqofficial): auto-append \n to final stream chunk (state=10)
* fix(qqofficial): propagate stream param to all _send_with_markdown_fallback call sites
* fix(qqofficial): retry on STREAM_MARKDOWN_NEWLINE_ERROR with newline fix
* fix(qqofficial): handle None/non-dict response in post_c2c_message gracefully
* fix(qqofficial): remove msg_id from video/file media payloads in send_by_session
QQ API rejects msg_id on proactive media (video/file, msg_type=7) messages
sent via the tool-call path, returning "请求参数msg_id无效或越权". The
msg_id passive-reply credential is consumed by the first send and cannot be
reused for subsequent media uploads in the same session.
Remove msg_id from the payload after setting msg_type=7 for video and file
sends, for both FRIEND_MESSAGE (C2C) and GROUP_MESSAGE paths.
* fix(qqofficial): replace deprecated get_event_loop() with get_running_loop()
asyncio.get_event_loop() is deprecated since Python 3.10 and raises a
DeprecationWarning (or errors) when called from inside a running coroutine
without a current event loop set on the thread. Replace both call-sites
in the streaming throttle logic with asyncio.get_running_loop(), which is
the correct API to use inside an already-running async context.
Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
---------
Co-authored-by: 2ndelement <2ndelement@users.noreply.github.com>
Co-authored-by: Claude Sonnet <noreply@anthropic.com>
* feat: implement websockets transport mode selection for chat
- Added transport mode selection (SSE/WebSocket) in the chat component.
- Updated conversation sidebar to include transport mode options.
- Integrated transport mode handling in message sending logic.
- Refactored message sending functions to support both SSE and WebSocket.
- Enhanced WebSocket connection management and message handling.
- Updated localization files for transport mode labels.
- Configured Vite to support WebSocket proxying.
* feat(webchat): refactor message parsing logic and integrate new parsing function
* feat(chat): add websocket API key extraction and scope validation
* feat: support registering command aliases for Telegram
Now when registering commands with aliases, all aliases will be
registered as Telegram bot commands in addition to the main command.
Example:
@register_command(command_name="draw", alias={"画", "gen"})
Now /draw, /画, and /gen will all appear in the Telegram command menu.
* feat(telegram): add duplicate command name warning when registering commands
Log a warning when duplicate command names are detected during Telegram
command registration to help identify configuration conflicts.
- Add _send_voice_with_fallback helper to deduplicate voice forbidden handling
- Catch telegram.error.BadRequest instead of bare Exception with string matching
- Add text field to Record component to preserve TTS source text
- Store original text in Record during TTS conversion for use as document caption
- Skip _send_chat_action when chat_id is empty to avoid unnecessary warnings