fix(slack): surface files_upload_v2 confirmation in SentMessage.raw#117
Conversation
SlackAdapter._upload_files already returns the list of Slack-confirmed file IDs, but post_message discarded the return and ThreadImpl._create_sent_message hardcoded raw=None, so the confirmation never reached SentMessage.raw. Slack was the only file-capable adapter to drop upload confirmation; discord/telegram upload inline and expose the platform response naturally. - post_message: capture _upload_files' return and augment RawMessage.raw with "uploaded_file_ids" on every return path that can carry files (file-only, card, table, text), via a new _augment_raw_with_uploads helper. None means no upload; empty list means Slack confirmed zero attachments. raw is augmented, not replaced — non-breaking. - thread.py: _create_sent_message accepts and propagates a raw parameter; the post() call site passes raw_msg.raw through. Platform-agnostic, so discord/telegram real platform responses now flow through too. Tests: 3 in test_slack_api.py (file-only, text+files, text-only no-augment) and 1 end-to-end in test_thread_faithful.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughThis PR captures Slack-uploaded file IDs in the Slack adapter, augments adapter RawMessage.raw with that data when present, propagates the adapter raw through ThreadImpl into SentMessage.raw, updates message-history persistence to null raw, and adds tests and changelog/version bump. ChangesUpload confirmation metadata propagation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Warning Review ran into problems🔥 ProblemsStopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a fix to surface Slack-confirmed file IDs through the post() method. Previously, SlackAdapter._upload_files computed these IDs but they were discarded, and ThreadImpl._create_sent_message hardcoded raw=None. The changes update post_message in the Slack adapter to augment RawMessage.raw with "uploaded_file_ids", and update ThreadImpl._create_sent_message to accept and propagate the adapter's raw payload into SentMessage.raw. Corresponding unit and integration tests have been added to verify this behavior. There are no review comments, and I have no additional feedback to provide.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/chat_sdk/thread.py (1)
1125-1136:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPreserve
SentMessage.rawacrosssent.edit()calls.
post()now correctly setsraw, but_edit()rebuilds a newSentMessagewithout forwarding it, sorawis lost after the first edit.Suggested fix
async def _edit(new_content: Any) -> SentMessage: await adapter.edit_message(thread_id, message_id, new_content) - return thread_impl._create_sent_message(message_id, new_content) + return thread_impl._create_sent_message(message_id, new_content, thread_id, raw=raw)Also applies to: 1164-1164
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/chat_sdk/thread.py` around lines 1125 - 1136, The edit helper _edit currently rebuilds a SentMessage via thread_impl._create_sent_message without preserving the original SentMessage.raw, so ensure the raw payload is forwarded: capture the existing raw value from the surrounding scope (the raw parameter) and pass it into thread_impl._create_sent_message when returning the edited SentMessage in _edit; apply the same change to the other edit helper at the second occurrence (around the _edit at 1164) so SentMessage.raw is preserved across sent.edit() calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/chat_sdk/thread.py`:
- Around line 1125-1136: The edit helper _edit currently rebuilds a SentMessage
via thread_impl._create_sent_message without preserving the original
SentMessage.raw, so ensure the raw payload is forwarded: capture the existing
raw value from the surrounding scope (the raw parameter) and pass it into
thread_impl._create_sent_message when returning the edited SentMessage in _edit;
apply the same change to the other edit helper at the second occurrence (around
the _edit at 1164) so SentMessage.raw is preserved across sent.edit() calls.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e086b0a5-d494-4e60-8f66-d5d31f9b1435
📒 Files selected for processing (6)
CHANGELOG.mdpyproject.tomlsrc/chat_sdk/adapters/slack/adapter.pysrc/chat_sdk/thread.pytests/test_slack_api.pytests/test_thread_faithful.py
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4ad7267ac
ℹ️ 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".
| files = extract_files(message) | ||
| if files: | ||
| await self._upload_files(files, channel, thread_ts or None) | ||
| uploaded_file_ids = await self._upload_files(files, channel, thread_ts or None) |
There was a problem hiding this comment.
Read Slack file IDs from the actual response shape
When this new path surfaces _upload_files()'s return value, real slack_sdk uploads will usually report uploaded_file_ids: []: the SDK's files_upload_v2 returns the files.completeUploadExternal response and puts uploaded files at completion["files"][i]["id"] (plus completion.data["file"] for a singleton), while _upload_files() only scans a nested uploaded["files"] list at lines 4069-4070. In production Slack uploads, consumers gating on this confirmation will see “zero attachments confirmed” even after successful uploads.
Useful? React with 👍 / 👎.
Post-merge review of PR #117 caught that _MessageHistoryCache.append in chat.py did not null out raw before persisting (unlike its sibling MessageHistoryCache.append in message_history.py, which already does). Without this, the platform raw payload (Slack team_id/user_id, Discord guild IDs, etc.) that #117 now correctly populates on SentMessage.raw would persist to Redis/Postgres-backed state on every reply, inflating storage size and PII surface. Mirrors the null-out in message_history.py:62.
Problem — consistency gap
Slack is the only file-capable adapter that discards upload confirmation.
SlackAdapter._upload_filescallsfiles_upload_v2separately and already computes the list of Slack-confirmed file IDs, butpost_messagethrew that return away, andThreadImpl._create_sent_messagehardcodedraw=None— so the confirmation never reached theSentMessagereturned to callers.discord and telegram don't have this gap: they upload inline, so their
RawMessage.rawis the real platform response and flows through naturally.SentMessagealready has arawfield; it was simply never populated on thepost()path.Changes
src/chat_sdk/adapters/slack/adapter.py—post_message:_upload_files' return (uploaded_file_ids)._augment_raw_with_uploadshelper adds an"uploaded_file_ids"key toRawMessage.rawon every return path that can carry files (file-only early return, card, table, text). The Slack response dict is augmented, never replaced — Slack never returns that key, so it's additive and non-breaking.None= no upload occurred; an empty list = Slack confirmed zero attachments (a real signal, preserved by guarding onis not None).src/chat_sdk/thread.py:_create_sent_messagegains araw: Any = Noneparameter and setsraw=rawon the returnedSentMessage(was hardcodedNone).post()call site passesraw_msg.rawthrough. Platform-agnostic — discord/telegram real platform responses now flow through toSentMessage.rawtoo, which is the intended use of the field.Why now
Unblocks a chinchill consumer that needs to gate UX on actual Slack delivery success (how many files Slack confirmed attaching), not just how many were requested.
An upstream
vercel/chatissue is being filed in parallel for convergence (same gap exists inpackages/adapter-slack/src/index.ts).Test plan
uv run pytest tests/ -q→ 4046 passed, 3 skipped (was ~4042; +4 new).tests/test_slack_api.py: file-only post surfaces confirmed IDs; text+files augments thechat_postMessageraw; text-only does not add the key.tests/test_thread_faithful.py: end-to-endpost()propagatesRawMessage.raw→SentMessage.raw.uv run ruff format+uv run ruff checkclean.0.4.29a1→0.4.29a2; CHANGELOG entry added.🤖 Generated with Claude Code
Summary by CodeRabbit
Release
Bug Fixes
Tests