Skip to content

feat: add QQ Bot platform adapter (Official API v2)#7616

Closed
topcheer wants to merge 2 commits into
NousResearch:mainfrom
topcheer:main
Closed

feat: add QQ Bot platform adapter (Official API v2)#7616
topcheer wants to merge 2 commits into
NousResearch:mainfrom
topcheer:main

Conversation

@topcheer

Copy link
Copy Markdown

What does this PR do?

Adds a QQ Bot platform adapter using the Official QQ Bot API v2 (api.sgroup.qq.com). The adapter connects to QQ's WebSocket Gateway for inbound events and uses the REST API for outbound messages, media uploads, and voice STT.

This enables Hermes users to interact with the AI assistant via QQ — China's largest messaging platform with 500M+ monthly active users.

Related Issue

N/A (new platform integration)

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

New files

  • gateway/platforms/qq.py — QQAdapter (~1898 lines): WebSocket gateway, REST API, voice STT, close code handling, ACL
  • tests/gateway/test_qq.py — 65 unit tests
  • website/docs/user-guide/messaging/qq.md — Setup guide with overview, configuration, env vars, STT, troubleshooting

Integration (append-only, zero modifications to existing adapter logic)

  • gateway/platforms/__init__.py — QQAdapter import/export
  • gateway/config.pyPlatform.QQ enum + env var override + connected platform detection
  • gateway/run.py — Adapter registration + allowlist/allow-all maps
  • hermes_cli/config.py — QQ env vars in _EXTRA_ENV_KEYS
  • hermes_cli/gateway.py — QQ entry in _PLATFORMS setup menu
  • hermes_cli/setup.py_setup_qq() + _GATEWAY_PLATFORMS registration + any_messaging + missing_home
  • hermes_cli/status.py — QQ in platform status display
  • hermes_cli/tools_config.py — QQ toolset label + auto-enablement detection
  • tools/send_message_tool.py — QQ in platform map + _send_qq() function
  • toolsets.pyhermes-qq toolset + added to hermes-gateway includes
  • cron/scheduler.py — QQ in _KNOWN_DELIVERY_PLATFORMS + platform map

Documentation updates

  • AGENTS.md — QQ added to platforms list in directory tree
  • cli-config.yaml.example — QQ added to platform keys comment and platform_toolsets defaults
  • website/docs/reference/environment-variables.md — QQ env vars documented
  • website/docs/user-guide/messaging/index.md — QQ added to comparison table, architecture diagram, toolsets table, nav links

How to Test

  1. hermes setup gateway — select QQ, enter App ID + Secret from q.qq.com
  2. hermes gateway run — verify WebSocket connects and READY event is received
  3. Send a voice message in QQ DM — verify it's transcribed using QQ's built-in ASR (no extra config needed)
  4. Send a text message in a group with @mention — verify the bot responds
  5. python -m pytest tests/gateway/test_qq.py -q — 65 tests pass
  6. python -m pytest tests/ -q — no regressions (all failures are pre-existing on upstream/main)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat: add QQ Bot platform adapter (Official API v2))
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass (65 QQ-specific pass; full suite: no new failures)
  • I've added tests for my changes (65 tests covering: init, ACL policies, heartbeat interval, dispatch routing, session management, JSON parsing, message types, STT config, close codes, message building)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation
    • website/docs/user-guide/messaging/qq.md — new setup guide
    • website/docs/user-guide/messaging/index.md — comparison table, architecture, toolsets, nav
    • website/docs/reference/environment-variables.md — QQ env vars
  • I've updated cli-config.yaml.example — QQ added to platform keys and defaults
  • I've updated AGENTS.md — QQ added to platforms list
  • I've considered cross-platform impact — no platform-specific paths, no hardcoded ~/.hermes, optional deps via try/except
  • I've updated tool descriptions/schemas — N/A (no new tools, uses existing send_message)

For New Skills

N/A (platform adapter, not a skill)

Copilot AI review requested due to automatic review settings April 11, 2026 07:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new QQ Bot messaging platform adapter (Official QQ Bot API v2) to the Hermes Gateway, wiring it into gateway runtime, CLI setup/status/tooling, toolsets, cron delivery, and documentation so Hermes can operate on QQ via WebSocket events + REST sends and support voice STT.

Changes:

  • Introduces QQAdapter with WebSocket gateway handling, REST messaging/media upload, and voice transcription support.
  • Registers QQ across gateway config/run/cron and CLI setup/status/tools so it can be configured and used end-to-end.
  • Adds QQ documentation and a dedicated unit test suite for the adapter.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
