Skip to content

feat(qqbot): add media attachment support for voice/image/video/file - #18353

Open
Allonz wants to merge 4 commits into
NousResearch:mainfrom
Allonz:feat/qqbot-voice-send
Open

feat(qqbot): add media attachment support for voice/image/video/file#18353
Allonz wants to merge 4 commits into
NousResearch:mainfrom
Allonz:feat/qqbot-voice-send

Conversation

@Allonz

@Allonz Allonz commented May 1, 2026

Copy link
Copy Markdown

Summary

  • Add native media attachment support for QQ Bot platform
  • Support sending voice, image, video, and file attachments via QQ Bot v2 API
  • Auto-detect chat type from target format (c2c:/group:/guild:)
  • Map file extensions to QQ Bot file_type (1=image, 2=video, 3=voice, 4=file)
  • Use base64 encoding for file upload via JSON API

Changes

  • Modified tools/send_message_tool.py to add _send_qqbot media support
  • Added chat type detection: c2c:<openid>, group:<group_openid>, guild:<channel_id>
  • Implemented media upload via QQ Bot v2 API endpoints

Test Plan

  • Voice message sent successfully via QQ
  • Media file upload working with base64 encoding
  • Chat type detection working for c2c and group chats

Allonz added 4 commits May 1, 2026 16:51
- Add media file upload support to _send_qqbot function
- Support chat_type detection from target format (c2c:/group:/guild:)
- Upload media via QQ Bot v2 API (/v2/users/{openid}/files, /v2/groups/{group_openid}/files)
- Map file extensions to QQ Bot file_type (1=image, 2=video, 3=voice, 4=file)
- Include media in message payload via 'file_info' field
- Update error messages to include qqbot in supported platforms
- Update schema description with qqbot target format examples
@alt-glitch alt-glitch added type/feature New feature or request platform/qqbot QQ Bot adapter P3 Low — cosmetic, nice to have labels May 1, 2026
@alt-glitch

alt-glitch commented May 1, 2026

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Re-triage correction: #18321 is closed/unmerged; #18353 is the author's repaired active resubmission. Current main still lacks QQBot MEDIA routing, so this PR is related work, not a duplicate.

1 similar comment
@alt-glitch

alt-glitch commented May 1, 2026

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Re-triage correction: #18321 is closed/unmerged; #18353 is the author's repaired active resubmission. Current main still lacks QQBot MEDIA routing, so this PR is related work, not a duplicate.

@Allonz

Allonz commented May 1, 2026

Copy link
Copy Markdown
Author

Likely duplicate of #18321 — same QQ Bot media attachment feature, previous version was closed.

I closed #18321 PR ,because there are some bugs when I test again,so I fixed them and commit a new one,thanks

@Allonz

Allonz commented May 1, 2026

Copy link
Copy Markdown
Author

I closed #18321 PR ,because there are some bugs when I test again,so I fixed them and commit a new one,thanks

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for tackling a real QQ Bot delivery gap. Current main still rejects or drops QQBot MEDIA: attachments in tools/send_message_tool.py:1034-1047, and its standalone sender is text-only at tools/send_message_tool.py:1851-1919.

Problems

  • The proposed media payload retains msg_type: 0. The maintained QQ adapter defines rich media as MSG_TYPE_MEDIA = 7 in gateway/platforms/qqbot/constants.py:64 and sends media.file_info with that type at gateway/platforms/qqbot/adapter.py:2908-2927.
  • The schema adds qqbot:c2c: / qqbot:group: targets, but _parse_target_ref has no QQBot branch (tools/send_message_tool.py:531-616), so those advertised targets would go to directory resolution rather than the new sender.
  • The branch predates current main's C2C/group text fallback from 3792b77bd; the replacement needs to retain that behavior. No tests accompany the new upload/send flow.

Suggested changes

  • Rework the change on current main, preserving the fallback; send one rich-media message per uploaded file with type 7.
  • Add QQBot target parsing and mocked C2C/group upload, failure, media-only, text-plus-media, and multi-file tests.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
@alt-glitch alt-glitch added comp/tools Tool registry, model_tools, toolsets needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists and removed sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades P3 Low — cosmetic, nice to have labels Jul 18, 2026

@GottZ GottZ 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.

This was generated by AI during triage.

Summary

