Skip to content

feat(line): add file message type download support#27787

Closed
carrotRakko wants to merge 2 commits into
openclaw:mainfrom
delight-co:fix/line-media-file-download-and-sandbox-path
Closed

feat(line): add file message type download support#27787
carrotRakko wants to merge 2 commits into
openclaw:mainfrom
delight-co:fix/line-media-file-download-and-sandbox-path

Conversation

@carrotRakko

@carrotRakko carrotRakko commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

LINE's file message type (PDFs, documents, etc.) is not handled by the inbound media download logic — only image, video, and audio are checked. This means file attachments sent via LINE are silently dropped.

Additionally, downloadLineMedia() saves all media to /tmp/openclaw/ via buildRandomTempFilePath(), but stageSandboxMedia() only allows files under ~/.openclaw/media/. This means sandboxed agents cannot access any LINE-downloaded media (image/video/audio/file).

Changes

  • src/line/bot-handlers.ts: add message.type === "file" to the media download condition; pass message.fileName for file-type messages
  • src/line/download.ts: switch from buildRandomTempFilePath() + fs.writeFile to saveMediaBuffer() (matching Telegram/Discord/Signal); extract Content-Type from LINE API response headers via getMessageContentWithHttpInfo; add originalFilename parameter
  • src/line/download.test.ts: update tests for saveMediaBuffer mock-based approach

Closes #27722

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

@greptile-apps

greptile-apps Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Added LINE file message support (PDF, PPTX, etc.) and fixed sandbox media access by migrating from /tmp/openclaw/ to ~/.openclaw/media/inbound/.

Key changes:

  • Extended media download condition in bot-handlers.ts to include message.type === "file" alongside existing image/video/audio types
  • Refactored download.ts to use centralized saveMediaBuffer() function (matching Telegram/Discord/Signal patterns) instead of custom file handling
  • Removed ~70 lines of manual content type detection logic, now delegated to shared detectMime() utility
  • Tests updated to verify saveMediaBuffer integration with correct parameters (buffer, contentType, "inbound" subdir, maxBytes)

Architecture improvement:
The change consolidates LINE media handling with other messaging channels. All channels (Telegram/Discord/Signal/LINE) now use the same saveMediaBuffer() function with the "inbound" subdirectory, ensuring consistent behavior and sandbox compatibility.

Confidence Score: 5/5

  • Safe to merge with high confidence — focused bug fix with proven implementation pattern
  • This PR earns a 5/5 confidence score because: (1) changes are minimal and well-scoped to LINE media handling, (2) implementation uses the proven saveMediaBuffer() pattern already used by Telegram, Discord, and Signal, (3) comprehensive test coverage with 3 updated tests verifying correct integration, (4) maintains existing security (streaming size checks, secure file paths via UUID), (5) production-verified by the author, and (6) no breaking changes or risky refactoring — the streaming size validation remains in place as a performance optimization before the saveMediaBuffer() safety check
  • No files require special attention

Last reviewed commit: 8987da8

@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from c1d9415 to 8987da8 Compare February 26, 2026 17:27
@bmendonca3

Copy link
Copy Markdown
Contributor

Nice improvement moving LINE downloads into saveMediaBuffer(...) for sandbox-safe storage.

One follow-up: downloadLineMedia() now calls saveMediaBuffer(buffer, undefined, "inbound", maxBytes) without originalFilename. For message.type === "file", passing the LINE filename would preserve extension/provenance and improve downstream media handling/debuggability.

@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from 8987da8 to 692f8e2 Compare February 27, 2026 02:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 692f8e23d1

ℹ️ 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".

Comment thread src/line/download.ts Outdated
const ext = getExtensionForContentType(contentType);
// Save to ~/.openclaw/media/inbound/ so sandbox can access the file.
// Previously saved to /tmp/openclaw/ which was outside the sandbox root.
const saved = await saveMediaBuffer(buffer, undefined, "inbound", maxBytes);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass LINE file metadata into media storage