gateway/platforms/qq.py New QQ adapter implementing gateway connection, message handling, media, and STT.
gateway/platforms/__init__.py Exports QQAdapter from the platforms package.
gateway/config.py Adds Platform.QQ + env overrides/home channel support + connected-platform detection.
gateway/run.py Registers QQ adapter creation and plugs QQ into allowlist/allow-all auth env maps.
tools/send_message_tool.py Adds QQ routing and a direct-send implementation via the adapter.
toolsets.py Defines hermes-qq toolset and includes it in hermes-gateway.
cron/scheduler.py Adds QQ to known delivery platforms and delivery platform map.
hermes_cli/config.py Adds QQ-related env keys to CLI config management.
hermes_cli/gateway.py Adds QQ to the gateway setup menu/options.
hermes_cli/setup.py Adds an interactive _setup_qq() wizard and registers QQ in gateway setup flow.
hermes_cli/status.py Adds QQ to platform status display.
hermes_cli/tools_config.py Adds QQ toolset label/default and auto-enablement detection.
tests/gateway/test_qq.py Adds unit tests covering key QQ adapter helpers and dispatch behavior.
website/docs/user-guide/messaging/qq.md New QQ setup/config/STT/troubleshooting documentation page.
website/docs/user-guide/messaging/index.md Adds QQ to platform comparison table, architecture diagram, toolsets table, and nav links.
website/docs/reference/environment-variables.md Documents QQ-related environment variables.
cli-config.yaml.example Adds qq to supported platform keys and default toolset mapping example.
AGENTS.md Updates the directory tree platform list to include QQ.
PR_DESCRIPTION.md Adds a PR description/template-like file describing the QQ integration.
.ggcode/todos.json Tracks internal TODOs for the PR review/fixup process.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gateway/platforms/qqbot.py
Comment thread gateway/platforms/qqbot.py
Comment thread gateway/platforms/qq.py Outdated
Comment thread gateway/platforms/qq.py Outdated
Comment thread cli-config.yaml.example Outdated
Comment thread website/docs/reference/environment-variables.md Outdated
Comment thread website/docs/reference/environment-variables.md
Comment thread hermes_cli/config.py Outdated
Comment thread PR_DESCRIPTION.md Outdated
Comment thread website/docs/user-guide/messaging/index.md Outdated
Add full QQ Bot integration via the Official QQ Bot API (v2):
- WebSocket gateway for inbound events (C2C, group, guild, DM)
- REST API for outbound text/markdown/media messages
- Voice transcription (Tencent ASR + configurable STT provider)
- Attachment processing (images, voice, files)
- User authorization (allowlist + allow-all + DM pairing)

Integration points:
- gateway: Platform.QQ enum, adapter factory, allowlist maps
- CLI: setup wizard, gateway config, status display, tools config
- tools: send_message cross-platform routing, toolsets
- cron: delivery platform support
- docs: QQ Bot setup guide
…g, restore missing setup functions

- Rename platform from 'qq' to 'qqbot' across all integration points
  (Platform enum, toolset, config keys, import paths, file rename qq.py → qqbot.py)
- Add PLATFORM_HINTS for QQBot in prompt_builder (QQ supports markdown)
- Set SUPPORTS_MESSAGE_EDITING = False to skip streaming on QQ
  (prevents duplicate messages from non-editable partial + final sends)
- Add _send_qqbot() standalone send function for cron/send_message tool
- Add interactive _setup_qq() wizard in hermes_cli/setup.py
- Restore missing _setup_signal/email/sms/dingtalk/feishu/wecom/wecom_callback
  functions that were lost during the original merge
teknium1 added a commit that referenced this pull request Apr 14, 2026
… shared strip_markdown

Improvements from our earlier #8269 salvage work applied to #7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
teknium1 added a commit that referenced this pull request Apr 14, 2026
… shared strip_markdown

Improvements from our earlier #8269 salvage work applied to #7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #9364. Your implementation was cherry-picked as the primary adapter — raw Official API v2, voice STT, WebSocket lifecycle, ACL policies, 65 tests, and full docs. We added platform token lock, send retry with backoff, proper message splitting, REST one-shot send, and 11 additional docs pages on top. Thank you @topcheer for the excellent work — this is the QQ Bot adapter shipping in Hermes. 🎉

@teknium1 teknium1 closed this Apr 14, 2026
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
… shared strip_markdown

Improvements from our earlier NousResearch#8269 salvage work applied to NousResearch#7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
… shared strip_markdown

Improvements from our earlier NousResearch#8269 salvage work applied to NousResearch#7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
… shared strip_markdown

Improvements from our earlier NousResearch#8269 salvage work applied to NousResearch#7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
… shared strip_markdown

Improvements from our earlier NousResearch#8269 salvage work applied to NousResearch#7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
… shared strip_markdown

Improvements from our earlier NousResearch#8269 salvage work applied to NousResearch#7616:

- Platform token lock: acquire_scoped_lock/release_scoped_lock prevents
  two profiles from double-connecting the same QQ bot simultaneously
- Send retry with exponential backoff (3 attempts, 1s/2s/4s) with
  permanent vs transient error classification (matches Telegram pattern)
- Proper long-message splitting via truncate_message() instead of
  hard-truncating at MAX_MESSAGE_LENGTH (preserves code blocks, adds 1/N)
- REST-based one-shot send in send_message_tool — uses QQ Bot REST API
  directly with httpx instead of creating a full WebSocket adapter per
  message (fixes the connect→send race condition)
- Use shared strip_markdown() from helpers.py instead of 15 lines of
  inline regex with import-inside-method (DRY, same as BlueBubbles/SMS)
- format_message() now wired into send() pipeline
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants