feat(agent): generate file download cards in chat via appendFilePart#810
Conversation
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
Adds infrastructure for agent-generated files (PDF, DOCX, PPTX, XLSX, images, text) to appear as interactive download cards in the chat UI instead of markdown links. - Add appendFilePart helper that saves a file part on the current assistant message using the SDK's promptMessageId (the ToolCtx type declares messageId but the runtime sets promptMessageId) - Add appendGeneratedFilePart internalAction using saveMessage to persist the file part at the same message order as the text response - Call appendFilePart in all 6 generate tool handlers after success - Replace downloadUrl in tool results with '[file card shown in chat]' so the model never sees a real URL to link in its response - Fix text tool schema: z.discriminatedUnion generates type None JSON schema which OpenAI rejects; converted to flat z.object with optional fields (consistent with all other tools) - Update file agent instructions: remove contradicting include download URL rule that overrode the do not link instruction
1bd3aa4 to
efcf3fd
Compare
📝 WalkthroughWalkthroughThis PR integrates file parts into chat messages across multiple file generation tools. A new helper function Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip Migrating from UI to YAML configuration.Use the |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@services/platform/convex/agent_tools/files/helpers/append_file_part.ts`:
- Around line 28-31: The current early return in appendFilePart (when threadId
or promptMessageId are missing) silently no-ops; change appendFilePart to return
an explicit status (e.g., Promise<boolean>) and replace the early "return" with
"return false" so callers can handle fallback deterministically; update the
function signature and all internal return paths to return true on success and
false on this precondition failure, and update callers to only mask downloadUrl
when appendFilePart(...) returns true (or handle false by throwing/using a
fallback) — refer to appendFilePart, threadId, promptMessageId, and the calling
sites that currently mask downloadUrl.
In `@services/platform/convex/agent_tools/files/internal_mutations.ts`:
- Around line 30-44: Duplicate construction of the assistant file-part payload
should be extracted into a single helper to avoid drift; create a small function
(e.g., buildAssistantFileMessage or buildFileContent) in internal_mutations.ts
that accepts filename, mimeType, and downloadUrl and returns the message.content
array/object currently inlined, then replace the duplicated inline payloads used
in the saveMessage calls (the block around saveMessage(...) at lines matching
the first occurrence and the second occurrence around 77-91) to call this helper
so both actions share the same construction logic.
In `@services/platform/convex/agent_tools/files/text_tool.ts`:
- Around line 126-132: The validation for generate currently throws before the
generate try/catch (checks on args.filename and args.content), causing uncaught
exceptions; instead, move these validations into the same try block used for
generation (or replace the throws with returning a structured TextGenerateResult
error) so missing args produce a TextGenerateResult with an error payload
consistent with the parse path; update the code paths referencing operation ===
'generate' and args to either perform the checks inside the try around the
generate logic or construct and return the TextGenerateResult error object when
validation fails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 16d9fbe2-416d-43c5-8027-b74a8b905bb9
⛔ Files ignored due to path filters (1)
services/platform/convex/_generated/api.d.tsis excluded by!**/_generated/**
📒 Files selected for processing (9)
services/platform/convex/agent_tools/files/docx_tool.tsservices/platform/convex/agent_tools/files/excel_tool.tsservices/platform/convex/agent_tools/files/helpers/append_file_part.tsservices/platform/convex/agent_tools/files/image_tool.tsservices/platform/convex/agent_tools/files/internal_mutations.tsservices/platform/convex/agent_tools/files/pdf_tool.tsservices/platform/convex/agent_tools/files/pptx_tool.tsservices/platform/convex/agent_tools/files/text_tool.tsservices/platform/convex/agents/file/agent.ts
Summary
appendFileParthelper andappendGeneratedFilePartinternalAction to save agent-generated files as downloadable cards in the chat message (usingpromptMessageIdfrom ToolCtx runtime, not the incorrectly-typedmessageId)appendFilePartin all 6 file tool generate handlers (pdf, docx, pptx, excel, image, text)downloadUrlin tool results with'[file card shown in chat]'so the model has no real URL to link in its responsetexttool:z.discriminatedUnionproducestype: "None"JSON schema rejected by OpenAI — converted to flatz.objectwith optional fields (same pattern as all other tools; added comment explaining why)Test plan
texttool in Convex logs🤖 Generated with Claude Code
Summary by CodeRabbit