This call always passes undefined content type (and no filename) into saveMediaBuffer, so LINE file uploads lose their original MIME/extension hints and rely only on byte sniffing. For common cases like plain text/CSV (often not sniffed) or ZIP-container office files (sniffed generically), the saved attachment can end up as unknown or generic type; later normalization falls back to application/octet-stream, and file extraction logic treats that as binary and skips parsing. As a result, some LINE file messages are downloaded but still unusable to the agent; pass available LINE file metadata (e.g., filename and content type/header when present) through this path.

Useful? React with 👍 / 👎.

This comment was marked as spam.

@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from 692f8e2 to 20e2252 Compare February 27, 2026 17:19
@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from 897f5ac to 21c35d9 Compare March 1, 2026 10:30

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21c35d9150

ℹ️ 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".

Comment thread src/line/download.ts
const filePath = buildRandomTempFilePath({ prefix: "line-media", extension: ext });
// Save to ~/.openclaw/media/inbound/ so sandbox can access the file.
// Previously saved to /tmp/openclaw/ which was outside the sandbox root.
const saved = await saveMediaBuffer(buffer, contentType, "inbound", maxBytes, originalFilename);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve extension-based MIME hints for LINE file uploads

Passing originalFilename into saveMediaBuffer here still drops the filename extension during MIME resolution, because saveMediaBuffer/detectMime only use buffer+header unless a filePath hint is provided. For ZIP-container Office uploads (.docx/.xlsx/.pptx), detectMime can collapse to application/zip (its own comment calls out the XLSX-vs-ZIP case), and media-understanding/apply.ts treats ZIP as binary and skips text extraction, so these LINE file messages remain downloaded but unusable to the agent.

Useful? React with 👍 / 👎.

This comment was marked as spam.

@carrotRakko

This comment was marked as spam.

@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from 31119eb to c458134 Compare March 2, 2026 04:45

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c458134d01

ℹ️ 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".

Comment thread src/line/bot-handlers.ts
Comment on lines +236 to +240
message.type === "image" ||
message.type === "video" ||
message.type === "audio" ||
message.type === "file"
) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Save LINE file downloads under media directory

Adding message.type === "file" here routes LINE file events through downloadLineMedia, but in this commit that helper still writes to buildRandomTempFilePath (src/line/download.ts:42), i.e. /tmp/openclaw/... rather than the inbound media store. In sandboxed runs, stageSandboxMedia only stages local attachments from getMediaDir() and explicitly skips paths outside that root (src/auto-reply/reply/stage-sandbox-media.ts:106-115), so these newly-downloaded file attachments are dropped before the agent can read them.

Useful? React with 👍 / 👎.

This comment was marked as spam.

Mitsuyuki Osabe added 2 commits March 3, 2026 04:48
LINE's file message type (PDFs, documents, etc.) was not handled
by the inbound media download logic. This adds "file" to the
existing image/video/audio check so file attachments are
downloaded and passed to the agent.

The previous version of this PR also included media sandbox path
fixes and MIME detection improvements, but upstream has since
landed equivalent changes (buildRandomTempFilePath + detectContentType).
This commit now only contains the file type addition.

Closes openclaw#27722

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
downloadLineMedia() was saving to /tmp/openclaw/ via buildRandomTempFilePath(),
but stageSandboxMedia() only allows files under ~/.openclaw/media/. This meant
all LINE media downloads (image/video/audio, and now file) were inaccessible
to sandboxed agents.

Switch to saveMediaBuffer() (matching Telegram/Discord/Signal), extract
Content-Type from LINE API response headers, and pass message.fileName
for file-type messages to improve MIME detection.

✍️ Author: Claude Code (Reizan Container) with osabe
@delight-ai-agent
delight-ai-agent force-pushed the fix/line-media-file-download-and-sandbox-path branch from 03f5420 to 0ec4545 Compare March 3, 2026 04:48
@Takhoffman

Copy link
Copy Markdown
Contributor

Superseded by #32546, which consolidates this LINE workstream into the merged canonical fix set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Support LINE file message type (PDF, etc.) in inbound media download

3 participants