fix(feishu): classify native voice messages as VOICE for auto-transcription - #29235
fix(feishu): classify native voice messages as VOICE for auto-transcription#29235wuli666 wants to merge 1 commit into
Conversation
6a0a4c5 to
7b85002
Compare
…iption Lark's native "audio" msg_type is an in-app voice recording — uploaded audio files arrive as "file"/"media". But _resolve_normalized_message_type resolved the "audio" preferred type to MessageType.AUDIO, which the gateway treats as a non-transcribed file attachment (run.py: AUDIO -> audio_file_paths, "never STT"; VOICE -> audio_paths, "always STT"). Result: a Feishu voice note reached the agent as an untranscribable audio attachment and was silently ignored — the user's spoken message never became text. Every other platform that receives native voice notes (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, WeChat, WeCom, DingTalk, QQ, BlueBubbles, Mattermost, Yuanbao) classifies them as MessageType.VOICE. Feishu was the only one classifying them as AUDIO. This is the follow-up to NousResearch#28993, which added native voice-note transcription for Discord + DingTalk but did not cover Feishu. Return MessageType.VOICE for the "audio" branch. The branch is reached only for Lark's top-level audio msg_type (set in the normalizer; file uploads map to "document"), so VOICE is unconditionally correct here — no risk of auto-transcribing an uploaded music/audio file. - plugins/platforms/feishu/adapter.py: _resolve_normalized_message_type audio branch returns VOICE instead of resolving to AUDIO via mime. - tests/gateway/test_feishu.py: test_extract_audio_message_downloads_and_caches asserted the old AUDIO behavior on a fixture literally named voice.ogg — updated to expect VOICE (the corrected classification). - tests/gateway/test_feishu_voice_message_type.py: new focused regression tests (audio->VOICE with and without mime; photo/document/text unaffected). Rebased onto current main: the Feishu platform moved from the single-file gateway/platforms/feishu.py into the plugins/platforms/feishu/ package; the fix applies to the same _resolve_normalized_message_type logic at its new home. Verified the new voice tests fail when the branch resolves to AUDIO and pass with VOICE, while the photo/document/text cases are unaffected either way. Note: classification is mock-tested here; the downstream STT pipeline is the shared, already-proven path (NousResearch#28993). End-to-end verification on a live Feishu account would be a welcome confirmation. Refs NousResearch#28993 (sibling-gap: Feishu was the platform left uncovered).
7b85002 to
4f9d402
Compare
|
Thanks for the focused Feishu fix. Current The PR changes the exact resolver branch and updates the existing Automated hermes-sweeper review. |
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Summary
Two PRs address the same Feishu native voice-note misclassification by changing the audio resolver from MessageType.AUDIO to MessageType.VOICE, allowing the gateway to send native recordings through STT. #29235 applies the fix and regression coverage at the current plugin path, while #29295 implements the same underlying change against the removed pre-migration adapter path.
Related pull requests
- #29235
related— (+60/-2) — merge: Changes the activeplugins/platforms/feishu/adapter.pyresolver branch and adds focused coverage showing that nativeaudiomessages become VOICE regardless of MIME while other normalized types remain unaffected; this matches the keep_open review, which found no correctness, completeness, or design-fit issue. - #29295
duplicate— (+58/-3) — close as duplicate of #29235: The diff makes the same AUDIO-to-VOICE correction and adds useful MIME/file-upload checks, but it targets the removedgateway/platforms/feishu.pypath and is conflicting. Despite the keep_open review on #29295, its own review identifies that the change must be salvaged at the current plugin path, which #29235 already does cleanly.
Duplicates
#29235 and #29295 implement the same resolver correction for Feishu native audio messages; #29295 is effectively superseded by the current-path implementation in #29235.
Suggested consolidation
Merge #29235 because it fixes the reported cause in the active Feishu adapter and includes direct regression coverage. Close #29295 as a duplicate/superseded implementation: its substantive change is already represented by #29235, while its diff applies to a removed path and currently conflicts.
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 Dup29235 ["PRs duplicating each other"]
P29235["PR #29235 (open)"]
P29295["PR #29295 (open)"]
end
class P29235 open
class P29295 open
class P29235 target
click P29235 "https://github.com/NousResearch/hermes-agent/pull/29235"
click P29295 "https://github.com/NousResearch/hermes-agent/pull/29295"
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 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 10 kB of PR diffs, 6 kB of issue/PR text, 2 kB of discussion (3 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Delta since our previous triage comment
Since the previous triage comment, @teknium1 closed #29295 as a stale-target implementation and confirmed that its intent is being salvaged by #29235 at the live plugin path. This new contributor decision confirms and extends our earlier analysis: #29295 cannot apply because it patches the deleted pre-migration adapter.
Changed pull requests
- #29295 [closed]
duplicate— (+58/-3) — closed as superseded by #29235: Despite the earlier keep_open review, @teknium1’s newer closure confirms that the diff targets deletedgateway/platforms/feishu.py; the equivalent AUDIO-to-VOICE fix remains relevant as the superseded reference implementation now covered at the active path by #29235.
Suggested consolidation
The recommendation is unchanged: merge #29235; #29295 is now closed as its stale-path duplicate.
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 Dup29235 ["PRs duplicating each other"]
P29235["PR #29235 (open)"]
P29295["PR #29295 (closed)"]
end
class P29235 open
class P29295 closed
class P29235 target
click P29235 "https://github.com/NousResearch/hermes-agent/pull/29235"
click P29295 "https://github.com/NousResearch/hermes-agent/pull/29295"
classDef changedSince stroke:#dc2626,stroke-width:3px,stroke-dasharray: 6 3
class P29295 changedSince
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).
Dashed red border = changed since our previous triage comment (1 added/updated, 1 removed graph elements).
Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 10 kB of PR diffs, 6 kB of issue/PR text, 3 kB of discussion (4 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
…dio path dedup Trimmed cherry-pick of PR #40592 (duration + dedup hunks only; the voice-classification hunk duplicates #29235 and the send_voice Opus rewrite is out of scope for this inbound-focused PR): - adapter.py: ffprobe duration (off-loop) attached to Feishu voice uploads via _build_file_upload_body(duration=...) and the audio message payload (#16524, #8300) - gateway/run.py: TTS dedup narrowed to the current turn; _enrich_message_with_transcription dedups repeated audio paths Refs #40592 #16524 #8300
…dio path dedup Trimmed cherry-pick of PR #40592 (duration + dedup hunks only; the voice-classification hunk duplicates #29235 and the send_voice Opus rewrite is out of scope for this inbound-focused PR): - adapter.py: ffprobe duration (off-loop) attached to Feishu voice uploads via _build_file_upload_body(duration=...) and the audio message payload (#16524, #8300) - gateway/run.py: TTS dedup narrowed to the current turn; _enrich_message_with_transcription dedups repeated audio paths Refs #40592 #16524 #8300
…dio path dedup Trimmed cherry-pick of PR #40592 (duration + dedup hunks only; the voice-classification hunk duplicates #29235 and the send_voice Opus rewrite is out of scope for this inbound-focused PR): - adapter.py: ffprobe duration (off-loop) attached to Feishu voice uploads via _build_file_upload_body(duration=...) and the audio message payload (#16524, #8300) - gateway/run.py: TTS dedup narrowed to the current turn; _enrich_message_with_transcription dedups repeated audio paths Refs #40592 #16524 #8300
|
Merged into main via consolidated salvage PR #73515 (merge Your contribution is credited to you in git history. Thank you! Closing this PR as merged-via-salvage. |
…dio path dedup Trimmed cherry-pick of PR NousResearch#40592 (duration + dedup hunks only; the voice-classification hunk duplicates NousResearch#29235 and the send_voice Opus rewrite is out of scope for this inbound-focused PR): - adapter.py: ffprobe duration (off-loop) attached to Feishu voice uploads via _build_file_upload_body(duration=...) and the audio message payload (NousResearch#16524, NousResearch#8300) - gateway/run.py: TTS dedup narrowed to the current turn; _enrich_message_with_transcription dedups repeated audio paths Refs NousResearch#40592 NousResearch#16524 NousResearch#8300
What does this PR do?
Feishu (Lark) native voice messages were never transcribed. Lark's top-level
audiomsg_type is an in-app voice recording (uploaded audio files arrive asfile/media), but_resolve_normalized_message_typeresolved theaudiopreferred type toMessageType.AUDIO. The gateway treats AUDIO as a non-transcribed file attachment:So a Feishu voice note reached the agent as an untranscribable attachment — the user's spoken message silently never became text.
Feishu was the only platform getting this wrong. Telegram, Discord, Slack, WhatsApp, Signal, Matrix, WeChat, WeCom, DingTalk, QQ, BlueBubbles, Mattermost, and Yuanbao all classify native voice notes as
MessageType.VOICE. This is the follow-up to #28993, which added native voice-note transcription for Discord + DingTalk but did not cover Feishu.Fix
Return
MessageType.VOICEfor theaudiobranch in_resolve_normalized_message_type. That branch is reached only for Lark's top-levelaudiomsg_type (the normalizer maps file uploads todocument), so VOICE is unconditionally correct here — no risk of auto-transcribing an uploaded music/audio file.Changes Made
gateway/platforms/feishu.py—audiobranch returnsMessageType.VOICEinstead of resolving to AUDIO via mime.tests/gateway/test_feishu.py—test_extract_audio_message_downloads_and_cachesasserted the old AUDIO behavior on a fixture literally namedvoice.ogg; updated to expect VOICE (the corrected classification).tests/gateway/test_feishu_voice_message_type.py(new) — focused regression:audio→ VOICE (with and without mime); photo/document/text unaffected.How to Test
Verified the new voice tests fail when the branch resolves to AUDIO and pass with VOICE; the photo/document/text cases are unaffected either way.
Scope honesty: classification is mock-tested here; the downstream STT pipeline is the shared, already-proven path from #28993. End-to-end verification on a live Feishu account would be a welcome confirmation — I don't have one.
Related Issue
No tracking issue — sibling-gap found while reviewing #28993 (Feishu was the platform left uncovered). Happy to file one if preferred.
Type of Change
Checklist
Code
fix(feishu): ...)pytest tests/ -q— ran the fulltests/gateway/test_feishu.py(198 passed) + new tests; did not run the whole repo suite locally, relying on CIDocumentation & Housekeeping
audio-is-voice rationale; N/A elsewhere