fix(msteams): channel file attachments broken by overly-broad HTML fallback (#58617, #51749)#64645
Conversation
Greptile SummaryThis PR fixes two related bugs in the MS Teams channel media pipeline: (1) the Confidence Score: 5/5Safe to merge — all three root causes are correctly addressed, the fix is well-scoped, and test coverage directly validates the regressions. No P0 or P1 findings. The attachment sourcing change (inline array vs. nonexistent sub-resource), the fallback gate (attachment IDs vs. content-type), and the error-logging improvements are all logically sound. The No files require special attention. Reviews (1): Last reviewed commit: "fix(msteams): gate channel attachment fa..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aef95e98dd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments); | ||
| const hasHtmlFileAttachment = attachmentIds.length > 0; |
There was a problem hiding this comment.
Trigger Graph fallback for hosted-content HTML images
This change gates both Bot Framework and Graph fallback on attachmentIds.length > 0, so HTML messages without <attachment id="..."> now skip downloadMSTeamsGraphMedia entirely. That drops valid media cases where Teams only provides inline/hosted image markup (for example cid: or hosted-content <img> sources): downloadMSTeamsAttachments does not fetch cid: sources, so mediaList stays empty and the only remaining path that can fetch /hostedContents is bypassed. As a result, inline image attachments that previously resolved through Graph hosted content will be silently lost.
Useful? React with 👍 / 👎.
047a8cb to
8aca740
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8aca740277
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // too, so keying off contentType alone produces spurious 404 diagnostics | ||
| // for every mention-only message and masks real file attachments (#58617). | ||
| const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments); | ||
| const hasHtmlFileAttachment = attachmentIds.length > 0; |
There was a problem hiding this comment.
Keep Graph fallback for hosted-content HTML images
Gating both fallback paths on attachmentIds.length > 0 means HTML messages without <attachment id="..."> never reach downloadMSTeamsGraphMedia, even when they still contain media that only Graph can resolve (for example cid:/hosted-content images). In this code path, downloadMSTeamsAttachments cannot recover those sources because inline extraction skips cid: URLs, so inbound images are silently dropped whenever Teams sends mention-free hosted HTML without attachment tags.
Useful? React with 👍 / 👎.
093a12c to
8c86959
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c869595e1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // too, so keying off contentType alone produces spurious 404 diagnostics | ||
| // for every mention-only message and masks real file attachments (#58617). | ||
| const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments); | ||
| const hasHtmlFileAttachment = attachmentIds.length > 0; |
There was a problem hiding this comment.
Keep Graph fallback for HTML media without attachment IDs
Conditioning fallback on attachmentIds.length > 0 causes non-Bot-Framework messages with HTML media but no <attachment id="..."> tags to skip downloadMSTeamsGraphMedia, which drops valid inbound images that are only retrievable through Graph hosted content. Fresh evidence: extractInlineImageCandidates in extensions/msteams/src/attachments/shared.ts explicitly skips cid: sources, so the direct attachment downloader cannot recover those images after this gate short-circuits.
Useful? React with 👍 / 👎.
885e5b9 to
1ed0358
Compare
1ed0358 to
bd84012
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bd84012b0f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const bfMedia = await downloadMSTeamsBotFrameworkAttachments({ | ||
| serviceUrl, | ||
| attachmentIds, | ||
| tokenProvider, | ||
| maxBytes, |
There was a problem hiding this comment.
Forward logger to Bot Framework attachment downloader
Pass log through when calling downloadMSTeamsBotFrameworkAttachments; this call used to provide logger but now omits it, so failures inside the downloader (token acquisition errors, non-OK attachment info/view fetches, parse/read failures) no longer emit the warning diagnostics in attachments/bot-framework.ts. In personal-chat file upload scenarios this turns real download errors into a generic bot framework attachments fetch empty debug line, which regresses observability for the exact failure mode this change set is trying to make diagnosable.
Useful? React with 👍 / 👎.
…llback (openclaw#58617, openclaw#51749) (openclaw#64645) * fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749) * test(msteams): remove dead mock branch in graph.test.ts
…llback (openclaw#58617, openclaw#51749) (openclaw#64645) * fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749) * test(msteams): remove dead mock branch in graph.test.ts
…llback (openclaw#58617, openclaw#51749) (openclaw#64645) * fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749) * test(msteams): remove dead mock branch in graph.test.ts
…llback (openclaw#58617, openclaw#51749) (openclaw#64645) * fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749) * test(msteams): remove dead mock branch in graph.test.ts
…llback (openclaw#58617, openclaw#51749) (openclaw#64645) * fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749) * test(msteams): remove dead mock branch in graph.test.ts
Summary
Channel file attachments (users uploading files into a Teams channel conversation) were silently failing because the Graph media fallback was triggering on any HTML attachment — including @mention cards — and calling a nonexistent Graph sub-resource.
Root cause
hasHtmlAttachmentininbound-media.tstreated alltext/htmlattachments as file candidates, including mention cards\${messageUrl}/attachments— a sub-resource that does not exist in the Graph APIcatch {}blocks, masking the real failureFix
<attachment id="...">tags in the HTML contentchatMessage.attachmentsarray returned by the main message fetch (correct Graph path)catch {}with proper error loggingFixes #58617
Fixes #51749
Test plan
🤖 Generated with Claude Code