Eight PRs address the QQBot MEDIA: delivery gap. The earlier diffs either add incomplete tool-local REST upload paths or partial adapter routing, while #40457 consolidates live-adapter and standalone delivery around shared QQBot upload, target-resolution, and authentication code with dedicated tests.

Related pull requests

  • #10257 [closed] related — (+131/-16) — superseded/incomplete: fixes the authorization header and adds JSON/base64 media upload, but its media-only guard is a no-op and a follow-up platform guard regresses supported-media handling. It remains relevant because the header fix landed separately in #11569, while its media implementation did not.
  • #18321 [closed] duplicate — (+108/-11) — superseded by #18353: adds C2C/group upload routing, but uses multipart upload and sends uploaded media with msg_type: 0; the author closed it after finding bugs and submitted #18353 as the repair.
  • #18353 related — (+114/-11) — do not merge as-is: routes QQBot media and switches uploads to JSON/base64, but still sends media with msg_type: 0, advertises prefixed targets without adding the required parser path, replaces newer text fallback behavior, and adds no tests. Despite the keep_open review on #18353, #40457 now implements the requested type-7, target-resolution, fallback, and test coverage more completely.
  • #26994 [closed] related — (+301/-2) — superseded duplicate: adds a separate C2C-first REST sender with URL/local uploads, but uses incorrect media/file-type values and msg_type: 2, assumes a media-item shape inconsistent with the surrounding tuple contract, and sends only the first successful upload. It remains relevant as a closed prior attempt, originally closed in favor of #15215.
  • #29716 related — (+120/-33) — superseded: correctly routes media and uses msg_type: 7, but duplicates the adapter protocol with inline base64, omits msg_seq and generic filenames, probes endpoints broadly, and has no tests. Despite the keep_open review on #29716, #40457 reuses chunked upload and the maintained media contract and covers both live and standalone paths.
  • #30347 related — (+253/-4) — superseded: introduces an active-adapter registry but the actual tool route bypasses its own adapter helper for another REST uploader, hard-codes C2C upload behavior, bypasses profile-aware configuration, and can report success after failed or skipped media operations. Despite the keep_open review on #30347, #40457 directly implements the review's requested adapter-backed dispatch, checked results, standalone fallback, and tests.
  • #39729 [closed] related — (+123/-3) — superseded adapter-backed attempt: reuses a live QQAdapter and its native media methods, but depends on a singleton, mishandles the (path, is_voice) media tuple, requires a running gateway, and lacks standalone delivery and tests. It remains relevant because it established the preferred adapter-backed direction before being closed in favor of #39430.
  • #40457 related — (+1408/-165) — preferred consolidation: routes live delivery through native QQAdapter methods and out-of-process delivery through a registered standalone sender, sharing QQApiClient, target normalization, authentication, type-7 messaging, chunked upload, and document semantics. The diff addresses the contributor keep_open review on #40457 that rejected the earlier raw REST/base64 and 7 MB path; the revised branch adds focused tests and reports 353 targeted tests passing after rebase.

Duplicates

#10257, #18321, #18353, #26994, and #29716 are successive tool-local REST implementations of substantially the same QQBot media upload/send change; #30347 and #39729 are partial adapter-backed variants. #40457 subsumes both clusters with shared live-adapter and standalone delivery.

Suggested consolidation

Merge #40457 — it is the only candidate shown that addresses the complete root cause across live gateway and CLI/cron/out-of-process delivery while reusing QQBot-owned authentication, target resolution, rich-media type 7, and chunked upload, with dedicated regression coverage. Close #18353, #29716, and #30347 as superseded duplicates; retain #10257, #18321, #26994, and #39729 as closed historical references.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup18321 ["PRs duplicating each other"]
        P18321["PR #18321 (closed)"]
        P18353["PR #18353 (open)"]
    end
    class P18321 closed
    class P18353 open
    class P18353 target
    click P18321 "https://github.com/NousResearch/hermes-agent/pull/18321"
    click P18353 "https://github.com/NousResearch/hermes-agent/pull/18353"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).

Cross-PR triage: Reviewed 8 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 144 kB of PR diffs, 16 kB of issue/PR text, 19 kB of discussion (25 comments), 3 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tools Tool registry, model_tools, toolsets needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists platform/qqbot QQ Bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants