feat(cli): add send-attachment and send-remote-attachment commands#1707
feat(cli): add send-attachment and send-remote-attachment commands#1707
Conversation
🦋 Changeset detectedLatest commit: b1a83d6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Add
|
55645bd to
5f7a732
Compare
5f7a732 to
1c8c7f7
Compare
1c8c7f7 to
982a57c
Compare
Add file attachment support to the CLI: - conversation send-attachment: reads a file from disk and sends it. Small files (≤1MB) are sent inline; large files are automatically encrypted and uploaded via a configured upload provider, then sent as a remote attachment. - conversation send-remote-attachment: sends a reference to a pre-uploaded encrypted file with the required decryption keys. - Pluggable upload provider system with Pinata (IPFS) as the first built-in provider. Configured via XMTP_UPLOAD_PROVIDER and XMTP_UPLOAD_PROVIDER_TOKEN env vars or per-command flags. - --encrypt flag for manual workflows: encrypts the file and outputs decryption keys without sending, so users can upload to their own hosting and use send-remote-attachment. - Auto-detects MIME type from file extension (26 types supported), with --mime-type override. - Updated README.md and SKILL.md with attachment documentation.
982a57c to
b1a83d6
Compare
| ); | ||
| } | ||
|
|
||
| const encryptedBytes = new Uint8Array(await response.arrayBuffer()); |
There was a problem hiding this comment.
🟡 Medium
conversation/download-attachment.ts:165 Suggestion: Avoid buffering entire remote attachments in memory via arrayBuffer(). Stream response.body to disk (e.g., with pipeline) for large files, or document size limits if buffering is acceptable.
🚀 Want me to fix this? Reply ex: "fix it for me".
🤖 Prompt for AI
In file packages/xmtp-cli/src/commands/conversation/download-attachment.ts around line 165:
Suggestion: Avoid buffering entire remote attachments in memory via `arrayBuffer()`. Stream `response.body` to disk (e.g., with `pipeline`) for large files, or document size limits if buffering is acceptable.
| flags.output ?? | ||
| attachment.filename ?? | ||
| `${messageId.slice(0, 16)}${getExtension(mimeType)}`; | ||
| const outputPath = isAbsolute(filename) ? filename : join(cwd(), filename); |
There was a problem hiding this comment.
🟠 High
conversation/download-attachment.ts:137 Suggestion: Sanitize filenames from message metadata before building the output path to prevent path traversal. Extract only the basename (e.g., using path.basename) for attachment.filename, remote.filename, and decrypted.filename.
🚀 Want me to fix this? Reply ex: "fix it for me".
🤖 Prompt for AI
In file packages/xmtp-cli/src/commands/conversation/download-attachment.ts around line 137:
Suggestion: Sanitize filenames from message metadata before building the output path to prevent path traversal. Extract only the basename (e.g., using `path.basename`) for `attachment.filename`, `remote.filename`, and `decrypted.filename`.
| }), | ||
| }; | ||
|
|
||
| const content = await readFile(args.file); |
There was a problem hiding this comment.
🟡 Medium
conversation/send-attachment.ts:132 Reading the entire file into memory with readFile may cause OOM for very large files despite the docs suggesting support for large videos. Consider documenting a practical file size limit, or using streaming reads for the upload path.
🚀 Want me to fix this? Reply ex: "fix it for me".
🤖 Prompt for AI
In file packages/xmtp-cli/src/commands/conversation/send-attachment.ts around line 132:
Reading the entire file into memory with `readFile` may cause OOM for very large files despite the docs suggesting support for large videos. Consider documenting a practical file size limit, or using streaming reads for the upload path.
Summary
Add file attachment support to the XMTP CLI with two new commands and a pluggable upload provider system.
New Commands
conversation send-attachment— Read a file from disk and send it to a conversation.AttachmentmessagesRemoteAttachmentmessages--encryptflag for manual workflows: encrypts the file and outputs decryption keys without sending--remoteflag to force remote upload even for small files--mime-typeoverrideconversation send-remote-attachment— Send a reference to a pre-uploaded encrypted file with the required decryption keys (content-digest, secret, salt, nonce, content-length).Upload Provider System
Pluggable provider interface for uploading encrypted attachments. Providers are configured via env vars or per-command flags:
Or per-command:
Built-in provider: Pinata (IPFS) — Uploads encrypted payload to IPFS via Pinata's pinning API, returns a public gateway URL.
Adding new providers (S3, Cloudflare R2, etc.) requires adding a single factory function to
PROVIDER_FACTORIESinupload.ts.Files Changed
src/commands/conversation/send-attachment.tssrc/commands/conversation/send-remote-attachment.tssrc/utils/upload.tssrc/utils/config.tsREADME.mdSKILL.mdTesting
--encryptmode tested end-to-end (file encryption + key output)